Du hast einen frischen Linux-Server? Dann bist du in den ersten Stunden am verwundbarsten. Diese 8 Schritte schützen deinen Server vor den häufigsten Angriffen — von Brute-Force bis zu Datenlecks.
Getestet auf: Ubuntu 22.04 / 24.04, Debian 12. Die meisten Befehle laufen auf allen Debian-basierten Systemen.
01 — Keine Passwörter: SSH-Keys statt Login
Passwörter können geraten, geleakt oder per Brute-Force geknackt werden. SSH-Keys sind mathematisch sicher — ohne den privaten Schlüssel kommt niemand rein.
Schritt 1: Key-Pair auf deinem Rechner erzeugen
# Modernen Ed25519-Key erstellen (sicherer als RSA)
ssh-keygen -t ed25519 -C "dein@email.de"
# Public Key auf den Server kopieren
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@DEINE-SERVER-IP
Schritt 2: Passwort-Login deaktivieren
sudo nano /etc/ssh/sshd_config
Diese Zeilen setzen oder ändern:
PasswordAuthentication no
PermitRootLogin prohibit-password
PubkeyAuthentication yes
# SSH-Daemon neu starten
sudo systemctl restart ssh
⚠️ Wichtig: Teste die SSH-Key-Verbindung in einem zweiten Terminal, bevor du die aktuelle Session schließt!
02 — Nicht als Root arbeiten: Deploy-User anlegen
Root hat unbegrenzte Rechte. Ein einziger Fehler — oder ein kompromittierter Prozess — und der Server gehört dem Angreifer. Ein Deploy-User mit sudo ist der Standard in der Praxis.
# Neuen User anlegen
sudo adduser deploy
# Sudo-Rechte geben
sudo usermod -aG sudo deploy
# SSH-Key für den neuen User einrichten
sudo mkdir -p /home/deploy/.ssh
sudo cp /root/.ssh/authorized_keys /home/deploy/.ssh/
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys
Ab jetzt immer als deploy arbeiten, nicht als root.
03 — Firewall einschalten: ufw richtig konfigurieren
Standardmäßig sind alle Ports offen. Die Firewall lässt nur durch, was du explizit erlaubst.
# UFW installieren
sudo apt install ufw -y
# Standard: alles blockieren, ausgehend erlauben
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Benötigte Ports öffnen
sudo ufw allow ssh # Port 22
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable
sudo ufw status verbose
04 — Updates automatisch: unattended-upgrades
Sicherheitslücken werden täglich gefunden. Automatische Updates stellen sicher, dass dein Server nie wochenlang auf einen Patch wartet.
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades
# Testen
sudo unattended-upgrades --dry-run --debug
05 — Fail2ban: Brute-Force automatisch blocken
Fail2ban überwacht Log-Dateien und sperrt IPs, die zu viele Fehlanmeldungen produzieren. Effektiv gegen automatisierte Angriffe und Bot-Scans.
sudo apt install fail2ban -y
# Eigene Config (nie original jail.conf editieren!)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
maxretry = 5
bantime = 3600
findtime = 600
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo fail2ban-client status sshd
sudo fail2ban-client status sshd | grep 'Banned IP'
06 — .env niemals committen: Secrets raus aus Git
Ein einziger Commit mit Passwörtern ist potenziell für immer in der Git-History — auch nach dem Löschen. Secrets gehören nie in den Code.
.gitignore richtig setzen
cat >> .gitignore << 'IGNORE'
.env
.env.local
.env.production
.env.*.local
*.pem
*.key
secrets/
IGNORE
Git-History nach Secrets durchsuchen
git log --all --full-history -- .env
git grep -i "password" $(git log --all --oneline | awk '{print $1}')
Dateiberechtigungen auf dem Server
chmod 600 /opt/myapp/.env
chown deploy:deploy /opt/myapp/.env
ls -la /opt/myapp/.env
# Ausgabe: -rw------- 1 deploy deploy ...
07 — HTTPS mit Certbot: Let's Encrypt SSL
Unverschlüsselte HTTP-Verbindungen sind für jeden im Netzwerk lesbar. Let's Encrypt gibt kostenlose SSL-Zertifikate — Certbot automatisiert alles inklusive der automatischen Erneuerung.
sudo apt install certbot python3-certbot-nginx -y
# Zertifikat ausstellen + Nginx automatisch konfigurieren
sudo certbot --nginx -d example.com -d www.example.com
# Auto-Renewal testen
sudo certbot renew --dry-run
sudo systemctl status certbot.timer
sudo certbot certificates
08 — Backups automatisieren: restic + 3-2-1-Regel
Kein Backup = kein Mitleid. Die 3-2-1-Regel: 3 Kopien, auf 2 verschiedenen Medien, 1 davon außerhalb des Servers.
sudo apt install restic -y
# Repository initialisieren (Hetzner Storage Box)
restic init --repo sftp:uXXXXXX@uXXXXXX.your-storagebox.de:/backups/myapp
#!/bin/bash
# /opt/scripts/backup.sh
export RESTIC_REPOSITORY="sftp:uXXXXXX@uXXXXXX.your-storagebox.de:/backups/myapp"
export RESTIC_PASSWORD_FILE="/root/.restic-password" # Datei mit chmod 600, NICHT inline im Skript!
restic backup \
/opt/myapp \
/etc/nginx \
/etc/fail2ban \
--exclude="*.log" \
--exclude="node_modules"
restic forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
--prune
restic check
chmod +x /opt/scripts/backup.sh
# Crontab: täglich 02:00 Uhr
(crontab -l 2>/dev/null; echo "0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1") | crontab -
sudo /opt/scripts/backup.sh # Manueller Test
restic snapshots # Snapshots anzeigen
✅ Restore testen! Ein Backup ist wertlos, wenn du nicht weißt ob der Restore funktioniert. Teste einmal im Monat: restic restore latest --target /tmp/restore-test
Die Checkliste: Ist dein Server sicher?
- ✅ SSH-Key eingerichtet, Passwort-Login deaktiviert
- ✅ Deploy-User angelegt, Root-Login eingeschränkt
- ✅ UFW aktiviert, nur benötigte Ports offen
- ✅ unattended-upgrades läuft für Sicherheitsupdates
- ✅ Fail2ban schützt SSH vor Brute-Force-Angriffen
- ✅ .env in .gitignore, keine Secrets im Code oder der Git-History
- ✅ HTTPS aktiv, Certbot-Auto-Renewal eingerichtet
- ✅ Backup läuft täglich, Restore-Test bestanden
Diese 8 Schritte decken die häufigsten Angriffsvektoren ab. Kein System ist zu 100% sicher — aber du machst es Angreifern deutlich schwerer. Bei 99% der automatisierten Scans reicht das, um zum nächsten, weniger gesicherten Server weiterzugehen.

