Deployment guide

MySQL 9.7 LTS

Overview

MySQL is a widely deployed open-source relational database. It is fully ACID compliant and supports stored procedures, triggers, views, window functions, CTEs, JSON columns, full-text search and multi-source replication. MySQL 9.7 is the first long-term support (LTS) release in the 9.x Innovation series, which includes atomic DDL, invisible indexes, role-based access control, hash join execution and query optimiser improvements.

This SecureAnyCloud image runs MySQL 9.7 LTS Community Server on Ubuntu 24.04 on Azure. LTS releases receive community patches and security fixes for five years, which makes 9.7 a good fit for production workloads where stability matters more than new features.

The image ships MySQL 9.7.0 installed from the official MySQL APT repository at repo.mysql.com, with the GPG key fingerprint verified at build time. The data directory is intentionally empty in the shipped image, so no password is baked in at any point.

On every fresh VM, a systemd drop-in runs mysqld --initialize-insecure before the server starts and initialises the data directory with no embedded password. Then mysql-firstboot.service generates a strong random root password unique to that VM, creates the default SecureAnyCloud database and writes the credentials to /stage/scripts/mysql-credentials.log. No two VMs ever share a root password.

What you get:

  • MySQL 9.7.0 Community Server, installed from the official MySQL APT repository
  • Listener on TCP port 3306 and X Protocol on TCP port 33060
  • mysql command-line client and standard MySQL utilities (mysqldump, mysqladmin, mysqlcheck, mysqlimport) at /usr/bin/
  • A per-VM root password generated on first boot and written to /stage/scripts/mysql-credentials.log
  • A default SecureAnyCloud database created on first boot with the utf8mb4 character set and utf8mb4_unicode_ci collation
  • Systemd service mysql.service for automatic startup on boot
  • Idempotent data directory initialisation through a mysql.service drop-in, safe across reboots and snapshots
  • Helper scripts at /usr/local/sbin/mysql-start.sh and /usr/local/sbin/mysql-stop.sh
  • 24/7 SecureAnyCloud support with a 24 hour response SLA

Prerequisites

Before you deploy this image, make sure you have:

  • An active Azure subscription
  • A subscription to the MySQL 9.7 LTS Community Server on Ubuntu 24.04 listing on Azure Marketplace
  • An SSH public key for VM authentication
  • Familiarity with Azure virtual machine management and SSH
  • A virtual network and subnet in the target region (or be ready to create one in the deploy wizard)

Recommended VM size: Standard_D2s_v3 (2 vCPU, 8 GB RAM). MySQL benefits from available RAM for the InnoDB buffer pool, and the D series provides a consistent baseline for small to medium production workloads.

For very small development or staging environments, Standard_B2s (2 vCPU, 4 GB RAM) is also sufficient.

1

Deploy the VM from the Azure Portal

Open the Azure Portal, go to the Marketplace and search for MySQL 9.7 LTS. Select the SecureAnyCloud publisher entry and click Create to start the wizard.

On the Basics tab, choose your subscription, target resource group and region, and set the VM name. Choose SSH public key as the authentication type. Set the username to a name of your choice (the examples below use azureuser) and paste your SSH public key. Standard_D2s_v3 is the recommended starting size.

On the Disks tab, set the OS disk type to Standard SSD. By default, MySQL data lives at /var/lib/mysql on the root disk. If your working set is larger than a few gigabytes, attach a separate data disk and bind mount it over /var/lib/mysql before you start the service.

On the Networking tab, select your existing virtual network and subnet. Attach a network security group that allows inbound TCP 22 from your management IP range, and inbound TCP 3306 only from application server subnets or the virtual network CIDR.

Do not expose port 3306 to the public internet. The root password is stored in plain text on the VM by design, so that you can read it without a second trip. An internet-exposed MySQL port would make brute-force attacks trivial.

The defaults on the Management, Monitoring and Advanced tabs are appropriate. Click Review + create, wait for validation to pass, then click Create. Deployment takes around two minutes.

2

Deploy the VM from the Azure CLI

To deploy from the command line, use the gallery image resource identifier as the source. The exact identifier is published on your Partner Center plan. The commands below show a typical invocation:

RG="mysql-prod" LOCATION="eastus" VM_NAME="mysql-01" ADMIN_USER="azureuser" GALLERY_IMAGE_ID="/subscriptions//resourceGroups/azure-sac/providers/Microsoft.Compute/galleries/sacGallery/images/mysql-9-7-lts-ubuntu-24-04/versions/" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create \
  --resource-group "$RG" \
  --name mysql-vnet \
  --address-prefix 10.70.0.0/16 \
  --subnet-name mysql-subnet \
  --subnet-prefix 10.70.1.0/24 az network nsg create --resource-group "$RG" --name mysql-nsg az network nsg rule create \
  --resource-group "$RG" --nsg-name mysql-nsg \
  --name allow-ssh-mgmt --priority 100 \
  --source-address-prefixes "" \
  --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create \
  --resource-group "$RG" --nsg-name mysql-nsg \
  --name allow-mysql-vnet --priority 110 \
  --source-address-prefixes 10.70.0.0/16 \
  --destination-port-ranges 3306 --access Allow --protocol Tcp az vm create \
  --resource-group "$RG" \
  --name "$VM_NAME" \
  --image "$GALLERY_IMAGE_ID" \
  --size Standard_D2s_v3 \
  --storage-sku StandardSSD_LRS \
  --admin-username "$ADMIN_USER" \
  --ssh-key-values "$SSH_KEY" \
  --vnet-name mysql-vnet --subnet mysql-subnet \
  --nsg mysql-nsg \
  --public-ip-address "" \
  --os-disk-size-gb 32

The --public-ip-address "" flag keeps the database off the public internet. To reach the VM, use a bastion host or your existing private connectivity.

3

Connect via SSH

After deployment, find the private IP of the new VM. From a host inside the same virtual network, connect over SSH:

ssh azureuser@``` The first login may take a few seconds while cloud init finalises. Once you have a shell, `mysql.service` will have already started and `mysql-firstboot.service` will have already run, generating the per VM root password and creating the `sac` database. Both services are one time operations gated by a sentinel file so they do not repeat on subsequent reboots. ## Step 4: Retrieve the Root Password The root password has been randomly generated on this specific virtual machine and written to a root only file. Read it with: ```bash
sudo cat /stage/scripts/mysql-credentials.log

The file contains lines like these:

port=3306 socket=/var/run/mysqld/mysqld.sock default_database=sac root_password= connect_command=mysql -u root -p'' -h 127.0.0.1 -P 3306

Store the value of root_password= in your secret store. You can shred the credentials file once the password is saved. Keeping it root-protected at mode 0600 is also a reasonable default for the life of the VM.

5

Connect locally with the mysql client

Export the root password and socket path as shell variables, so that you do not have to type them repeatedly:

export MYSQL_ROOT_PW="$(sudo awk -F= '/^root_password=/{print $2}' /stage/scripts/mysql-credentials.log)"
export MYSQL_SOCKET="/var/run/mysqld/mysqld.sock"

Connect to the server through the Unix socket:

mysql -u root -p"${MYSQL_ROOT_PW}" --socket="${MYSQL_SOCKET}"

The client shows a welcome banner and prompt like this:

Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 9.7.0 MySQL Community Server - GPL mysql>

Run SELECT VERSION(); to confirm the server version, then \q to exit.

6

Create a table, insert a row and query it

The default SecureAnyCloud database is ready to use from first boot. Run a SQL round-trip to verify the full stack:

mysql -u root -p"${MYSQL_ROOT_PW}" --socket="${MYSQL_SOCKET}" sac ' -h -P 3306 sac

If the application server is in the same virtual network, the TCP connection succeeds with the default caching_sha2_password plugin, using TLS negotiated automatically by the MySQL protocol.

If you see Authentication plugin 'caching_sha2_password' cannot be loaded, upgrade the client to MySQL Connector 8.0.3 or later.

8

Server components

The installation uses the following files and paths:

  • MySQL server daemon: /usr/sbin/mysqld
  • mysql CLI client: /usr/bin/mysql
  • mysqldump backup utility: /usr/bin/mysqldump
  • mysqladmin admin utility: /usr/bin/mysqladmin
  • MySQL data directory: /var/lib/mysql/
  • MySQL socket: /var/run/mysqld/mysqld.sock
  • MySQL error log: /var/log/mysql/error.log
  • Systemd unit: /usr/lib/systemd/system/mysql.service
  • SecureAnyCloud init drop-in: /etc/systemd/system/mysql.service.d/sac-init.conf
  • First-boot systemd unit: /etc/systemd/system/mysql-firstboot.service
  • First-boot script: /usr/local/sbin/mysql-firstboot.sh
  • Start helper: /usr/local/sbin/mysql-start.sh
  • Stop helper: /usr/local/sbin/mysql-stop.sh
  • Credentials file: /stage/scripts/mysql-credentials.log
  • First-boot sentinel: /var/lib/mysql/.firstboot-done
  • Build version record: /stage/scripts/BUILD_VERSIONS

The exact installed version is recorded in /stage/scripts/BUILD_VERSIONS. Inspect it with:

cat /stage/scripts/BUILD_VERSIONS

The output looks like this:

mysql-server=9.7.0-1ubuntu24.04
9

Review the filesystem layout

  • / (32 GB): root filesystem, which includes /var/lib/mysql
  • /boot (1 GB): operating system kernel files
  • /var/lib/mysql (on root): MySQL data directory

For production workloads, attach a separate Premium SSD data disk, format it with ext4 or xfs, and bind mount it over /var/lib/mysql before you start the service. This keeps database I/O off the OS disk, improves IOPS, and lets you resize and snapshot the data volume independently.

10

Manage the MySQL service

systemd starts and stops MySQL through the mysql.service unit.

Check the service status:

systemctl status mysql.service

Stop MySQL:

sudo /usr/local/sbin/mysql-stop.sh

Start MySQL:

sudo /usr/local/sbin/mysql-start.sh

Restart MySQL:

sudo systemctl restart mysql.service

View the MySQL error log:

sudo tail -n 50 /var/log/mysql/error.log
11

Troubleshooting

Cannot connect to MySQL on port 3306

  • Verify that the service is running: systemctl status mysql.service
  • Verify that the listener is bound: ss -tln | grep 3306
  • Check the error log: sudo tail -n 50 /var/log/mysql/error.log
  • Confirm that the network security group allows TCP 3306 from your client source IP
  • Confirm that the VM's NIC is in the expected subnet with the NSG attached

Authentication errors after connecting

  • Re-read the password from the credentials file: sudo awk -F= '/^root_password=/{print $2}' /stage/scripts/mysql-credentials.log
  • Make sure the shell variable was not truncated (the password is 32 characters)
  • Verify that the first-boot sentinel exists: ls -la /var/lib/mysql/.firstboot-done. If it is absent, mysql-firstboot.service did not complete. Check its journal: journalctl -u mysql-firstboot.service --no-pager

First-boot service did not run

  • Check the first-boot service status: systemctl status mysql-firstboot.service
  • Review the journal: journalctl -u mysql-firstboot.service --no-pager -n 50
  • Verify that MySQL started first: systemctl status mysql.service
  • If MySQL failed to start, check whether the data directory was initialised: ls /var/lib/mysql/mysql/
  • If the data directory is empty, trigger initialisation manually: sudo mysqld --initialize-insecure --user=mysql

Remote clients cannot authenticate with caching_sha2_password

  • The client library must be MySQL Connector 8.0.3 or later, or the official MySQL C connector 8.0.3 or later.
  • For legacy applications, create the account with the older plugin: CREATE USER 'user'@'%' IDENTIFIED WITH mysql_native_password BY '';
  • The mysql_native_password plugin is available in 9.7 but is deprecated upstream. For long-lived accounts, plan a migration to caching_sha2_password or authentication_fido.

Service fails to start

  • Check the systemd journal: journalctl -u mysql.service --no-pager -n 50
  • Check the MySQL error log: sudo tail -n 50 /var/log/mysql/error.log
  • Check filesystem space: df -h /var/lib/mysql
  • Verify data directory ownership: ls -la /var/lib/mysql. Files should be owned by mysql:mysql.
12

Security recommendations

Rotate the root password immediately after reading it from the credentials file:

mysql -u root -p"${MYSQL_ROOT_PW}" --socket="${MYSQL_SOCKET}" '; FLUSH PRIVILEGES; SQL
  • Create application-specific users with minimal privileges. Never connect application code as root.
  • Restrict port 3306 in your NSG to trusted application server subnets only.
  • Remove anonymous users: DELETE FROM mysql.user WHERE User=''; FLUSH PRIVILEGES;
  • Disable remote root login: DELETE FROM mysql.user WHERE User='root' AND Host != 'localhost'; FLUSH PRIVILEGES;
  • Enable the error log and monitor it for connection failures and authentication errors: /var/log/mysql/error.log
  • Back up regularly with mysqldump: mysqldump -u root -p"${MYSQL_ROOT_PW}" --socket="${MYSQL_SOCKET}" --all-databases > backup.sql
  • Keep MySQL updated by running sudo apt-get update && sudo apt-get upgrade mysql-server periodically. The official MySQL APT repository is already configured on this image.
  • Shred the credentials file once the password is stored in your secret store: sudo shred -u /stage/scripts/mysql-credentials.log
13

Support and licensing

MySQL Community Server is released under the GNU General Public License version 2. There is no per-core, per-seat or per-server fee for the Community edition. MySQL is a registered trademark of Oracle Corporation.

SecureAnyCloud provides commercial support for this image, separately from the upstream project. Contact us at any time for support questions, architectural advice, capacity planning or migration help.

  • Email: sales@secureanycloud.com
  • Website: secureanycloud.com
  • Support hours: 24/7, with a 24 hour response SLA

Deploy on Azure

Launch MySQL 9.7 LTS Community Server on Ubuntu 24.04 with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure

Launch MySQL 9.7 LTS on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure