Deploy MySQL with YAML

Deploy a managed MySQL instance on Bahriya with a Reis YAML manifest: tiers, plans, databases and users, tuning, TLS, external access and a full field reference.

Updated 22 Oct 20264 min read

A managed MySQL instance lives inside a project and is reachable from any container in that project — a relational database with one or more logical databases, each owned by its own user. For the concepts, see the MySQL overview.

This guide covers the YAML shape. For the flag-mode equivalent, see Deploy MySQL with flags.

Minimal example

kind: mysql
project: my-project
handle: orders-db
name: Orders DB
tier: single
cpu: 1000
memory: 2048
regions:
  - falkenstein-1
databases:
  - name: orders
    username: orders-app
persistence:
  storage: 20

Apply it:

reis apply -f orders-db.yml

That gets you a single-node MySQL instance on the 1 vCPU / 2 GB plan with 20 GB of storage and one database. cpu and memory must be one of the published plan pairs (see the overview).

Read replicas, several databases and tuning

kind: mysql
project: my-project
handle: shop-db
name: Shop DB
tier: replicated
cpu: 2000
memory: 8192
regions:
  - falkenstein-1
databases:
  - name: catalog
    username: catalog-app
  - name: reporting
    username: reporting-ro
 
topology:
  replicas: 2             # read replicas: 1 or 2
 
persistence:
  storage: 100            # GB per node, grow-only
 
tuning:
  config:
    max_connections: 500
    slow_query_log: true
 
backup:
  backup_schedule: "0 3 * * *"

Highly available, encrypted and externally reachable

kind: mysql
project: my-project
handle: ledger-db
name: Ledger DB
tier: ha
cpu: 4000
memory: 16384
regions:
  - falkenstein-1
databases:
  - name: ledger
    username: ledger-app
 
topology:
  replicas: 3             # group members including the primary: 3 or 5
 
persistence:
  storage: 250
 
security:
  encryption: true        # set at creation only
  volume_encryption: true # billed add-on, set at creation only
  tls: true
 
exposure:
  external: true
  allowed_ips:
    - 198.51.100.0/24
 
client:
  phpmyadmin: true
  phpmyadmin_ttl: 8       # hours, then it switches off

External access requires TLS and a non-empty allowlist. The connection port is allocated by the platform — read it with reis mysql:show <id> once applied.

Field reference

YAML pathDescriptionDefault
tiersingle, replicated or ha — fixed at creationrequired
cpuCPU per node in millicores — a plan pair with memoryrequired
memoryMemory per node in MB — a plan pair with cpurequired
regionsRegions to deploy to — each runs an independent copy with its own datarequired
databasesList of {name, username}; at least onerequired
persistence.storageData storage per node in GB, 5–250, grow-onlyrequired
topology.replicasreplicated: 1 or 2 read replicas. ha: 3 or 5 members1 / 3
tuning.configSupported mysqld settings (see the overview)—
backup.backup_scheduleCron schedule for the database dumps — backups are always onplatform default
security.encryptionMySQL encryption at rest (tables, redo/undo logs, binary logs) — set at creation only. See Encryption at restfalse
security.volume_encryptionBilled add-on: also encrypt every disk of the instance — set at creation onlyfalse
security.tlsServe MySQL-native TLSfalse
security.tls_bundleHandle of your own TLS bundle to serveplatform-managed
security.tls_validity_yearsLifetime of the platform-managed server certificate: 1, 3, 5 or 10 years. Renewed 30 days before expiry, always from the same CA (a new CA only with reis mysql:replace-ca)3
exposure.externalExpose at the platform edge on an allocated portfalse
exposure.allowed_ipsCIDR allowlist — required for external access and phpMyAdmin—
exposure.hostnamesCustom hostnames (- hostname: db.example.com)—
client.phpmyadminRun phpMyAdmin over HTTPSfalse
client.phpmyadmin_ttlHours until phpMyAdmin switches off, 1–16824
networking.network_policiesNetwork policies narrowed to this instance, by handle—

Passwords are never part of the file. Reveal or rotate them with reis mysql:credentials.

Updating an instance

Re-apply the same file with any changes:

reis apply -f orders-db.yml

Moving to another plan, growing storage, adding a database or changing tuning all happen the same way; Reis matches by handle. tier, security.encryption and security.volume_encryption cannot change — they need a new instance.

Removing an entry from databases drops that database and its user, with all their data, in every region. Double-check the list before you apply.

To capture an existing instance as a file, export it and re-apply it later:

reis export mysql <instance-id> -f orders-db.yml

Restoring to a point in time

A restore is an action, not a file to apply: start it with reis mysql:restore (see Deploy MySQL with flags) or from the console. It creates a new instance and never changes the one described by your file.