Skip to content

Host a MySQL database

Two ways to do this on MicroApps: a managed database pod, where we provision MySQL and hand you the credentials, or a regular Ubuntu pod you install MySQL on yourself. Option A is the one you want unless you have a specific reason not to, and it is what most of this tutorial covers: from an empty pods table to a mysql> prompt, with the private-network wiring done properly so your app pod can reach the database without exposing it to the internet.

Database pods have no browser Shell

The in-browser Shell is for instance pods only. The Shell button is still drawn on a running database pod, but clicking it opens a panel that says Failed to obtain console ticket instead of giving you a prompt. Connect with a MySQL client instead - steps 3 to 5 below set that up.

What you need first

  • At least $3 of credit on the account, or pod creation is refused. Check on Billing.
  • A MySQL client on the machine you'll connect from: the mysql command line, TablePlus, DBeaver, whatever you like.
  • Optionally, the app pod that will use the database. Create it in the same Region, because a pod and its private network have to share one.

Option A - a managed database pod

1. Create the pod

  1. Open Pods in the console, or click Pods in the side panel.
  2. Click New, at the top right of the pods table. You land on the Create Pod page.
  3. Workload - click the MySQL tile. (The other tile is Ubuntu, which is Option B.)
  4. Version - 8.0. The field only appears once a workload is picked, and MySQL offers 5.7 and 8.0.
  5. Compute - 1 vCPU, 1GB RAM is fine for most small apps. You can resize later from the pod's Overview tab.
  6. Pod Name (optional) - db-pod, or leave it blank and we'll generate one.
  7. Region - the same Region as your app pod. This one cannot be changed afterwards.
  8. Storage - 10 GB. Pick larger if you'll be storing more; storage grows later but never shrinks.
  9. Network (optional) - pick the private network your app pod is on. Read the note below before leaving this blank.
  10. Firewall (optional) - pick a firewall that already allows the IP you'll connect from. Read the note below before leaving this blank too.
  11. Username is filled in and greyed out, reading root. Nothing to do here.
  12. Click Create Pod.

Neither blank picker means "none"

Network (optional) blank does not give the pod a private network to itself. We put it on the oldest network you already own in that Region, and only create one if you have none there. Two pods created with the picker blank in the same Region usually land on the same network and can already reach each other, which may be exactly what you want or exactly what you don't.

Firewall (optional) blank does not leave the pod open. It gets a brand new firewall of its own that blocks all public traffic, your MySQL client included, until you add your address to it. Step 4 is how.

Both behaviours are spelled out in Networks & firewalls.

No Network or Firewall picker on the form?

They only appear once you own at least one. On a new account they are simply not there, and you get the blank behaviour above. Create a network or a firewall first if you want to choose.

2. Save the password before the toast disappears

You come back to the pods table with the pod in it. Its Status goes from Initializing to Running, usually in under a minute.

A green toast at the top right carries the generated password: "Auto-generated password: ...". It is shown once and never again. Hover over it to stop it clearing itself, and copy the password somewhere safe. The user it belongs to is root.

Missed it? That's recoverable, see Lost the password below. But copy it now and save yourself the trip.

3. Find the connection details

  1. Open Pods and click the pod's name in the table. You land on the pod's page, on the Overview tab.
  2. Click the Connection Strings tab. A MySQL pod shows two cards, each holding a whole command, ready to run:
    • Public MySQL - mysql -P 3308 -u root -h your-db.microapps.io -p, for connecting over the internet.
    • Private MySQL - mysql -P 3306 -u root -h db-pod -p, for connecting from another pod on the same private network. Your card shows a generated hostname in place of db-pod, something like d-70a1e4c6b92f3d8a5e1b7c42, so copy the card rather than typing your pod's name.
  3. Click either card to copy the command it shows.

Copying the whole line is the quick way. The individual values are labelled on the Networking tab if you need them one at a time:

ValueWhere it is
Network, Private IP and Hostname - how pods on the same network reach this oneNetworking tab, Private Network card
Firewall in force, Public Host, and Ports (two numbers, one marked private and one marked public)Networking tab, Security & Public Access card
UsernameOverview tab, Details card

Click any of those values to copy it.

There is no "public IP" anywhere in the console

From the internet you connect to a Public Host, a name, not an address. Pods in the same Region share that host, so the public port is the part that belongs to your pod alone, which is why -P is not optional. The Private IP on the Networking tab is a private-network address and is not reachable from the internet at all. Both are already assembled into the two connection strings above.

4. Let your IP through the firewall

Only needed if you're connecting from outside the private network, which includes your own laptop. Skip to step 5 if the only thing talking to this database is a pod on the same network - that traffic never passes through the firewall.

  1. On the pod's page, click the Networking tab.
  2. In the Security & Public Access card, click the firewall's name in the Firewall row. You land on that firewall's page.
  3. Click New Rule, at the top right. An Add Rule panel opens above the table.
  4. Fill in IP Address / Network with the address you are arriving from. curl ifconfig.me, run on the machine you'll connect from, prints it. 203.0.113.42/32 for a single address.
  5. Fill in Description with something you'll recognise in six months, then click Add.
  6. Click Apply Changes, at the top right. Until you do, the rule exists only in your browser and the header shows an Unsaved changes badge.

Rules take effect within seconds, no reboot.

5. Connect

From an app pod on the same network - the way you want your application doing it. Paste the Private MySQL command:

bash
mysql -P 3306 -u root -h db-pod -p

db-pod is the database pod's Hostname from its Networking tab, and 3306 is MySQL's real internal port. Same-network peers reach each other on internal ports with no mapping and no public round-trip, so there's nothing to open up.

From your own machine - handy for a one-off import or a GUI client. Paste the Public MySQL command:

bash
mysql -P 3308 -u root -h your-db.microapps.io -p

Swap in the external port and public host shown on your own pod. If it hangs and then times out, your address isn't on the firewall's allow-list yet: back to step 4.

Either way you're at a mysql> prompt as root, and CREATE DATABASE, CREATE USER and GRANT work exactly as they do anywhere else.

Lock it down

Public access is convenient but risky. Put your app pod and database pod on the same private network, and attach a firewall that allow-lists only IPs you trust. Firewall rules are per-IP and cover every public port, so everyone else loses the MySQL external port (and everything else) in one go - while your app pod keeps reaching the database over the private network, which doesn't pass through the firewall.

Lost the password

Database pods can have theirs regenerated. Ubuntu pods cannot, which is one more reason to use a managed pod.

  1. Open Pods and click the database pod's name in the table.
  2. Click the ... button at the top right of the pod's page, next to Shell.
  3. Choose Reset password from the menu, then confirm in the dialog.

A fresh password is generated and shown once, in the toast that follows. Copy it there and then. (Via the API: POST /api/pods/:id/reset-password.)

Option B - install MySQL manually

If you want full control:

  1. Create a regular Ubuntu pod (1 vCPU, 1GB RAM or larger) from New pod, following step 1 above with Workload set to Ubuntu and Version 24.04. Add an SSH key in SSH Public Key (optional) while you're there.
  2. Allow your IP through the pod's firewall, per step 4 above, then copy the Public SSH command from the pod's Connection Strings tab:
    bash
    ssh -p 3001 ubuntu@your-pod.microapps.io
  3. Install MySQL:
    bash
    sudo apt update
    sudo apt install -y mysql-server
    sudo mysql_secure_installation
  4. Bind to the IPs you want in /etc/mysql/mysql.conf.d/mysqld.cnf.
  5. Create users and databases as usual.
  6. An Ubuntu pod's only public mapping is SSH, so MySQL is not directly reachable from the internet - which for a database is a feature. Reach it from other pods on the same network via the private Hostname and 3306, or from your laptop through an SSH tunnel: ssh -p <external-port> -L 3306:localhost:3306 ubuntu@<public-host>.
  7. Lock down SSH access with a firewall.

You get the browser Shell on this one, and no Reset password in the ... menu. Connecting via SSH has the rest.

Keep a safety net

Either way, turn on an automatic snapshot schedule so you always have a recent rollback point. In the console, open the pod, click the Snapshots tab, and pick Daily in the Auto schedule dropdown. Or via the API:

http
PUT /api/pods/:id/snapshot-schedule
{ "schedule": "daily" }

schedule is "", "daily", "weekly", or "monthly" - all at 3:00 AM UTC, rotated automatically. Snapshots rewind the pod in place. For a copy that restores as a separate pod (proper disaster recovery), also set a backup schedule from the Backups tab's Auto schedule dropdown. See Schedule nightly snapshots.

Built for the long tail.