Deployment guide

MySQL Router

Overview

MySQL Router is Oracle's official lightweight connection proxy for MySQL. It gives applications a single stable endpoint and routes each connection to a healthy backend. It is the standard connection tier in front of a MySQL InnoDB Cluster or replica set.

This SecureAnyCloud image installs MySQL Router 8.4 from Oracle's official APT repository on Ubuntu 24.04 LTS (Noble Numbat). It also bundles a MySQL 8.4 LTS Community server as the default backend, so the appliance routes live traffic as soon as it boots.

What you get:

  • MySQL Router 8.4 from Oracle's official APT repository
  • A bundled MySQL 8.4 LTS Community server as the default backend
  • Four routing listeners: classic and X protocol, each with a read/write and a read-only port
  • A unique MySQL root password and a unique application-user password, generated automatically on first boot, with no credential baked into the image

Topology

The image ships a self-contained routing tier. Use it immediately, then re-point it at your own database in production.

Listener Port Bind Routes to

Classic protocol, read/write 6446 0.0.0.0 MySQL 127.0.0.1:3306

Classic protocol, read-only 6447 0.0.0.0 MySQL 127.0.0.1:3306

X protocol, read/write 6448 0.0.0.0 MySQL 127.0.0.1:33060

X protocol, read-only 6449 0.0.0.0 MySQL 127.0.0.1:33060

The bundled MySQL server is bound to loopback (127.0.0.1) and is reachable only through the router. MySQL authentication is the security gate: each VM has its own password, and anonymous login is not allowed.

In production, you point the router at your own MySQL server or InnoDB Cluster. This is a configuration change, not a boot dependency.

Prerequisites

  • An Azure subscription with permission to create virtual machines
  • An SSH key pair, whose public key you upload during VM creation
  • A MySQL client installed locally, if you want to connect from your workstation

Step 1 - Deploy from the Azure Portal

  • Find MySQL Router 8.4 on Ubuntu 24.04 by SecureAnyCloud in the Azure Marketplace and select Create.
  • On the Basics tab, select or create a resource group, choose East US as the region, and set the VM size to Standard_B2s (2 vCPU / 4 GB RAM) or larger.
  • Under Administrator account, choose SSH public key and paste your public key.
  • On the Networking tab, open the router ports you intend to use, in addition to 22 (SSH). Use 6446 (read/write) and 6447 (read-only) for the classic protocol, and 6448 and 6449 for the X protocol. Restrict the source to your application subnet.
  • Select Review + create, then Create.

Step 2 - Deploy with the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:mysql-router:default:latest
az vm create \
  --resource-group <your-resource-group> \
  --name mysql-router \
  --image sac1647283583153:mysql-router:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_rsa.pub \
  --public-ip-sku Standard

When the VM is running, open the router read/write port:

az vm open-port --port 6446 --resource-group <your-resource-group> --name mysql-router

Step 3 - Connect over SSH

ssh azureuser@<vm-ip>

On first boot, mysql-router-firstboot.service starts the backend MySQL server and generates the per-VM root and application passwords. It also creates the default SecureAnyCloud database and the sac_app user, then starts MySQL Router.

Allow 30-60 seconds for the service to finish before you connect.

Step 4 - Retrieve your credentials

sudo cat /stage/scripts/mysql-router-credentials.log

The file is owned by root:root with mode 0600. It lists the generated passwords, the router ports and ready-to-use connect commands. Store the passwords somewhere safe before you rotate them.

Step 5 - Verify the routing topology

Confirm that both services are active, then inspect the listening ports. The router listens on 0.0.0.0, while the backend MySQL server listens on loopback only.

systemctl is-active mysql mysqlrouter
sudo ss -tlnp | grep -E ':(3306|33060|6446|6447|6448|6449) '

Step 6 - Connect through the router

Connect to the router read/write port (6446) with the generated application password. Write a sentinel row, then read it back. The row records the backend port the connection actually reached, which proves the traffic went through the router.

APP_USER=$(sudo awk -F= '/^app_user=/{print $2}' /stage/scripts/mysql-router-credentials.log)
APP_PASS=$(sudo awk -F= '/^app_password=/{print $2}' /stage/scripts/mysql-router-credentials.log) MYSQL_PWD="$APP_PASS" mysql -u "$APP_USER" -h 127.0.0.1 -P 6446 sac --table <<'SQL' CREATE TABLE IF NOT EXISTS demo (id INT PRIMARY KEY AUTO_INCREMENT, note VARCHAR(64), via_port INT, backend_port INT); INSERT INTO demo (note, via_port, backend_port) VALUES ('hello via router', 6446, @@port); SELECT note, via_port AS connected_to_router_port, backend_port AS mysql_server_port FROM demo ORDER BY id DESC LIMIT 1; SQL

You connected to the router on 6446, but the backend reports its port as 3306. The connection was routed through MySQL Router to the MySQL server behind it.

Step 7 - Use the read-only port and inspect the router log

Read the same data back over the router's read-only port (6447). Then confirm that the router logged that it is accepting connections on each routing port.

APP_USER=$(sudo awk -F= '/^app_user=/{print $2}' /stage/scripts/mysql-router-credentials.log)
APP_PASS=$(sudo awk -F= '/^app_password=/{print $2}' /stage/scripts/mysql-router-credentials.log) MYSQL_PWD="$APP_PASS" mysql -u "$APP_USER" -h 127.0.0.1 -P 6447 sac --table \
  -e "SELECT note, via_port, backend_port FROM demo ORDER BY id DESC LIMIT 3;"
sudo grep 'Start accepting' /var/log/mysqlrouter/mysqlrouter.log | tail -4

Step 8 - Point the router at your own MySQL or InnoDB Cluster

In production, the router fronts your own database. Edit the destinations in /etc/mysqlrouter/mysqlrouter.conf and restart the service. For a single server, change the destinations lines to your host:

sudo sed -i 's#destinations=127.0.0.1:3306#destinations=<your-mysql-host>:3306#' /etc/mysqlrouter/mysqlrouter.conf
sudo sed -i 's#destinations=127.0.0.1:33060#destinations=<your-mysql-host>:33060#' /etc/mysqlrouter/mysqlrouter.conf
sudo systemctl restart mysqlrouter

For a MySQL InnoDB Cluster, re-bootstrap the router against the cluster. The router then tracks membership and failover automatically. Bootstrapping rewrites mysqlrouter.conf with a metadata cache.

sudo mysqlrouter --bootstrap <cluster-admin>@<your-mysql-host>:3306 \
  --user mysqlrouter --force sudo systemctl restart mysqlrouter

Step 9 - Manage the service

sudo systemctl status mysqlrouter --no-pager
sudo /usr/local/sbin/mysql-router-status.sh
sudo journalctl -u mysqlrouter -n 50 --no-pager

Step 10 - Security recommendations

  • Point the router at your own MySQL server or InnoDB Cluster (Step 8). Keep the bundled backend for evaluation only, or repurpose it as a production node.
  • Open only the router ports your applications need (6446/6447 for classic, 6448/6449 for X protocol). Restrict the NSG source to your application subnet.
  • Rotate the generated application password, and create least-privilege users for each application:
ROOT_PASS=$(sudo awk -F= '/^root_password=/{print $2}' /stage/scripts/mysql-router-credentials.log)
mysql -u root --password="${ROOT_PASS}" --socket=/var/run/mysqld/mysqld.sock <<SQL ALTER USER 'sac_app'@'%' IDENTIFIED WITH caching_sha2_password BY '<new-password>'; FLUSH PRIVILEGES; SQL
  • Keep the system patched with sudo apt-get update && sudo apt-get upgrade -y.

Troubleshooting

Router not accepting connections. Confirm that it is listening, then check the log:

sudo ss -tlnp | grep 6446
sudo tail -n 50 /var/log/mysqlrouter/mysqlrouter.log

Backend unreachable. The router starts even when its destination is down, and it returns errors to clients until the backend is up. Confirm that the backend MySQL server is running and reachable from the router host:

sudo systemctl status mysql --no-pager

Support

This image is provided and supported by SecureAnyCloud. For deployment questions, configuration help or bug reports, contact us at sales@secureanycloud.com.

For upstream documentation, see the MySQL Router 8.4 Reference.

Deploy on Azure

Launch mysql-router with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure