MySQL 8.0 on a 2-Core, 2-GB Debian 12 Box: Squeezing 2 120 IOPS, Kicking Alibaba Cloud Bloat, and Nightly Dual-Site Backups

Rey Posted on 24 days ago 27 Views


TL;DR Skip the fluff and copy-paste the commands. This guide shows you how to:

  • run MySQL 8.0 on 2 GB RAM without swapping to death
  • remove every last Alibaba “security” agent that eats half your memory
  • keep seven days of encrypted, compressed backups on two different machines

Prerequisites

  • Debian 12 VPS: 192.168.0.2, 2 vCPU / 2 GB RAM, 2 120 IOPS (the vendor lied—expect ~2 000).
  • Backup box on the same LAN: 192.168.0.3, SSH daemon listening on 22102/tcp.
  • Alibaba Cloud Security Group already allows 53768/tcp (SSH) and 33106/tcp (MySQL).
  • You have sudo and your SSH key on the server.

1. Change SSH Port and Disable Local Firewall

# 1. Open new port first—don’t lock yourself out
sudo sed -i 's/#Port 22/Port 53768/' /etc/ssh/sshd_config
sudo systemctl restart sshd

# 2. Once you can log in on 53768, kill UFW
sudo systemctl stop ufw
sudo systemctl disable ufw
sudo apt purge ufw -y

Security Group handles the rest; UFW is dead weight on 2 GB.


2. Remove Alibaba Cloud Agents (Aegis, CloudMonitor, Aliyun Assist)

sudo systemctl stop aliyun.service
sudo systemctl disable aliyun.service
sudo rm -rf /usr/local/aegis* /usr/local/cloudmonitor /etc/init.d/aegis
sudo rm -rf /etc/systemd/system/aliyun*
sudo apt purge aliyun-assist aliyun-cli -y

Reboot and run ps aux | grep -E 'aegis|aliyun'—should be empty.


3. Install MySQL 8.0 from the Official APT Repo

wget https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.29-1_all.deb   # choose 8.0
sudo apt update && sudo apt install -y mysql-server

Do not start it yet—tune first.


4. Tuning my.cnf for 2 120 IOPS and 2 GB RAM

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
# Network
bind-address   = 192.168.0.2
port           = 33106
user           = mysql
default_authentication_plugin = mysql_native_password

# InnoDB for 2 120 IOPS
innodb_buffer_pool_size   = 768M
innodb_log_file_size      = 128M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method       = O_DIRECT
innodb_io_capacity        = 2000
innodb_io_capacity_max    = 3000

# Save RAM
skip_name_resolve         = 1
performance_schema        = OFF
max_connections           = 50
key_buffer_size           = 32M
tmp_table_size            = 32M
max_heap_table_size       = 32M
sudo systemctl restart mysql
sudo systemctl enable mysql

5. Lock Down Accounts

sudo mysql -uroot -p
-- root only from localhost
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'SuperStrongRootPass';

-- application user, one source IP only
CREATE USER IF NOT EXISTS 'app'@'192.168.0.3' IDENTIFIED WITH mysql_native_password BY 'AppUserPass';
GRANT ALL PRIVILEGES ON *.* TO 'app'@'192.168.0.3';
FLUSH PRIVILEGES;

Test from the backup host:

mysql -h192.168.0.2 -P33106 -uapp -p

6. Encrypted Nightly Backups (Local + Remote)

6.1 Install tools

sudo apt install zip msmtp rsync -y

6.2 Backup script: /usr/local/bin/mysql_backup.sh

#!/bin/bash
set -euo pipefail

BACKUP_DIR="/www/bak/db"
REMOTE_HOST="192.168.0.3"
REMOTE_PORT="22102"
REMOTE_DIR="/www/bak/mysql"
RETAIN_DAYS=3
ZIP_PASS="12345678"
MAIL_TO="123@163.com"

mkdir -p "$BACKUP_DIR"
cd "$BACKUP_DIR"

# Dump each DB
for DB in $(mysql -uroot -p'SuperStrongRootPass' -N -e "SHOW DATABASES;" | grep -Ev '^(information_schema|performance_schema|mysql|sys)$'); do
    TS=$(date +%F-%H%M%S)
    DUMP_FILE="${DB}_${TS}.sql"
    mysqldump -uroot -p'SuperStrongRootPass' --single-transaction --routines --triggers "$DB" > "$DUMP_FILE"
    zip -P "$ZIP_PASS" "${DUMP_FILE}.zip" "$DUMP_FILE"
    rm "$DUMP_FILE"
done

# Push to remote
rsync -avz -e "ssh -p $REMOTE_PORT" ./*.zip root@$REMOTE_HOST:$REMOTE_DIR/

# Prune local & remote
find "$BACKUP_DIR" -type f -mtime +$RETAIN_DAYS -delete
ssh -p $REMOTE_PORT root@$REMOTE_HOST "find $REMOTE_DIR -type f -mtime +$RETAIN_DAYS -delete"

# Ping us
echo "MySQL backup $(date +%F) completed" | msmtp "$MAIL_TO"
sudo chmod +x /usr/local/bin/mysql_backup.sh

6.3 Schedule it

sudo crontab -e
0 1 * * * /usr/local/bin/mysql_backup.sh >> /var/log/mysql_backup.log 2>&1

7. msmtp for Email Alerts

sudo nano /etc/msmtprc
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile /var/log/msmtp.log

account default
host smtp.163.com
port 465
from 123@163.com
user 123@163.com
password YOUR_SMTP_AUTH_TOKEN

Test:

echo "test" | msmtp 123@163.com

8. Smoke Test

  1. Reboot: sudo reboot
  2. SSH into 192.168.0.2:53768
  3. Connect from backup box: mysql -h192.168.0.2 -P33106 -uapp -p
  4. Wait for 01:00 UTC and check /www/bak/db and 192.168.0.3:/www/bak/mysql

9. Pitfalls (a.k.a. “Why it broke at 3 a.m.”)

  • Security Group or remote ufw forgot port 22102 → rsync dies with “broken pipe”.
  • Special characters in password → wrap in single quotes inside the script.
  • innodb_buffer_pool_size > 1 GB → OOM killer loves MySQL.
  • 163 SMTP needs an auth token, not your login password.

10. TL;DR Recap

  • Debian 12 + MySQL 8.0: 768 MB buffer pool, 2 000 IOPS tuned.
  • Alibaba bloatware nuked—freeing ~120 MB RAM.
  • Encrypted, compressed backups on two hosts, auto-pruned after three days.

Happy hacking, and may your pagers stay silent.

This author has not provided a description.
Last updated on 2025-08-19