MariaDB und MySQL absichern: die Schritte nach der Installation
Nach dem Paketinstall ist eine Datenbank noch nicht sicher. Dieser Leitfaden geht mysql_secure_installation durch, klärt die unix_socket-Frage und zeigt eigene Benutzer je Anwendung.
Eine frisch installierte Datenbank auf einem Rootserver ist selten so unsicher, wie ältere Anleitungen behaupten, und selten so sicher, wie das Paketsystem suggeriert. Zwischen diesen beiden Polen liegen genau die Handgriffe, die dieser Artikel beschreibt: was mysql_secure_installation tatsächlich erledigt, warum die unix_socket-Frage auf modernen Systemen anders zu beantworten ist als 2015, wie ein Anwendungsbenutzer mit minimalen Rechten aussieht und wie man Passwörter aus der Prozessliste heraushält.
Alle Befehle laufen als root. Wer mit einem normalen Benutzer arbeitet, stellt sudo voran. Die Ausgaben stammen von Debian 13 und Debian 12 sowie Ubuntu 24.04 und Ubuntu 22.04.
Ausgangslage: welches Paket auf welcher Distribution läuft
Der erste Stolperstein liegt vor dem ersten Sicherheitsschritt. Debian liefert seit Jahren kein eigenes Paket namens mysql-server mehr. Der Name existiert dort nur noch als virtuelles Paket ohne eigene Version, sichtbar allein über die Abhängigkeiten von mariadb-server:
apt-cache policy mysql-server
mysql-server:
Installed: (none)
Candidate: (none)
Version table:
Dieser Versionsvergleich liefert also nur unter Ubuntu ein Ergebnis, dort 8.0.46 sowohl auf 24.04 als auch auf 22.04. Auf Debian nimmt man stattdessen apt-cache showpkg mysql-server, das den virtuellen Charakter des Namens sichtbar macht.
Auf Debian ist die Datenbank damit immer MariaDB. Auf Ubuntu gibt es beide, und man muss sich entscheiden. Die Fassungen der aktuellen Distributionen:
| Distribution | mariadb-server | mysql-server |
| Debian 13 | 11.8 | nur virtueller Name, keine Version |
| Debian 12 | 10.11 | nur virtueller Name, keine Version |
| Ubuntu 24.04 | 10.11 | 8.0.46 |
| Ubuntu 22.04 | 10.6 | 8.0.46 |
Installiert wird wie gewohnt:
apt update
apt install -y mariadb-server
Ob man wirklich die erwartete Fassung erwischt hat, klärt nicht die Paketversion allein, sondern der laufende Server:
mariadb -e "SELECT @@version, @@version_comment;"
Der zweite Stolperstein ist der Programmname. Ab MariaDB 11.0 liegen die MySQL-kompatiblen Namen nicht mehr im Hauptpaket, sondern in mariadb-client-compat und mariadb-server-compat. Auf Debian 13 kann ein mysql --version deshalb entweder mit einer Warnung antworten oder gar nicht existieren:
mysql: Deprecated program name. It will be removed in a future release, use '/usr/bin/mariadb' instead
bash: mysql: command not found
Wer Skripte schreibt, die auf allen vier Systemen laufen sollen, nutzt unter MariaDB durchgängig mariadb, mariadb-dump und mariadb-secure-installation. Diese Namen existieren seit MariaDB 10.5, also auch auf Ubuntu 22.04.
mysql_secure_installation Schritt für Schritt
Das Werkzeug heißt je nach Server anders. Unter MariaDB ist der kanonische Name mariadb-secure-installation, unter MySQL 8.0 bleibt es mysql_secure_installation. Den alten Namen gibt es unter MariaDB auf Debian 12 sowie auf Ubuntu 24.04 und 22.04 weiterhin als Symlink, auf Debian 13 dagegen nicht mehr: dort existiert ausschließlich mariadb-secure-installation.
Ein Blick auf die Optionen lohnt sich, denn das Programm akzeptiert unter anderem --defaults-file, --socket und --protocol. Diese Übersicht steht allerdings nur im Handbuch:
man mariadb-secure-installation
Ein --help gibt es nämlich nicht. Das Skript wertet Argumente überhaupt nicht aus, es verschluckt den unbekannten Schalter stillschweigend und startet sofort den interaktiven Ablauf. Fehlt dabei eine echte Konsole, etwa in einer Pipeline oder in einem Container ohne Terminal, wiederholt es die Rückfrage nach dem Passwort endlos und kehrt nie von selbst zurück. Aufgerufen wird deshalb ohne Argument und in einer interaktiven Shell:
mariadb-secure-installation
Auf Debian 13 stellt das Skript dem Ablauf einen deutlichen Hinweis voran:
NOTE: MariaDB is secure by default in Debian. Running this script is useless at best,
and misleading at worst. This script will be removed in a future MariaDB release in Debian.
Debian hält den Durchlauf dort also für überflüssig und wird das Skript in einer künftigen Fassung entfernen, nachzulesen in /usr/share/doc/mariadb-server/README.Debian.gz. Die folgenden Schritte lohnen trotzdem, denn sie zeigen, was geprüft wird und warum auf einem aktuellen System kaum noch etwas zu ändern ist.
Der Ablauf beginnt mit der Frage nach dem Passwort für root. Der Wortlaut hängt von der Fassung des Skripts ab:
Enter current password for root (enter for none):
Neuere Fassungen fragen stattdessen:
Enter root user password or leave blank:
Gemeint ist beide Male dasselbe. Auf einer frischen Installation gibt es kein Passwort, hier drückt man einfach Enter.
Danach folgen die eigentlichen Entscheidungen. Die Reihenfolge und der Wortlaut unterscheiden sich zwischen MariaDB und MySQL, inhaltlich geht es um dieselben fünf Punkte.
Die unix_socket-Frage
Bei MariaDB erscheint als nächstes:
Switch to unix_socket authentication [Y/n]
Diese Frage verwirrt, weil sie auf allen hier behandelten Systemen bereits beantwortet ist. Seit MariaDB 10.4 ist root@localhost von Haus aus über das Plugin unix_socket abgesichert, und das gilt für 10.6 auf Ubuntu 22.04 genauso wie für 11.8 auf Debian 13. Bei MySQL 8.0 heißt das Gegenstück auth_socket, und der Assistent sagt das auch offen:
Skipping password set for root as authentication with auth_socket is used by default.
Praktisch bedeutet das: Wer als Systembenutzer root angemeldet ist, kommt mit mariadb ohne Passwort in die Datenbank. Wer es nicht ist, kommt gar nicht hinein, auch nicht mit dem richtigen Passwort. Das ist kein Mangel, sondern die stärkere Variante. Es gibt kein Passwort, das aus einem Backup, einer Konfigurationsdatei oder einem Screenshot abfließen kann. Die Antwort auf die Frage lautet also Ja beibehalten, und ein zusätzliches root-Passwort ist auf einem einzelnen Anwendungsserver überflüssig.
Prüfen lässt sich der Zustand nur an der echten Tabelle. Die naheliegende Abfrage SELECT user, host, plugin FROM mysql.user führt hier nämlich in die Irre: sie zeigt bei root den Wert mysql_native_password, obwohl in Wirklichkeit unix_socket greift. Bei MariaDB ab 10.4 ist mysql.user nur noch eine Sicht auf mysql.global_priv, und diese Sicht kennt pro Konto nur eine einzige Authentifizierungsmethode. Wer sich darauf verlässt, hält den Server fälschlich für passwortauthentifiziert. Die vollständige Regel steht im JSON-Feld Priv der echten Tabelle:
mariadb -e "SELECT User, Host, JSON_DETAILED(Priv) FROM mysql.global_priv;"
Für root auf localhost steht dort unter MariaDB sinngemäß:
{"plugin":"mysql_native_password","authentication_string":"invalid","auth_or":[{},{"plugin":"unix_socket"}]}
Der erste Eintrag ist die Passwortmethode gegen den unbrauchbaren Hash der Zeichenkette invalid, den niemand treffen kann. Der zweite Eintrag unter auth_or ist die tatsächlich greifende Socketauthentifizierung. Kompakter fragt man beides so ab:
mariadb -e "SELECT User, Host, JSON_VALUE(Priv,'$.plugin') AS plugin, JSON_QUERY(Priv,'$.auth_or') AS auth_or FROM mysql.global_priv;"
Erwartet wird bei root und localhost ein unix_socket, wenn nicht in der Spalte plugin, dann unter auth_or. Steht dort ausschließlich eine Passwortmethode und nichts unter auth_or, arbeitet das Konto rein mit Passwort. Unter MySQL 8.0 gibt es mysql.global_priv nicht, dort ist mysql.user eine echte Tabelle und die Spalte plugin muss auth_socket zeigen. Aus der MariaDB-Sicht lesen kann man übrigens weiterhin, hineinschreiben nicht mehr.
Nur wenn ein Werkzeug zwingend ein Passwort braucht, etwa ein Monitoring, das nicht als root läuft, stellt man um. Sinnvoller ist es dann aber, einen zweiten Administrationsbenutzer anzulegen, statt root umzuwidmen. In MariaDB ab 11.6, also auch in 11.8 auf Debian 13, lässt sich ein Konto zusätzlich an einen bestimmten Systembenutzer binden:
CREATE USER 'dbadmin'@'localhost' IDENTIFIED VIA unix_socket AS 'deploy';
Damit darf sich der Systembenutzer deploy als Datenbankbenutzer dbadmin anmelden, ohne dass die Namen übereinstimmen müssen. Auf Debian 12 und den Ubuntu-Fassungen wird die Zeichenkette nach AS noch ignoriert, dort müssen Systembenutzer und Datenbankbenutzer gleich heißen.
Die vier verbleibenden Fragen
Der Rest ist unstrittig und wird durchgehend mit Ja beantwortet: anonyme Benutzer entfernen, root-Anmeldung aus der Ferne verbieten, die Datenbank test samt Rechten entfernen, Rechtetabellen neu laden. Auf einem aktuellen Debian oder Ubuntu sind anonyme Benutzer und die Testdatenbank meist ohnehin nicht angelegt, das Skript meldet dann schlicht, dass nichts zu tun war.
Bei MySQL 8.0 kommt eine Frage hinzu, die MariaDB nicht kennt:
Would you like to setup VALIDATE PASSWORD component?
Diese Komponente erzwingt Mindestanforderungen an alle künftig gesetzten Passwörter. Sie ist nützlich, wenn mehrere Personen Benutzer anlegen. Sie ist lästig, wenn ein Provisionierungsskript zufällige Passwörter erzeugt, die aus Versehen kein Sonderzeichen enthalten. Dann bricht das Skript ab mit:
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
Wer sie aktiviert, sollte den Passwortgenerator vorher darauf einstellen. Die Standardstufe ist MEDIUM und verlangt mindestens acht Zeichen, Groß- und Kleinbuchstaben, Ziffer und Sonderzeichen.
Wenn es schiefgeht: zurück in die Datenbank
Der häufigste Weg, sich auszusperren, ist der gut gemeinte Wechsel von unix_socket auf ein Passwort, das dann verloren geht. Oder umgekehrt: Ein altes Skript legt /etc/mysql/debian.cnf neu an, und plötzlich passt nichts mehr zusammen. Die Fehlermeldungen, nach denen dann gesucht wird, lauten:
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
ERROR 1524 (HY000): Plugin 'unix_socket' is not loaded
Fehler 1698 heißt: Das Konto erwartet unix_socket, du bist aber nicht der passende Systembenutzer. Ein sudo davor löst das oft schon. Fehler 1045 heißt: Es wird ein Passwort erwartet und deines stimmt nicht.
Kommt man gar nicht mehr hinein, startet man den Server ohne Rechteprüfung. Bei MariaDB geht das sauber über die Umgebungsvariable, die die mitgelieferte systemd-Unit auswertet, ganz ohne Bearbeitung von Paketdateien:
systemctl stop mariadb
systemctl set-environment MYSQLD_OPTS="--skip-grant-tables --skip-networking"
systemctl start mariadb
Jetzt verbindet man sich mit mariadb -u root und setzt den Zustand zurück. Wichtig ist das FLUSH PRIVILEGES vorweg, denn ohne geladene Rechtetabellen scheitert ALTER USER:
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED VIA unix_socket;
Danach unbedingt aufräumen, sonst startet der Server nach jedem Reboot ungeschützt:
systemctl stop mariadb
systemctl unset-environment MYSQLD_OPTS
systemctl start mariadb
Bei MySQL 8.0 auf Ubuntu funktioniert dieser Weg nicht, weil die Unit keine solche Variable auswertet und weil ALTER USER unter --skip-grant-tables zusätzliche Fallstricke hat. Dort nimmt man eine Startdatei. Sie muss in einem Verzeichnis liegen, das AppArmor dem Serverprozess erlaubt, andernfalls scheitert der Start mit Can't open file. /var/lib/mysql-files ist erlaubt, /tmp nicht:
systemctl stop mysql
echo "ALTER USER 'root'@'localhost' IDENTIFIED WITH auth_socket;" > /var/lib/mysql-files/reset.sql
chown mysql:mysql /var/lib/mysql-files/reset.sql
systemctl edit mysql
In den Editor kommt eine Überschreibung des Startbefehls, die leere erste Zeile ist notwendig, um den Originalwert zu löschen:
[Service]
ExecStart=
ExecStart=/usr/sbin/mysqld --init-file=/var/lib/mysql-files/reset.sql
Nach systemctl daemon-reload und einem Start ist das Konto zurückgesetzt. Anschließend die Überschreibung mit systemctl revert mysql entfernen und die Datei löschen. Wer Datenbanken auf getrennten Systemen betreibt, findet ergänzende Hinweise zur Absicherung des Zugangs im Beitrag SSH-Server absichern.
Ein eigener Benutzer je Anwendung statt root
Der wirksamste Schritt kommt in keinem Assistenten vor. Anwendungen dürfen sich nicht als root verbinden, und sie brauchen auch kein GRANT ALL. Eine typische Webanwendung liest und schreibt Zeilen, sie legt keine Datenbanken an und sie liest keine Dateien vom Server.
CREATE DATABASE shopdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'shopapp'@'localhost' IDENTIFIED BY 'HierEinLangesZufallspasswort';
GRANT SELECT, INSERT, UPDATE, DELETE ON shopdb.* TO 'shopapp'@'localhost';
Drei Dinge sind daran wichtig. Erstens der Punkt in shopdb.* statt *.*: Rechte auf *.* sind globale Rechte und gelten auch für mysql und information_schema. Zweitens die Angabe @'localhost' statt @'%': Damit ist das Konto ausschließlich lokal nutzbar, selbst wenn der Port später einmal offen steht. Drittens fehlt WITH GRANT OPTION, denn ein Konto, das Rechte weitergeben kann, ist faktisch ein Administrator.
Schemaänderungen laufen dann über ein zweites Konto, das nur beim Deployment verwendet wird:
CREATE USER 'shopmigrate'@'localhost' IDENTIFIED BY 'EinAnderesLangesZufallspasswort';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, INDEX, REFERENCES ON shopdb.* TO 'shopmigrate'@'localhost';
Das klingt nach Mehraufwand und ist genau der Punkt, an dem eine SQL-Injection in der Anwendung zum ärgerlichen Datenleck statt zum Totalverlust wird. Ein Konto ohne DROP kann keine Tabelle löschen.
Kontrolliert wird nicht am Wortlaut des GRANT, sondern am Ergebnis:
SHOW GRANTS FOR 'shopapp'@'localhost';
Erwartet wird genau zwei Zeilen: ein GRANT USAGE ON *.*, das lediglich das Anmelderecht darstellt und keinerlei Datenzugriff bedeutet, und die Zeile mit den vier Rechten auf shopdb.*. Taucht dort ALL PRIVILEGES ON *.* auf, war der Punkt an der falschen Stelle. Die zweite, aussagekräftigere Probe ist eine Anmeldung mit dem neuen Konto und ein SHOW DATABASES;. Sichtbar sein dürfen nur information_schema und shopdb.
Ein häufiger Fehler beim Anlegen:
ERROR 1396 (HY000): Operation CREATE USER failed for 'shopapp'@'localhost'
Das heißt fast immer, dass das Konto bereits existiert, oft als Überbleibsel eines früheren Versuchs. DROP USER 'shopapp'@'localhost'; und noch einmal von vorn.
bind-address: wo die Datenbank überhaupt lauscht
Auf allen vier Distributionen lauscht die Datenbank nach der Paketinstallation nur auf 127.0.0.1. Die Zeile steht bei MariaDB in /etc/mysql/mariadb.conf.d/50-server.cnf und bei MySQL 8.0 in /etc/mysql/mysql.conf.d/mysqld.cnf. Nachsehen statt vermuten:
grep -R "bind-address" /etc/mysql/
Bei MySQL 8.0 gibt es eine zweite Zeile, die gern übersehen wird: mysqlx-bind-address steuert das X-Protokoll auf Port 33060. Wer nur bind-address ändert, öffnet unter Umständen nur den halben Zugang oder lässt den zweiten Port offen.
Die verlässlichste Prüfung ist nicht die Konfigurationsdatei, sondern der Kernel:
ss -lntp
LISTEN 0 80 127.0.0.1:3306 0.0.0.0:* users:(("mariadbd",pid=712,fd=22))
Steht dort 0.0.0.0:3306 oder *:3306, ist der Dienst im Netz erreichbar. Ergänzend liefert der Server seine eigene Sicht:
mariadb -e "SELECT @@bind_address, @@port, @@skip_networking;"
Zwei Fallen sind hier verbreitet. Die erste: Die Dateien in mariadb.conf.d werden in alphabetischer Reihenfolge gelesen, und die zuletzt gelesene Angabe gewinnt. Wer seine Änderung in eine eigene Datei schreibt, nennt sie deshalb 99-eigene.cnf und nicht 10-eigene.cnf. Genau daran scheitern die meisten Berichte, in denen MariaDB angeblich bind-address ignoriert. Der Vorteil einer eigenen Datei: Paketaktualisierungen fragen nicht nach Konfliktlösung, weil die mitgelieferte Datei unangetastet bleibt.
Die zweite Falle: Wer den Netzwerkzugang gar nicht braucht, geht einen Schritt weiter als bind-address und setzt skip-networking. Dann existiert kein TCP-Port mehr, nur noch der Unix-Socket. Das ist die richtige Einstellung für den Standardfall Webanwendung und Datenbank auf demselben Server, kostet aber Nerven, wenn eine Anwendung in der Konfiguration 127.0.0.1 stehen hat statt localhost: Bei 127.0.0.1 erzwingen die Clientbibliotheken TCP.
Zugriff von außen nur, wenn es wirklich nötig ist
Ein Datenbankport im offenen Netz wird innerhalb von Stunden gefunden und dauerhaft durchprobiert. Die beste Antwort auf die Frage nach externem Zugriff ist deshalb, ihn zu vermeiden. Für gelegentliche Wartung reicht ein SSH-Tunnel, der auf dem eigenen Rechner einen lokalen Port auf den Datenbanksocket der Gegenstelle legt. Das Datenbankwerkzeug verbindet sich dann gegen 127.0.0.1, ohne dass der Server im Netz etwas öffnet.
Für dauerhafte Verbindungen zwischen mehreren Servern ist ein WireGuard-Tunnel die saubere Lösung. Die Datenbank bindet dann ausschließlich an die Tunneladresse, nicht an die öffentliche IP-Adresse.
Wenn es doch ein offener Port sein muss, greifen vier Maßnahmen zusammen. Der Server bindet an genau eine interne Adresse. Die Firewall lässt nur die bekannte Quelladresse durch. Das Datenbankkonto ist an dieselbe Adresse gebunden, also 'shopapp'@'10.0.0.5' und niemals 'shopapp'@'%'. Und die Verbindung wird verschlüsselt erzwungen:
ALTER USER 'shopapp'@'10.0.0.5' REQUIRE SSL;
Beim Testen von außen begegnen einem zwei Fehler, die oft verwechselt werden. Der erste bedeutet, dass niemand antwortet, also Firewall oder bind-address:
ERROR 2003 (HY000): Can't connect to MySQL server on '203.0.113.10:3306' (110)
Der zweite bedeutet, dass der Server antwortet und die Verbindung bewusst ablehnt, also fehlt das passende Konto für diese Herkunft:
ERROR 1130 (HY000): Host '203.0.113.55' is not allowed to connect to this MariaDB server
Lokal wiederum ist der Klassiker, dass der Dienst schlicht nicht läuft:
ERROR 2002 (HY000): Can't connect to local server through socket '/run/mysqld/mysqld.sock' (2)
Passwörter nicht auf der Kommandozeile
Der Aufruf mariadb -u shopapp -pGeheim123 funktioniert und ist trotzdem ein Fehler. Der Server sagt es selbst:
Warning: Using a password on the command line interface can be insecure.
Zwei Gründe stehen dahinter. Erstens landet die Zeile in der Shell-Historie. Zweitens ist die Kommandozeile eines Prozesses auf einem Standardsystem für jeden angemeldeten Benutzer über ps sichtbar. Auf einem Server mit mehreren Kunden oder mehreren Diensten ist das ein Passwortabzug ohne Aufwand.
Der richtige Weg für Menschen ist -p ohne Anhang. Dann wird interaktiv gefragt, und nichts steht in der Historie:
mariadb -u shopapp -p shopdb
Der richtige Weg für Skripte und Cronjobs ist eine Optionsdatei mit engen Rechten. Anlegen mit korrektem Modus in einem Schritt:
install -m 600 /dev/null /root/.my.cnf
Inhalt:
[client]
user=backup
password=HierEinLangesZufallspasswort
Danach findet jeder Client die Zugangsdaten selbst. Für getrennte Aufgaben legt man mehrere Dateien an und verweist gezielt darauf. Dabei gilt eine Regel, an der viele scheitern: --defaults-extra-file und --defaults-file müssen die erste Option des Aufrufs sein, sonst werden sie kommentarlos ignoriert.
mariadb-dump --defaults-extra-file=/root/.my-backup.cnf --single-transaction shopdb
Die Umgebungsvariable MYSQL_PWD ist keine Lösung. Sie steht in /proc und ist damit ähnlich sichtbar wie die Kommandozeile. Unter MySQL 8.0 gibt es zusätzlich mysql_config_editor, das eine Datei ~/.mylogin.cnf schreibt. Der Inhalt ist verschleiert, aber nicht verschlüsselt, und MariaDB kennt das Werkzeug nicht. Auf gemischten Umgebungen ist die einfache Optionsdatei mit Modus 600 die verlässlichere Wahl.
Ein letzter Punkt betrifft Backups. Ein Dump enthält alles, was die Anwendung sieht, und ein Backupkonto braucht dafür keine Schreibrechte. Für mariadb-dump mit --single-transaction genügt in der Regel:
GRANT SELECT, SHOW VIEW, TRIGGER, LOCK TABLES ON shopdb.* TO 'backup'@'localhost';
GRANT PROCESS ON *.* TO 'backup'@'localhost';
Abnahme: woran man erkennt, dass es sitzt
Ein Befehl, der ohne Fehler durchläuft, beweist nichts. Diese sechs Proben beweisen etwas:
- Das root-Konto nutzt Socketauthentifizierung:
mariadb -e "SELECT User, Host, JSON_VALUE(Priv,'$.plugin') AS plugin, JSON_QUERY(Priv,'$.auth_or') AS auth_or FROM mysql.global_priv;"zeigt beirooteinunix_socket, entweder in der Spaltepluginoder unterauth_or. Die Sichtmysql.usertaugt dafür nicht, sie gibt nur die erste Methode aus. Unter MySQL 8.0 ist umgekehrt die Spalteplugininmysql.usermaßgeblich, dort mussauth_socketstehen. - Es gibt keine anonymen Konten:
mariadb -e "SELECT user, host FROM mysql.user WHERE user = '';"liefert eine leere Ergebnismenge. - Die Testdatenbank ist weg:
mariadb -e "SHOW DATABASES LIKE 'test';"liefert nichts. - Der Port ist zu:
ss -lntpzeigt für 3306 entweder gar nichts oder ausschließlich127.0.0.1. - Das Anwendungskonto ist eingeschränkt: Eine Anmeldung damit zeigt bei
SHOW DATABASES;nur die eigene Datenbank, und einDROP TABLEscheitert. - Kein Passwort im Klartext unterwegs:
grep -rs "password" /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/ /etc/cron.weekly/ /etc/cron.monthly/findet nichts, ebenso wenigcrontab -lfür root und ein Blick in/var/spool/cron/crontabs/, und die Optionsdateien haben Modus 600. Der Schalter-sgehört dazu, weil ein fehlendes Verzeichnis den Aufruf sonst mit Exitcode 2 abbricht: auf Debian 13 existiert/etc/cron.dnach einer reinen Datenbankinstallation nicht, dort ist noch gar kein cron-Paket installiert.
Wer diese sechs Punkte auf einem neuen Server abarbeitet, hat die überwiegende Mehrheit der Angriffe gegen Datenbanken bereits ausgeschlossen, ohne eine einzige zusätzliche Software zu installieren. Der Rest ist Aktualisierungsdisziplin und ein funktionierendes Backup, dessen Wiederherstellung mindestens einmal geprobt wurde.
Häufige Fragen
Brauche ich unter MariaDB überhaupt noch ein root-Passwort?
Warum sagt mein Debian, dass es das Paket mysql-server nicht gibt?
Wie komme ich wieder in die Datenbank, wenn ich mich ausgesperrt habe?
Was bedeutet ERROR 1698 gegenüber ERROR 1045?
Reicht bind-address = 127.0.0.1 aus, um die Datenbank abzusichern?
Warum soll die Anwendung nicht als root auf die Datenbank zugreifen?
Wie übergebe ich einem Cronjob ein Datenbankpasswort sicher?
2026 KernelHost GmbH. Alle Rechte vorbehalten. Diese Anleitung ist urheberrechtlich geschützt. Eine Veröffentlichung auf anderen Webseiten, auch auszugsweise oder in bearbeiteter Form, ist ohne unsere schriftliche Zustimmung nicht gestattet. Zitate mit Quellenangabe und Link sind ausdrücklich willkommen.

