MySQL zu installieren ist ein Befehl. Die eigentliche Arbeit kommt danach: ein App-Benutzer, ein Weg vom eigenen Computer zur Datenbank, der Port 3306 nicht ins Internet stellt, Speichereinstellungen für einen kleinen Server und Backups, die ohne Sie laufen. Diese Anleitung behandelt alle vier auf Ubuntu 24.04. Jeder Schritt lief auf unserem Ubuntu-24.04-Image, und die Zahlen unten stammen von diesem Server.
Führen Sie die Befehle als Benutzer mit sudo aus. Die Ubuntu-Einrichtungsanleitung legt einen an.
1. Installieren
sudo apt update
sudo apt install -y mysql-server
mysql --version
Die Installation dauerte auf unserem Server 51 Sekunden und lieferte MySQL 8.0.46. Es startet sofort, startet bei jedem Boot wieder und lauscht nur auf dem Server selbst: 127.0.0.1:3306 für normale Verbindungen und 127.0.0.1:33060 für das neuere X-Protokoll von MySQL. Von außen ist noch nichts erreichbar.
2. Eine Datenbank und einen Benutzer anlegen
Das root-Konto von MySQL nutzt unter Ubuntu Socket-Authentifizierung, deshalb meldet sudo mysql Sie ohne Passwort an. Legen Sie eine Datenbank und einen Benutzer für Ihre App an:
sudo mysql
CREATE DATABASE app CHARACTER SET utf8mb4;
CREATE USER 'app'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'localhost';
EXIT;
Testen Sie es so, wie Ihre App sich verbinden wird:
mysql -u app -p app -e "SELECT CURRENT_USER();"
Ausgegeben werden sollte app@localhost. Ein falsches Passwort ergibt ERROR 1045 (28000): Access denied for user 'app'@'localhost'. Der Benutzer darf innerhalb von app alles und außerhalb nichts.
3. Vom eigenen Computer verbinden: SSH-Tunnel
Um einen Desktop-Client wie DBeaver, MySQL Workbench oder die mysql-Kommandozeile auf Ihrem Rechner zu nutzen, öffnen Sie keinen Port. Leiten Sie einen über SSH weiter:
ssh -L 3307:127.0.0.1:3306 deploy@YOUR.SERVER.IP
Bei einem NAT-Tarif ergänzen Sie -p und den persönlichen SSH-Port aus dem Dashboard. Solange das Fenster offen ist, richten Sie Ihren Client auf Host 127.0.0.1, Port 3307, Benutzer app. Lokal haben wir 3307 genommen, damit es nicht mit einem MySQL kollidiert, das vielleicht auf Ihrem Rechner läuft. In unserem Test antwortete der Server sofort durch den Tunnel, während eine direkte Verbindung zu seiner Adresse auf 3306 abgewiesen wurde.
4. Direkter Zugriff für einen anderen Server
Manchmal läuft die App auf einem zweiten Server und muss sich direkt verbinden. Dafür braucht die Datenbank einen Tarif mit eigener IPv4, denn ein NAT-Tarif leitet nur Ihren SSH-Port weiter. Drei Änderungen, alle auf die Adresse des App-Servers beschränkt (hier 203.0.113.20):
sudo sed -i 's/^bind-address.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
sudo systemctl restart mysql
sudo ufw allow from 203.0.113.20 to any port 3306 proto tcp
CREATE USER 'app'@'203.0.113.20' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'203.0.113.20';
Ist ufw noch nicht aktiv, erlauben Sie zuerst SSH (sudo ufw allow OpenSSH) und führen dann sudo ufw enable aus. Die Details stehen in der ufw-Anleitung.
Wir haben beide Schlösser einzeln geprüft. Mit Firewall-Regel, aber ohne passenden MySQL-Benutzer lehnte der Server mit error 1130: Host '…' is not allowed to connect to this MySQL server ab. Mit hinzugefügtem Benutzer ging die Verbindung durch. Ohne Firewall-Regel lief die Verbindung einfach in einen Timeout. Jede andere Adresse im Internet bekommt genau diesen Timeout.
5. Weniger RAM
Im Leerlauf, ohne eigene Daten, belegte MySQL 8.0 auf unserem Server 383 MB. Das meiste davon ist das Performance Schema, eine Diagnosefunktion, die Speicher vorab reserviert. Schalten Sie es auf einem kleinen VPS ab und legen Sie die Größe des Hauptcaches selbst fest:
sudo tee /etc/mysql/mysql.conf.d/zz-small-vps.cnf >/dev/null <<'EOF'
[mysqld]
performance_schema = OFF
innodb_buffer_pool_size = 256M
max_connections = 50
EOF
sudo systemctl restart mysql
ps -o rss= -C mysqld
Nach dem Neustart belegte es 165 MB. Der Buffer Pool cacht Ihre Daten und Indizes, und 256 MB passen zu einem 2-GB-Server, auf dem auch die App läuft. Erhöhen Sie ihn, wenn die Datenbank die Hauptsache auf dem Server ist und größer als der Cache geworden ist. max_connections = 50 reicht für eine App mit Connection-Pool reichlich. Sie verlieren die Statistiken von performance_schema. Schalten Sie es wieder ein, wenn Sie langsame Abfragen einmal genau untersuchen müssen.
6. Nächtliche Backups
mysqldump --single-transaction zieht eine konsistente Kopie von InnoDB-Tabellen, ohne die App auszusperren. Packen Sie es in ein kleines Skript:
sudo tee /usr/local/bin/mysql-backup >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
umask 077
mkdir -p /var/backups/mysql
mysqldump --single-transaction --routines --triggers app | gzip > /var/backups/mysql/app-$(date +%F).sql.gz
find /var/backups/mysql -name 'app-*.sql.gz' -mtime +14 -delete
EOF
sudo chmod 755 /usr/local/bin/mysql-backup
echo '0 3 * * * root /usr/local/bin/mysql-backup' | sudo tee /etc/cron.d/mysql-backup
sudo /usr/local/bin/mysql-backup && sudo ls -l /var/backups/mysql
Jede Zeile hat ihren Grund:
umask 077macht den Dump nur für root lesbar (-rw-------), denn er enthält alle Ihre Daten.pipefaillässt das ganze Skript scheitern, wennmysqldumpscheitert. Ohne das würdegzipein winziges leeres Archiv schreiben und Erfolg melden. Wir haben den Befehl absichtlich kaputt gemacht, und das Skript endete wie gewünscht mit Code 2.find … -mtime +14 -deletehält zwei Wochen Kopien vor.- Das Skript läuft als root, also meldet sich
mysqldumpüber den Socket an, und kein Passwort liegt in einer Datei.
Ein Backup, das Sie nie wiederhergestellt haben, zählt noch nicht. Stellen Sie es in eine Testdatenbank wieder her und sehen Sie sich die Daten an:
sudo mysql -e "CREATE DATABASE app_restore"
gunzip -c /var/backups/mysql/app-2026-10-25.sql.gz | sudo mysql app_restore
sudo mysql -e "SHOW TABLES FROM app_restore"
sudo mysql -e "DROP DATABASE app_restore"
In unserem Test hatte die wiederhergestellte Tabelle dieselben Zeilen wie das Original. Kopien auf derselben Platte schützen Sie nicht, wenn der Server verloren geht, also holen Sie sie ab und zu mit scp oder restic auf einen anderen Rechner. Managed Backups ergänzen das um tägliche Wiederherstellungspunkte des ganzen Servers.
Welcher Tarif
Micro (2 vCPU, 2 GB, 25 GB, $5/Monat) trägt MySQL mit dieser Einstellung plus eine Web-App. Wächst die Datenbank selbst über ein paar Gigabyte, erlaubt Small mit 4 GB und 35 GB für $8/Monat einen Buffer Pool von 1 GB oder mehr. Beides sind NAT-Tarife, und der SSH-Tunnel aus Schritt 3 funktioniert dort. Schritt 4 braucht eine eigene IPv4: Micro-IP kostet $10/Monat.
Lieber PostgreSQL? Die PostgreSQL-Anleitung folgt demselben Aufbau. Alle Tarife finden Sie unter VPS, bezahlt wird in USDT, USDC oder ETH auf Base, Ethereum oder Polygon.
Kommentare
Noch keine Kommentare. Sei der Erste.