Connecting to MySQL

Connecting to managed MySQL on Bahriya: the in-project endpoint on port 3306, database users and passwords, read replicas, and TLS.

Updated 22 Oct 20264 min read

Any MySQL client library, ORM or tool connects to a Bahriya MySQL instance unchanged.

The in-project endpoint

Containers in the same project reach the instance at its handle on port 3306:

<mysql-handle>:3306

Pass it to your application as environment variables or a connection URL:

DATABASE_URL=mysql://orders-app:<password>@orders-db:3306/orders

Access is restricted to the project by network isolation; an instance is never reachable from other projects. To reach an instance from outside the platform, see External access.

Read replicas

replicated and ha instances also answer at a read-only endpoint:

<mysql-handle>-readonly:3306

On a replicated instance it spreads reads across the read replicas, which apply writes asynchronously and can trail the primary by a moment. Send reads that must see a write you just made to the primary endpoint; send the rest to -readonly. Writes always go to the primary endpoint.

Users and passwords

Each database you declare has its own user, granted on that database only. The platform also creates a root user for administration. Every password is generated by the platform:

  • It is never returned when you read the instance — not by the API, Reis or Terraform.

  • Reveal it from the instance's detail page in the console, or with Reis:

    reis mysql:credentials <instance-id> --username orders-app
    reis mysql:credentials <instance-id>                 # root
  • Rotate it the same way. Rotation generates a new password and updates the instance to use it; clients still using the old password fail to connect until they are given the new one.

    reis mysql:credentials <instance-id> --username orders-app --rotate

Revealing and rotating are recorded in the activity log. Give applications their database user, not root.

Where the passwords are kept

The passwords live in your vault as platform-managed secrets, attached to the instance's project: <handle>-mysql-root for root and <handle>-mysql-<database> for each database user (an underscore in a database name becomes a hyphen). Because they are attached, a container in the project can reference a password like any other vault secret instead of copying it. They are billed like any secret. You cannot edit, rotate, detach or delete them directly: rotate through the instance as above, and they are released when the database is removed or the instance terminated. root cannot be used as a database name, because its secret handle belongs to the root password.

TLS

With TLS enabled on the instance, clients can connect encrypted and verify the server's identity. Verifying needs the CA certificate that signed the server's certificate, passed as a file:

mysql --host orders-db --user orders-app -p \
  --ssl-mode=VERIFY_IDENTITY --ssl-ca=orders-db-ca.pem orders

TLS is optional inside the project and required for external access.

Getting the CA certificate

Unless you supply your own bundle, the platform issues the instance a TLS bundle in your vault, named <handle>-tls. Its CA certificate is public, so you can copy or download it:

  • Console: open Vaults → TLS bundles, view <handle>-tls, and download the CA certificate. The instance's page links straight to it.
  • Reis: reis tls_bundle:show <handle>-tls --ca > orders-db-ca.pem saves the CA certificate, and nothing else, to a file.
  • Terraform: the bahriya_tls_bundle data source exposes it as ca.

Pass the file to your client with --ssl-ca (or your driver's equivalent). Do not install it in your operating system's trust store; it is meant for this instance only.

Certificate lifetime and renewal

Choose how long each server certificate lasts with tlsvalidityyears: 1, 3, 5 or 10 years, 3 by default. The platform renews it automatically 30 days before it expires, and issues a new one when you change the lifetime or add a hostname or region. Every one of these is signed by the same CA, which lasts 30 years, so the CA file your clients saved keeps working. Instances do not restart to pick up a renewed certificate.

If you supply your own bundle, you renew it yourself.

Replacing the CA

Because renewals keep the CA, you only get a new one by asking for it, for example if a copy of the CA file was exposed. Replace it from the instance's page in the console (Replace CA), or with:

reis mysql:replace-ca <instance-id>

The platform issues a new CA and server certificate for the same names and lifetime and applies them without a restart. From that moment, every client that verifies the server with the old CA file fails to connect until you give it the new one, so get the new CA certificate as described above and roll it out straight away. The replacement is recorded in your activity log.

Multi-region applications

Each region runs an independent copy of the instance, and the in-project endpoint always resolves to the copy in the container's own region. The same handle works everywhere; there is no replication between the copies.

Connection limits

The default max_connections is 151 per node. If your application runs many replicas with connection pools, raise it in the instance's tuning settings (up to 5000) or size the pools down — and choose a plan with the memory to match.