Datenbank
MariaDB + phpMyAdmin
Kompakte Datenbankverwaltung ohne Apache oder Nginx: Caddy übernimmt HTTPS und Auslieferung, PHP-FPM verarbeitet PHP, MariaDB stellt die Datenbank bereit.
1. Architektur
flowchart LR
Browser["Browser"] -->|"HTTPS · 443"| Caddy["Caddy
Reverse Proxy + Auto-TLS"]
Caddy -->|"Unix-Socket"| FPM["PHP-FPM"]
FPM --> PMA["phpMyAdmin"]
PMA -->|"127.0.0.1 : 3306"| DB[("MariaDB")]
classDef default fill:#112338,stroke:#45d3ff,stroke-width:1px,color:#dce8f5,rx:8,ry:8
classDef db fill:#0d1b2a,stroke:#7fffd4,stroke-width:1.5px,color:#dce8f5
class DB db
linkStyle default stroke:#45d3ff,stroke-width:1.5px,color:#91a7bd
db.example.de. Der DNS-Eintrag muss auf die öffentliche
IP-Adresse des VPS zeigen, bevor Caddy ein TLS-Zertifikat anfordern kann.
2. MySQL oder MariaDB?
MariaDB ist ein 2009 von den ursprünglichen MySQL-Gründern gestarteter Fork von
MySQL – als Reaktion auf die Übernahme von MySQL durch Sun und später Oracle.
Beide Systeme sprechen bis heute dasselbe Protokoll auf Port 3306
und nutzen dieselben Client-Bibliotheken (z. B. php-mysql), haben sich
seit MySQL 5.7/MariaDB 10.2 aber zunehmend auseinanderentwickelt.
| Kriterium | MySQL | MariaDB |
|---|---|---|
| Träger / Entwicklung | Oracle Corporation | MariaDB Foundation / MariaDB plc (community-getragen) |
| Lizenz | GPL (Community-Edition) plus kostenpflichtige, proprietäre Enterprise-Erweiterungen | Vollständig quelloffen (GPL), keine proprietäre Variante |
| Paketname unter Ubuntu/Debian | mysql-server |
mariadb-server – auf Debian seit einigen Jahren die Vorgabe, wenn mysql-server installiert wird |
| Kompatibilität | Referenzimplementierung des MySQL-Protokolls | Weitgehend Drop-in-kompatibel (gleicher Port, gleiche Clients), aber kein 100%iger Gleichlauf mehr in neueren Versionen |
| Storage-Engines | InnoDB (Standard), MyISAM | InnoDB, zusätzlich eigene Engines wie Aria, ColumnStore, Spider |
| Clustering | InnoDB Cluster / Group Replication | Galera Cluster nativ integriert |
| Feature-Roadmap | Eigenständig, z. B. MySQL 8.x/9.x | Eigenständig seit ca. Version 10.2/10.3, zunehmend abweichend von MySQL |
mysqldump bzw. mariadb-dump), da beide dasselbe
SQL-Dialekt-Fundament teilen. Bei Nutzung sehr neuer, versionsspezifischer
Funktionen (z. B. bestimmte JSON- oder Window-Funktionen) vorher die Kompatibilität
prüfen.
3. MariaDB und PHP installieren
sudo apt update
sudo apt install mariadb-server php-fpm php-mysql php-mbstring php-xml php-curl php-zip php-gd
Dienste aktivieren und direkt starten:
sudo systemctl enable --now mariadb
sudo systemctl enable --now php8.5-fpm
php8.3-fpm). Vorab prüfen und danach konsequent in allen
folgenden Befehlen verwenden.
systemctl list-unit-files | grep 'php.*fpm'
4. Editor-Grundlagen: nano und vim
nano zeigt die wichtigsten Tastenkombinationen permanent am unteren
Bildschirmrand an und eignet sich für schnelle Änderungen. vim ist auf
praktisch jedem Linux-System vorinstalliert und funktioniert auch dann zuverlässig,
wenn Copy & Paste in einer Konsole (z. B. VNC oder seriellen Konsole) nicht
verfügbar ist.
Anders als nano arbeitet vim modal: Der
Normalmodus ist der Startzustand zum Navigieren, mit
i/a/o wechselt man in den
Einfügemodus, mit : in den
Kommandozeilenmodus zum Speichern, Suchen/Ersetzen und Beenden.
| Taste / Befehl | Wirkung |
|---|---|
i | Einfügen vor der Cursorposition |
Esc | Zurück in den Normalmodus (immer zuerst drücken) |
:wq | Speichern und beenden |
:q! | Beenden ohne zu speichern |
dd | Aktuelle Zeile löschen |
u | Rückgängig |
/suchbegriff | Vorwärts suchen, weiter mit n |
:%s/alt/neu/g | Alle Vorkommen von „alt“ durch „neu“ ersetzen |
Beide Editoren sind für alle folgenden Konfigurationsschritte gleichwertig
einsetzbar; die Befehle in diesem Dokument zeigen nano, alternativ
funktioniert überall vim.
5. MariaDB grundlegend absichern
sudo mariadb-secure-installation
Üblicherweise sind folgende Einstellungen sinnvoll:
- Anonyme Benutzer entfernen
- Testdatenbank löschen
- Remote-Root-Login deaktivieren
- Berechtigungstabellen neu laden
6. Separaten Datenbankbenutzer anlegen
Öffne zunächst die MariaDB-Konsole:
sudo mariadb
Lege anschließend einen eigenen Administrator für phpMyAdmin an:
CREATE USER 'dbadmin'@'localhost'
IDENTIFIED BY 'EIN_SEHR_STARKES_PASSWORT';
GRANT ALL PRIVILEGES ON *.* TO 'dbadmin'@'localhost'
WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;
7. phpMyAdmin installieren
sudo apt install phpmyadmin
Während der Installation:
- Keinen Webserver auswählen
- Mit Tab zu „OK“ wechseln und bestätigen
- Einrichtung über dbconfig-common bestätigen
phpMyAdmin liegt anschließend in der Regel unter:
/usr/share/phpmyadmin
sudo systemctl disable --now apache2
sudo apt remove apache2
8. PHP-FPM-Socket prüfen
find /run/php -name '*.sock'
Eine typische Ausgabe lautet (Version entsprechend der eigenen Installation):
/run/php/php8.5-fpm.sock
Dienststatus kontrollieren:
sudo systemctl status php8.5-fpm
9. Caddy konfigurieren
Öffne die Caddy-Konfiguration:
sudo nano /etc/caddy/Caddyfile
# oder:
sudo vim /etc/caddy/Caddyfile
Minimale Konfiguration für eine eigene Subdomain:
db.example.de {
root * /usr/share/phpmyadmin
php_fastcgi unix//run/php/php8.5-fpm.sock
file_server
}
Konfiguration validieren und neu laden:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
Wichtige Caddyfile-Direktiven
| Direktive | Bedeutung |
|---|---|
root * <pfad> | Basisverzeichnis, aus dem file_server und php_fastcgi Dateien ausliefern. |
php_fastcgi <socket|adresse> | Leitet .php-Anfragen an PHP-FPM weiter, per Unix-Socket (unix//pfad) oder TCP (127.0.0.1:9000). |
file_server | Liefert statische Dateien (CSS, JS, Bilder) direkt aus root aus. |
basic_auth | Fragt vor jedem Zugriff Benutzername/Passwort ab, geprüft gegen einen mit caddy hash-password erzeugten Hash. |
header | Setzt zusätzliche HTTP-Antwort-Header, z. B. für Sicherheits-Policies. |
tls internal | Erzwingt ein lokal signiertes Zertifikat statt eines öffentlichen Let's-Encrypt-Zertifikats – nützlich für interne/Test-Domains ohne öffentliches DNS. |
encode gzip | Aktiviert Kompression der Antworten, reduziert Ladezeiten. |
log | Schreibt Zugriffslogs, standardmäßig nach stdout bzw. in den systemd-Journal-Log von Caddy. |
Alternative: Apache2 statt Caddy
sudo systemctl disable --now caddy.
sudo apt install apache2
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.5-fpm
Das PHP-FPM-Paket legt beim Installieren automatisch die Datei
/etc/apache2/conf-available/php8.5-fpm.conf an; a2enconf
aktiviert sie und verbindet Apache über proxy_fcgi mit dem PHP-FPM-Socket.
VirtualHost für phpMyAdmin anlegen:
sudo nano /etc/apache2/sites-available/db.example.de.conf
<VirtualHost *:80>
ServerName db.example.de
DocumentRoot /usr/share/phpmyadmin
<Directory /usr/share/phpmyadmin>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/db.example.de-error.log
CustomLog ${APACHE_LOG_DIR}/db.example.de-access.log combined
</VirtualHost>
sudo a2ensite db.example.de.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
Anders als Caddy stellt Apache kein automatisches HTTPS bereit. Ein Zertifikat lässt sich über Certbot einrichten, das den VirtualHost passend ergänzt:
sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d db.example.de
Wichtige Apache-Direktiven
| Direktive | Bedeutung |
|---|---|
DocumentRoot | Basisverzeichnis der ausgelieferten Website, entspricht Caddys root *. |
<Directory> | Blockweise Rechte- und Optionszuweisung für ein Verzeichnis, z. B. AllowOverride für .htaccess. |
Require all granted | Erlaubt den Zugriff für alle Clients (Apache-2.4-Syntax, ersetzt das alte Allow from all). |
ProxyPassMatch / SetHandler "proxy:unix:..." | Alternative Wege, .php-Anfragen an PHP-FPM weiterzuleiten, falls a2enconf php-fpm nicht greift. |
AuthType Basic / AuthUserFile | Aktiviert Basic Auth in Kombination mit einer per htpasswd erzeugten Passwortdatei – das Apache-Äquivalent zu Caddys basic_auth. |
Alternative: Nginx statt Caddy
sudo systemctl disable --now caddy.
sudo apt install nginx
Server-Block für phpMyAdmin anlegen:
sudo nano /etc/nginx/sites-available/db.example.de
server {
listen 80;
server_name db.example.de;
root /usr/share/phpmyadmin;
index index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
}
sudo ln -s /etc/nginx/sites-available/db.example.de /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Auch Nginx liefert kein automatisches HTTPS – ein Zertifikat lässt sich ebenfalls über Certbot einrichten:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d db.example.de
Wichtige Nginx-Direktiven
| Direktive | Bedeutung |
|---|---|
root | Basisverzeichnis der ausgelieferten Website, entspricht Caddys root *. |
index | Datei, die bei Verzeichnisaufrufen ohne Dateiname ausgeliefert wird (hier index.php). |
location | Regelblock für passende URL-Pfade oder -Muster, vergleichbar mit Caddys Matcher-Syntax. |
fastcgi_pass | Leitet .php-Anfragen an PHP-FPM weiter, per Unix-Socket oder TCP – Nginx-Pendant zu Caddys php_fastcgi. |
fastcgi_param SCRIPT_FILENAME | Teilt PHP-FPM den vollständigen Dateipfad des aufzurufenden Skripts mit; ohne diesen Parameter schlägt die Ausführung fehl. |
try_files | Prüft nacheinander mehrere Pfade/Dateien und liefert die erste passende aus, sonst 404 – hier das Nginx-Äquivalent zu Caddys file_server. |
auth_basic / auth_basic_user_file | Aktiviert Basic Auth gegen eine per htpasswd erzeugte Datei – das Nginx-Äquivalent zu Caddys basic_auth. |
10. Zugriff zusätzlich schützen
phpMyAdmin sollte nicht ohne zusätzliche Schutzschicht frei im Internet erreichbar sein.
Passwort-Hash erzeugen
caddy hash-password
Caddy mit Basic Auth
db.example.de {
basic_auth {
USERNAME DEIN_PASSWORT_HASH
}
root * /usr/share/phpmyadmin
php_fastcgi unix//run/php/php8.5-fpm.sock
file_server
header {
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
Referrer-Policy same-origin
}
}
USERNAME steht für den gewünschten Basic-Auth-Login (frei wählbar,
unabhängig vom Linux- oder Datenbankbenutzer), DEIN_PASSWORT_HASH für
die Ausgabe von caddy hash-password. Beide vor dem Einsatz durch
echte Werte ersetzen.
Anschließend erneut prüfen und laden:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
11. MariaDB-Konfiguration prüfen und anpassen
sudo ss -lntp | grep 3306
Optimal ist eine Bindung ausschließlich an die lokale Adresse:
127.0.0.1:3306
Falls MariaDB extern lauscht, prüfe folgende Datei:
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
# oder:
sudo vim /etc/mysql/mariadb.conf.d/50-server.cnf
Danach MariaDB neu starten:
sudo systemctl restart mariadb
Wichtige Direktiven in 50-server.cnf
| Direktive | Empfehlung | Bedeutung |
|---|---|---|
bind-address |
127.0.0.1 | Bindet MariaDB an die lokale Adresse; von außen ist der Port dann nicht erreichbar. Zugriff von entfernten Anwendungen läuft stattdessen über SSH-Tunnel oder ein privates Netzwerk. |
port |
3306 | TCP-Port des Datenbankdiensts. Nur relevant, wenn bind-address nicht auf 127.0.0.1 steht bzw. für lokale TCP-Verbindungen. |
socket |
/run/mysqld/mysqld.sock | Pfad zum Unix-Socket für lokale Verbindungen ohne TCP – schneller als 127.0.0.1 und von bind-address unabhängig. |
datadir |
/var/lib/mysql | Speicherort aller Datenbankdateien. Bei Änderung müssen Dateirechte und AppArmor/SELinux-Profile angepasst werden. |
max_connections |
151 (Standard) oder höher | Maximale Anzahl gleichzeitiger Client-Verbindungen. Bei vielen parallelen Anwendungen ggf. erhöhen, erhöht aber auch den RAM-Bedarf. |
innodb_buffer_pool_size |
ca. 60–70 % des verfügbaren RAM (dediziert) | Cache für InnoDB-Tabellen und -Indizes im Arbeitsspeicher. Wichtigster Wert für die Performance, auf kleinen VPS aber konservativ wählen. |
character-set-server / collation-server |
utf8mb4 / utf8mb4_unicode_ci | Standard-Zeichensatz neuer Datenbanken. utf8mb4 unterstützt im Gegensatz zum alten utf8 auch Emojis und den vollen Unicode-Bereich. |
skip-networking |
nicht gesetzt (aus) | Würde TCP/IP komplett deaktivieren und nur noch Unix-Socket-Verbindungen erlauben – für einen reinen Localhost-Betrieb eine zusätzliche Alternative zu bind-address. |
slow_query_log / long_query_time |
1 / 2 (Sekunden) | Protokolliert Abfragen, die länger als long_query_time dauern, in slow_query_log_file – hilfreich zur Performance-Analyse. |
log_error |
/var/log/mysql/error.log | Pfad der Fehlerprotokolldatei, erste Anlaufstelle bei Startproblemen. |
innodb_buffer_pool_size oder max_connections
ohne Rücksicht auf den tatsächlich verfügbaren RAM können auf kleinen VPS-Instanzen
zu Out-of-Memory-Abbrüchen führen. Werte schrittweise erhöhen und Speicherauslastung
beobachten.
12. Fehlersuche
Caddy-Protokoll
sudo journalctl -u caddy -f
PHP-FPM-Protokoll
sudo journalctl -u php8.5-fpm -f
MariaDB-Protokoll
sudo journalctl -u mariadb -f
Aktive Dienste prüfen
systemctl status caddy mariadb php8.5-fpm
Caddy-Konfiguration formatieren
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
13. Abschlusscheck
- DNS-Subdomain zeigt auf die öffentliche VPS-IP
- Caddy läuft und besitzt ein gültiges HTTPS-Zertifikat
- PHP-FPM-Socket stimmt mit der Caddy-Konfiguration überein
- phpMyAdmin öffnet sich über die gewünschte Subdomain
- Basic Auth oder eine IP-Beschränkung ist aktiv
- MariaDB lauscht nur auf 127.0.0.1:3306
- Für Anwendungen werden separate DB-Benutzer verwendet
- Regelmäßige Datenbank-Backups sind eingerichtet