---
title: "MySQL Protocol Configuration"
---

# MySQL Protocol Configuration

The MySQL listener of HeliosDB Full is configured with `heliosdb-full` startup flags
and environment variables. There is no `[mysql]` section in the config file: the server
reads only `[storage]` keys from it and refuses to start when a file sets keys it does
not honour.

## Enabling the listener

| Setting | Flag | Environment variable | Default |
|---------|------|----------------------|---------|
| Enable | `--enable-mysql` | — | off |
| Port | `--mysql-port` | `HELIOSDB_MYSQL_PORT` | 3306 |
| Bind address (all listeners) | `--bind-addr` | `HELIOSDB_BIND_ADDR` | `127.0.0.1` |
| Allow a non-loopback bind | `--allow-external` | `HELIOSDB_ALLOW_EXTERNAL` | off |
| Connections (all listeners) | `--max-connections` | `HELIOSDB_MAX_CONNECTIONS` | 10000 |
| New connections per client IP | `--conn-rate-limit` | `HELIOSDB_CONN_RATE_LIMIT` | 500 per minute |

```bash
heliosdb-full --data-dir /var/lib/heliosdb --enable-mysql
# MySQL protocol listening on 127.0.0.1:3306

# Another port, reachable from a private network
heliosdb-full --data-dir /var/lib/heliosdb --enable-mysql --mysql-port 3307 \
  --bind-addr 10.0.0.12 --allow-external
```

In a container, append `--enable-mysql` after the image name and publish the port
(`-p 127.0.0.1:3306:3306`).

## Authentication

The MySQL listener looks users up in the server's role catalog, the same roles
PostgreSQL clients log on with:

- the built-in superuser `postgres`
- roles created over PostgreSQL: `CREATE ROLE app LOGIN PASSWORD '...'`

Clients may use the `caching_sha2_password` (MySQL 8 default) or
`mysql_native_password` plugin; other plugins are refused. Unknown users and empty
passwords are refused. `--auth-mode trust` does not apply to this listener.

:::caution[Passwords are not verified yet]
In the current release the listener checks only that the role exists and that the
client sent a non-empty password. It does not yet verify the password against the
role's password, so any non-empty password logs on as an existing role, including
`postgres`. Until password verification is available:

- bind the server to loopback (the default) or a private network segment where every
  client is trusted, and firewall port 3306;
- do not expose `--enable-mysql` to untrusted networks;
- use the PostgreSQL listener (SCRAM-SHA-256, optional TLS) wherever authentication
  matters.
:::

## TLS

The MySQL listener does not offer TLS. Keep it on loopback or a private network and
restrict port 3306 with a firewall, or reach it through an SSH or TLS tunnel. Clients
that require TLS (`--ssl-mode=REQUIRED`) cannot connect; the default `PREFERRED` mode
connects without it.

## Connecting

```bash
mysql -h 127.0.0.1 -P 3306 -u app -p postgres
```

```python
import os, pymysql
conn = pymysql.connect(host="127.0.0.1", port=3306, user="app",
                       password=os.environ["APP_PASSWORD"], database="postgres")
```

```java
String url = "jdbc:mysql://127.0.0.1:3306/postgres?sslMode=DISABLED";
Connection conn = DriverManager.getConnection(url, "app", System.getenv("APP_PASSWORD"));
```

Statements run on the same SQL engine as the PostgreSQL listener and see the same
tables. MySQL-specific functions and syntax may need small changes; test your
application's statements against a non-production server.

## Related

- [Connecting](/docs/full/guides/user/connecting/)
- [Server Configuration Reference](/docs/full/reference/configuration/)
