29. September, 2025

WordPress absichern in der Schweiz: Podman, Traefik und Fail2Ban inkl. Cockpit für maximale Sicherheit

Zunehmende Angriffe auf Webseiten machen verstärkte Wartung und präventive Sicherheitsmaßnahmen notwendig – damit es nicht mühsam wird, findest Du hier eine einfache Anleitung.

Ich zeige Dir, wie Du auf einem Ubuntu-Server WordPress mit Podman (rootless = sicherer, isolierter Betrieb) startest, mit Cockpit verwaltest, über Traefik automatisch per HTTPS veröffentlichst und mit Fail2Ban absicherst.
Alle Konfigurationen sind auf die Zeitzone Europe/Zurich abgestimmt.

Fertige Pakete kannst Du auch bei mir buchen: https://cloudmeister.services

1. Vorbereitung & System

Einloggen als ubuntu-User (Standard bei Ubuntu-Servern). System updaten und Zeitzone setzen:

sudo apt update && sudo apt upgrade -y
sudo timedatectl set-timezone Europe/Zurich

2. WordPress mit Podman (rootless, Dateien unter /srv)

WordPress und MariaDB laufen in einem gemeinsamen Pod. Die Web-Dateien liegen unter /srv/wordpress, die DB-Daten unter /srv/wp-db.

# Verzeichnisse anlegen und Berechtigungen setzen
sudo mkdir -p /srv/wp-db /srv/wordpress
sudo chown -R $USER:$USER /srv/wp-db /srv/wordpress

# Pod erstellen (rootless), WordPress intern auf Port 80, extern 8080
podman pod create --name wp -p 8080:80

# MariaDB starten (persistente Daten in /srv/wp-db)
podman run -d --pod wp --name wp-db \
  -e MYSQL_ROOT_PASSWORD=geheim \
  -e MYSQL_DATABASE=wordpress \
  -e MYSQL_USER=wpuser \
  -e MYSQL_PASSWORD=wppass \
  -v /srv/wp-db:/var/lib/mysql \
  mariadb:10.11

# WordPress starten (Code/Uploads in /srv/wordpress)
podman run -d --pod wp --name wordpress \
  -e WORDPRESS_DB_HOST=127.0.0.1 \
  -e WORDPRESS_DB_USER=wpuser \
  -e WORDPRESS_DB_PASSWORD=wppass \
  -e WORDPRESS_DB_NAME=wordpress \
  -v /srv/wordpress:/var/www/html \
  wordpress:latest

# Test
# http://<SERVER-IP>:8080

3. Cockpit Web-GUI

Cockpit ist die Admin-Oberfläche für Server und Container (inkl. Podman-Plugin).

sudo apt install -y cockpit cockpit-podman
sudo systemctl enable --now cockpit.socket
# Zugriff: https://<SERVER-IP>:9090

4. Traefik als Reverse Proxy

Traefik läuft rootful und bindet Ports 80/443 (Let’s Encrypt). WordPress bleibt rootless auf Port 8080.

sudo mkdir -p /etc/traefik/dynamic
sudo touch /etc/traefik/acme.json
sudo chmod 600 /etc/traefik/acme.json

/etc/traefik/traefik.yml:

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

providers:
  file:
    directory: "/etc/traefik/dynamic"
    watch: true

certificatesResolvers:
  letsencrypt:
    acme:
      email: deine-mail@example.com
      storage: /etc/traefik/acme.json
      httpChallenge:
        entryPoint: web

accessLog:
  filePath: "/var/log/traefik/access.log"
  format: common

/etc/traefik/dynamic/wp.yml:

http:
  routers:
    wp:
      rule: "Host(`deine-domain.tld`)"
      entryPoints: ["websecure"]
      service: wp-svc
      tls:
        certResolver: letsencrypt
    wp-redirect:
      rule: "Host(`deine-domain.tld`)"
      entryPoints: ["web"]
      middlewares: ["https-redirect"]
      service: wp-svc

  middlewares:
    https-redirect:
      redirectScheme:
        scheme: https
        permanent: true

  services:
    wp-svc:
      loadBalancer:
        servers:
          - url: "http://host.containers.internal:8080"

Hinweis: host.containers.internal erlaubt Traefik (Host) den Zugriff auf den rootless-exponierten Port 8080.

5. Autostart mit Quadlets

Quadlets starten Pod/Container per systemd im User-Kontext (rootless).

mkdir -p ~/.config/containers/systemd

~/.config/containers/systemd/wp.pod:

[Pod]
Name=wp
PublishPort=8080:80

~/.config/containers/systemd/wp-db.container:

[Container]
Image=mariadb:10.11
Name=wp-db
Pod=wp
Environment=MYSQL_ROOT_PASSWORD=geheim
Environment=MYSQL_DATABASE=wordpress
Environment=MYSQL_USER=wpuser
Environment=MYSQL_PASSWORD=wppass
Volume=/srv/wp-db:/var/lib/mysql
RestartPolicy=always

~/.config/containers/systemd/wordpress.container:

[Container]
Image=wordpress:latest
Name=wordpress
Pod=wp
Environment=WORDPRESS_DB_HOST=127.0.0.1
Environment=WORDPRESS_DB_USER=wpuser
Environment=WORDPRESS_DB_PASSWORD=wppass
Environment=WORDPRESS_DB_NAME=wordpress
Volume=/srv/wordpress:/var/www/html
RestartPolicy=always

Aktivieren:

systemctl --user daemon-reload
systemctl --user enable --now wp.pod wp-db.container wordpress.container
loginctl enable-linger $USER

6. Fail2Ban (SSH & WordPress)

Fail2Ban drosselt Fehlversuche anhand des Traefik-Access-Logs.

/etc/fail2ban/filter.d/traefik-wp-login-post.conf:

[Definition]
failregex = ^<HOST> .* "POST /wp-login\.php.*" .* (200|403)
ignoreregex = ^<HOST> .* "POST /wp-login\.php.*" .* 30[123] .*/wp-admin/

/etc/fail2ban/filter.d/traefik-xmlrpc.conf:

[Definition]
failregex = ^<HOST> .* "POST /xmlrpc\.php.*" .* 200
ignoreregex =

Jail-Beispiel (/etc/fail2ban/jail.d/traefik-wp.conf):

[traefik-wp-login-post]
enabled = true
port    = http,https
filter  = traefik-wp-login-post
logpath = /var/log/traefik/access.log
maxretry = 6
findtime = 10m
bantime  = 1h

[traefik-xmlrpc]
enabled = true
port    = http,https
filter  = traefik-xmlrpc
logpath = /var/log/traefik/access.log
maxretry = 4
findtime = 10m
bantime  = 1h
sudo systemctl restart fail2ban
sudo fail2ban-client status traefik-wp-login-post

7. Firewall-Härtung

Öffne nur die benötigten Ports.

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 9090/tcp
sudo ufw enable
sudo ufw status

8. Dateizugriff per SFTP

  • Web-Dateien: /srv/wordpress (Themes, Plugins, Uploads)
  • DB-Daten: /srv/wp-db

9. Fazit

  • Podman (rootless): isolierter, sicherer Betrieb
  • Dateien in /srv: einfacher SSH/SFTP-Zugriff, persistente Daten
  • Traefik: automatisches HTTPS & Routing
  • Cockpit: komfortable Server-GUI
  • Fail2Ban + UFW: wirksame Grundhärtung

Damit betreibst Du WordPress sicher und modern – optimiert für Zürich.

10. Quellen & Tools

Facebook

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert