Percona Server for MySQL on AWS User Guide
Overview
This image runs Percona Server for MySQL, an enhanced open source drop in replacement for MySQL that adds performance, scalability and observability features while remaining wire protocol compatible with stock MySQL clients and tooling. Percona Server is the only database workload on the image, so the platform stays lean, predictable and easy to reason about. The current stable line of Percona Server for MySQL 8 is provided, installed from the official Percona apt repository.
The image ships with password authentication switched on. On the first boot of your instance a one shot service generates two fresh, strong passwords unique to that instance: one for the MySQL root superuser and one for a dedicated cloudimg application user. The script applies the passwords to the running server and writes them, together with the connection details, to /root/percona-credentials.txt. The file is readable only by the root user. No shared or default database credentials ship in the image.
Percona Server database files (InnoDB tablespaces, redo logs, binary logs) live on a dedicated EBS storage volume mounted at /var/lib/mysql. Keeping database files on their own volume means storage can be grown, snapshotted and backed up independently of the operating system disk.
A small nginx listing identity shim runs on port 80 and serves a static page identifying the running product. This is the AWS Marketplace listing identity endpoint that the catalogue scanner queries; the MySQL wire protocol on port 3306 is the actual product.
This is a headless image. Percona Server has no web administration interface; you operate it over SSH with the standard mysql client and any MySQL compatible driver from your application tier.
Prerequisites
Before you deploy this image you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network and inbound port 3306 from any client networks that will connect to MySQL
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Recommended instance type: m5.large (2 vCPU, 8 GB RAM) or larger. Percona Server sizes its InnoDB buffer pool from available memory and benefits from additional CPU and RAM for production workloads.
Step 1: Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images choose AWS Marketplace AMIs and search for Percona Server for MySQL. Select the cloudimg listing and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or larger. Choose your EC2 key pair under Key pair (login). Under Network settings select your VPC and subnet, and either create or select a security group that allows inbound port 22 from your management network and inbound port 3306 from any client networks that will connect to MySQL. Leave the root volume at the default size or larger; the MySQL data volume is attached automatically from the image.
Select Launch instance. First boot initialisation, which generates the passwords and starts Percona Server, takes a minute or two after the instance state becomes Running and the status checks pass.
Step 2: Launch the Instance from the AWS CLI
The following block launches an instance from the cloudimg Percona Server for MySQL Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens inbound port 22 and port 3306 from your client networks.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--metadata-options HttpTokens=required \
--block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":30,"VolumeType":"gp3"}}]' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=percona-01}]'
The command prints a JSON document on success. Note the instance ID, then retrieve its public address once it is running with aws ec2 describe-instances --instance-ids <instance-id> --query "Reservations[].Instances[].PublicIpAddress" --output text.
Step 3: Connect over SSH
Connect over SSH with the key pair you selected and the public IP address from step 2. The SSH login user depends on the operating system of the AMI variant you launched:
| AMI variant | SSH login user |
|---|---|
| Percona Server for MySQL 8 on Ubuntu 24.04 | ubuntu |
ssh <login-user>@<public-ip>
Wait until the instance has passed both EC2 status checks before connecting. The first boot service runs as part of system startup, so Percona Server is initialised and the credentials file is in place by the time you can log in.
Step 4: Retrieve the Generated Passwords
The first boot service generates fresh root and cloudimg passwords for this instance and writes them, with the connection details, to /root/percona-credentials.txt. The file is readable only by the root user. Display it from your SSH session:
sudo cat /root/percona-credentials.txt
The file looks like this, with a unique pair of passwords on your instance:
# Percona Server for MySQL 8 - generated on first boot.
mysql.host=54.211.13.92
mysql.port=3306
mysql.root.user=root
mysql.root.pass=<your generated root password>
mysql.cloudimg.user=cloudimg
mysql.cloudimg.pass=<your generated application user password>
Use the mysql.root.pass value as the password for the root account, and the mysql.cloudimg.pass value as the password for the cloudimg application user. Both accounts have full privileges across all databases; the cloudimg user is also reachable remotely on port 3306, the root user is restricted to root@localhost.
Step 5: Confirm the Service and the Listener
Percona Server runs under systemd as the mysql service and starts automatically on boot. Confirm it is active:
sudo systemctl status mysql.service --no-pager
The output shows the unit as active (running):
* mysql.service - Percona Server
Loaded: loaded (/usr/lib/systemd/system/mysql.service; enabled; preset: enabled)
Drop-In: /etc/systemd/system/mysql.service.d
`-10-firstboot-order.conf
Active: active (running) since Sun 2026-05-24 23:56:44 UTC; 12s ago
Confirm the MySQL wire protocol is listening on port 3306 and the listing identity shim is listening on port 80:
sudo ss -tln | grep -E ':80 |:3306 '
The output shows both ports bound on all interfaces:
LISTEN 0 200 0.0.0.0:3306 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
Step 6: Open the MySQL Client
Open a MySQL session as the root user with the password from the credentials file:
PASS=$(sudo awk -F= '/^mysql.root.pass=/{print $2}' /root/percona-credentials.txt)
sudo mysql -u root -p"$PASS"
Confirm the build identifies as Percona Server, not stock MySQL, and that the InnoDB buffer pool has been sized for the image defaults:
SELECT VERSION();
SELECT @@version_comment AS version_comment;
SELECT @@innodb_buffer_pool_size AS innodb_buffer_pool_size;
The output identifies Percona Server 8.0 and shows the default 512 MiB buffer pool:
VERSION()
8.0.45-36
version_comment
Percona Server (GPL), Release '36', Revision '8fe4a72d'
innodb_buffer_pool_size
536870912
List the system and user databases:
SHOW DATABASES;
The fresh server reports the four system databases:
Database
information_schema
mysql
performance_schema
sys
Exit the mysql client with exit; or Ctrl-D when you are done.
Step 7: Create a Database and a Table
Create your first database, create a table, and insert a row, all from the mysql client:
PASS=$(sudo awk -F= '/^mysql.root.pass=/{print $2}' /root/percona-credentials.txt)
sudo mysql -u root -p"$PASS"
CREATE DATABASE my_app;
USE my_app;
CREATE TABLE accounts (
id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
INSERT INTO accounts (email) VALUES ('alice@example.com');
SELECT * FROM accounts;
The SELECT returns the row you inserted, with the auto generated identifier and timestamp:
+----+--------------------+---------------------+
| id | email | created_at |
+----+--------------------+---------------------+
| 1 | alice@example.com | 2026-05-25 00:01:23 |
+----+--------------------+---------------------+
Step 8: Connect Remotely as the cloudimg Application User
The cloudimg user is created with full privileges and is reachable from any host ('cloudimg'@'%'). After opening port 3306 to your application CIDR in the EC2 security group, connect from your application host:
mysql -h <public-ip> -P 3306 -u cloudimg -p
Paste the mysql.cloudimg.pass value from the credentials file when prompted. The cloudimg account is the recommended account for application connections because it can be reached over the network; the root account is intentionally restricted to localhost (database hardening best practice).
Step 9: The Listing Identity Endpoint
A small nginx listing identity shim runs on port 80 and serves a static page identifying the running product. AWS Marketplace uses this endpoint to confirm the image identity, and it gives the catalogue listing a screenshotable surface. From the instance:
curl -s http://127.0.0.1/ | head -8
The output is the identity page, served by nginx, identifying the running product as Percona Server for MySQL:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Percona Server for MySQL - cloudimg AWS Marketplace AMI</title>
This shim does not proxy to MySQL; the MySQL wire protocol on port 3306 is the actual product. You can disable the shim on a production instance by stopping nginx.service (sudo systemctl disable --now nginx.service).
Step 10: The Dedicated Data Volume
Database files live on a dedicated EBS volume mounted at /var/lib/mysql. Confirm the mount and the free space:
df -h /var/lib/mysql /
The output shows the data disk separate from the OS disk:
Filesystem Size Used Avail Use% Mounted on
/dev/nvme1n1 30G 194M 28G 1% /var/lib/mysql
/dev/root 19G 4.0G 15G 22% /
To grow the data volume, use the AWS console or the AWS CLI to resize the underlying EBS volume, then run growpart and resize2fs on the instance to extend the filesystem live without downtime.
Step 11: Service Management
Percona Server is a single systemd unit, mysql.service. Standard service commands manage it:
sudo systemctl status mysql.service # current state
sudo systemctl restart mysql.service # rolling restart (brief connection drop)
sudo systemctl stop mysql.service # stop the daemon
sudo systemctl start mysql.service # start the daemon
The nginx listing identity shim is nginx.service; the per instance first boot service is percona-firstboot.service and is one shot — it has already completed by the time you log in.
Step 12: Tuning the Buffer Pool
The image ships with innodb_buffer_pool_size = 512M, a sensible default for an m5.large (8 GB RAM). Production workloads on larger instances should raise this to roughly 60-70% of host RAM. Edit /etc/mysql/mysql.conf.d/99-cloudimg.cnf:
[mysqld]
bind-address = 0.0.0.0
datadir = /var/lib/mysql
default-authentication-plugin = caching_sha2_password
innodb_buffer_pool_size = 5G # 5 GiB on an m5.xlarge with 16 GB RAM
max_connections = 200
Apply the change with sudo systemctl restart mysql.service.
Step 13: Rotating the Passwords
To rotate the root password, log in with the existing one and ALTER USER:
PASS=$(sudo awk -F= '/^mysql.root.pass=/{print $2}' /root/percona-credentials.txt)
sudo mysql -u root -p"$PASS" -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '<new-password>';"
After rotation, update /root/percona-credentials.txt to the new password so the credentials file stays accurate. Repeat for the cloudimg user (ALTER USER 'cloudimg'@'%' IDENTIFIED BY '...') when you need to rotate the application credential.
Step 14: Backups
For ad hoc logical backups, mysqldump ships in the image:
PASS=$(sudo awk -F= '/^mysql.root.pass=/{print $2}' /root/percona-credentials.txt)
sudo mysqldump -u root -p"$PASS" --all-databases --single-transaction --routines --triggers --events \
> /tmp/mysql-backup-$(date +%F).sql
For production environments, switch to Percona XtraBackup, the hot backup tool for InnoDB. XtraBackup is part of the Percona suite and is available from the same Percona apt repository the server was installed from. Install with:
sudo apt-get install -y percona-xtrabackup-80
XtraBackup documentation: https://docs.percona.com/percona-xtrabackup/8.0/.
Troubleshooting
/root/percona-credentials.txt does not exist. First boot has not completed. Check the unit:
sudo systemctl status percona-firstboot.service
sudo journalctl -u percona-firstboot.service --no-pager
The unit is one shot; once it reaches inactive (dead) with condition: succeeded, the credentials file is in place and the sentinel /var/lib/cloudimg/percona-firstboot.done exists.
mysql -u root -p reports Access denied. The password in the credentials file is the live one; if you have rotated the password since first boot, use your new value. The root account is restricted to 'root'@'localhost' so you cannot use it from a remote host — use the cloudimg account for remote connections.
Cannot connect on port 3306 from a remote host. Open inbound TCP 3306 on the EC2 security group from your application CIDR. The MySQL daemon already binds on 0.0.0.0:3306 (bind-address is 0.0.0.0 in /etc/mysql/mysql.conf.d/99-cloudimg.cnf).
/var/lib/mysql is full. Grow the underlying EBS volume in the AWS console, then on the instance:
sudo growpart /dev/nvme1n1 1 2>/dev/null || true
sudo resize2fs /dev/nvme1n1
(Replace the device name with the result of lsblk.)
Screenshots

Terminal output showing Percona Server for MySQL 8.0.45 installed and the mysql.service active (running) under systemd.

SHOW DATABASES listing the four system databases on a fresh Percona Server instance alongside SHOW VARIABLES LIKE 'version%' confirming the Percona Server build.

df -h confirming the 30 GiB dedicated EBS gp3 volume mounted at /var/lib/mysql, separate from the OS root disk.
Support
This image is published by cloudimg. For technical support contact support@cloudimg.co.uk.