Deployment guide

MySQL 9 on Oracle Linux 10

Overview

MySQL 9 Community Server (version 9.6.0, Innovation track) brings new SQL features, vector data types for AI workloads, and continued support for the InnoDB storage engine. This SecureAnyCloud image runs it on Oracle Linux 10 on Microsoft Azure, preinstalled and preconfigured.

A firstboot service rotates the root password to a unique per-VM value on the first customer boot. This guide covers deployment and configuration from the Azure Marketplace.

What you get:

  • MySQL 9.6.0 Community Server from the official Oracle MySQL Innovation channel for Oracle Linux 10
  • A default configuration at /etc/my.cnf.d/sac.cnf: utf8mb4 as the default character set, a 512M InnoDB buffer pool, the slow query log on, and max_connections 200
  • Per-VM root password rotation by mysql-firstboot.service on first boot
  • A default SecureAnyCloud database (utf8mb4_0900_ai_ci), ready to use
  • mysqld.service enabled to start at boot
  • A firewalld rule that already opens TCP 3306 on the OS
  • Logs at /var/log/mysql/error.log and /var/log/mysql/slow.log
  • The latest security patches, applied at build time

Platform: Microsoft Azure (Gen2 Hyper-V)

Default OS user: azureuser

1

Deploy the Virtual Machine

Accept the Marketplace terms, then create the virtual machine. Replace <resource-group> with your resource group name.

az vm image terms accept --urn sac1647283583153:mysql-9-oel10:standard:latest
az vm create -g <resource-group> -n mysql-9-vm -l eastus \
  --image sac1647283583153:mysql-9-oel10:standard:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_rsa.pub

For higher-load workloads, choose a memory-optimised SKU such as Standard_E4s_v5 (4 vCPU, 32 GB RAM). Tune innodb_buffer_pool_size after first boot, as described in Step 10.

2

Connect via SSH

Connect to the virtual machine over SSH:

ssh azureuser@<public-ip>

Confirm the OS:

cat /etc/oracle-release
3

Confirm MySQL is Running

mysqld.service starts automatically at boot. Check that it is active:

sudo systemctl is-active mysqld.service

Show the full status:

sudo systemctl status mysqld.service --no-pager | head -12
4

Locate the Per VM Root Password

The mysql-firstboot.service rotates the root password on first boot and writes the new credentials to /home/azureuser/CREDENTIALS.txt. Read the file:

sudo cat /home/azureuser/CREDENTIALS.txt

The file is owned by root:root with mode 0600. It contains the per-VM password, the default database name and the path to your config file.

Copy the password to a secure location, then remove the file.

5

Confirm MySQL is Listening

Check that MySQL is listening on port 3306:

sudo ss -tlnp | grep ':3306'
6

Connect with the MySQL Client

Connect as root and enter the password from Step 4 when prompted:

mysql -uroot -p

Run a quick smoke test:

sudo mysql -uroot -p$(grep '^Password:' /home/azureuser/CREDENTIALS.txt | awk '{print $2}') -e "SELECT VERSION(), NOW()"
7

Create an Application Database and User

The default SecureAnyCloud database is fine for testing. For production workloads, use a dedicated database and a least-privilege user instead of connecting as root.

Create them with the commands below, and set the password to a strong value of your own choice:

sudo mysql -uroot -p$(grep '^Password:' /home/azureuser/CREDENTIALS.txt | awk '{print $2}') <<'SQL' CREATE DATABASE IF NOT EXISTS appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; CREATE USER IF NOT EXISTS 'appuser'@'%' IDENTIFIED BY 'CHANGE_ME_StrongPasswordExample123!'; GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'%'; FLUSH PRIVILEGES; SHOW GRANTS FOR 'appuser'@'%'; SQL

For a localhost-only user, replace 'appuser'@'%' with 'appuser'@'localhost'. This is more secure if your application runs on the same VM.

8

Open Azure NSG for Port 3306 (Remote Connections)

The OS firewalld already permits port 3306, but the Azure Network Security Group attached to the VM blocks it by default. Open the port from your application VNet only. For production, never open it from 0.0.0.0/0:

az network nsg rule create -g <resource-group> --nsg-name <nsg-name> \
  -n allow-mysql-3306 \
  --priority 200 \
  --direction Inbound \
  --access Allow \
  --protocol Tcp \
  --source-address-prefixes 10.0.0.0/16 \
  --destination-port-ranges 3306

Replace 10.0.0.0/16 with your application subnet's CIDR. Then test the connection from a client machine on that VNet:

mysql -h <vm-private-ip> -P 3306 -u appuser -p
9

Backup and Restore

Create a logical dump of a single database:

sudo mysqldump -uroot -p$(grep '^Password:' /home/azureuser/CREDENTIALS.txt | awk '{print $2}') \
  --single-transaction --routines --triggers --events \
  appdb > /home/azureuser/appdb-$(date +%Y%m%d).sql

To back up the whole server, use --all-databases:

sudo mysqldump -uroot -p$(grep '^Password:' /home/azureuser/CREDENTIALS.txt | awk '{print $2}') \
  --all-databases --single-transaction --routines --triggers --events \
  --master-data=2 > /home/azureuser/full-$(date +%Y%m%d).sql

Restore a dump into a target database:

sudo mysql -uroot -p$(grep '^Password:' /home/azureuser/CREDENTIALS.txt | awk '{print $2}') appdb < /home/azureuser/appdb-20260509.sql

For routine production backups, schedule the dump with cron and copy it to Azure Blob Storage or an Azure Files share.

10

Tuning InnoDB Buffer Pool for Larger VMs

SecureAnyCloud defaults innodb_buffer_pool_size to 512 MB, so that MySQL fits comfortably on the Standard_B2s build target (4 GB RAM total). On a larger VM, allocate roughly 50 to 70 percent of system RAM to the buffer pool. For example, on a Standard_E4s_v5 (32 GB RAM), use 16G.

Add an override file at /etc/my.cnf.d/local.cnf. It loads after sac.cnf, so its values win. Replace <buffer-pool-size> with a value that suits your VM RAM, for example 16G on Standard_E4s_v5:

sudo tee /etc/my.cnf.d/local.cnf >/dev/null <<CNF [mysqld] innodb_buffer_pool_size = <buffer-pool-size> innodb_buffer_pool_instances = 8 innodb_log_file_size = 1G max_connections = 500 CNF
sudo systemctl restart mysqld.service

Confirm the new value is applied:

sudo mysql -uroot -p$(grep '^Password:' /home/azureuser/CREDENTIALS.txt | awk '{print $2}') -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size'"

The local override survives package upgrades. The sac.cnf file does not regenerate on package upgrade, but to change a shipped default, always do it in local.cnf rather than editing sac.cnf in place.

11

Slow Query Analysis

SecureAnyCloud enables the slow query log out of the box at /var/log/mysql/slow.log, with a 2-second threshold. Generate some load, then inspect the log:

sudo tail -30 /var/log/mysql/slow.log 2>/dev/null || echo "no slow queries logged yet"

Use the bundled mysqldumpslow to summarise the slowest queries by total time:

sudo mysqldumpslow -s t /var/log/mysql/slow.log | head -30

To lower the threshold temporarily for debugging, run the command below. No restart is needed:

sudo mysql -uroot -p$(grep '^Password:' /home/azureuser/CREDENTIALS.txt | awk '{print $2}') -e "SET GLOBAL long_query_time = 0.5"

When you finish, set it back with SET GLOBAL long_query_time = 2.

12

SSL/TLS Connections

MySQL 9 generates self-signed SSL certificates automatically on first initialisation. Verify that they are in place and that the server accepts TLS:

sudo ls -la /var/lib/mysql/*.pem
sudo mysql -uroot -p$(grep '^Password:' /home/azureuser/CREDENTIALS.txt | awk '{print $2}') -e "SHOW VARIABLES LIKE 'have_ssl'"

To force a single user to connect over TLS only, run:

sudo mysql -uroot -p$(grep '^Password:' /home/azureuser/CREDENTIALS.txt | awk '{print $2}') -e "ALTER USER 'appuser'@'%' REQUIRE SSL"

For production, replace the auto-generated certificates with ones from Azure Key Vault or Let's Encrypt. Then point ssl-cert, ssl-key and ssl-ca in /etc/my.cnf.d/local.cnf at the new files.

Managing the Server

Restart MySQL:

sudo systemctl restart mysqld.service

Tail the error log:

sudo tail -20 /var/log/mysql/error.log

List open connections:

sudo mysql -uroot -p$(grep '^Password:' /home/azureuser/CREDENTIALS.txt | awk '{print $2}') -e "SHOW PROCESSLIST"

Updating MySQL Within the 9.x Innovation Channel

The image ships with mysql-innovation-community enabled and mysql-8.4-lts-community disabled. To apply minor 9.x updates as Oracle ships them, use dnf upgrade:

sudo dnf upgrade -y --nogpgcheck mysql-community-server mysql-community-client
sudo systemctl restart mysqld.service mysqld --version

Note: the MySQL signing key (B7B3B788A8D3785C) expired on 2025-10-22, but Oracle continues to sign 9.x RPMs with it. The --nogpgcheck flag is required until Oracle publishes a 2026 replacement key.

On dnf5, you may also need dnf download --resolve plus rpm -ivh --nosignature --nodigest.

Common Errors

"Access denied for user 'root'@'localhost' (using password: NO)": firstboot has rotated the password. Read /home/azureuser/CREDENTIALS.txt again.

"Can't connect to MySQL server on '\<vm-ip>:3306'": the Azure NSG is blocking the port. See Step 8.

"Too many connections": raise max_connections in /etc/my.cnf.d/local.cnf and restart.

"[Warning] Using a password on the command line interface can be insecure": MySQL emits this warning every time you pass a password on the command line. For automation, put the password in ~/.my.cnf with mode 0600 and call mysql --defaults-file=~/.my.cnf instead.

"InnoDB: Cannot allocate memory for the buffer pool": your VM does not have enough RAM for the configured innodb_buffer_pool_size. Lower it in /etc/my.cnf.d/local.cnf, or move to a larger SKU.

On Startup

systemd enables mysqld.service at boot. Verify it:

sudo systemctl is-enabled mysqld.service

mysql-firstboot.service runs once, on the very first customer boot, to rotate the root password. It then stays in the active (exited) state and does nothing on later reboots.

Support

SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.

License: MySQL Community Server is licensed under GPLv2. SecureAnyCloud charges a per-vCPU, per-hour fee for packaging, security patching and 24/7 support.

Deploy on Azure

Launch MySQL 9 Community Server on Oracle Linux 10 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