Server erstinstallation
Server erstinstallation
Section titled “Server erstinstallation”Komplett-Walkthrough: vom ersten SSH-Login nach dem Provisioning bis zum produktionsreifen Server. Annahme: Debian 12 (Bookworm) oder Ubuntu 22.04/24.04 LTS. Cloud-VM (Hetzner, DigitalOcean, AWS) oder bare metal — der Ablauf ist identisch.
Quick-Links:
- Server härten — die Checklistenfassung
- Server Backups — verschlüsselte Off-Site-Backups
Phase 0: Was du VOR dem ersten Login brauchst
Section titled “Phase 0: Was du VOR dem ersten Login brauchst”- Server-IP / Hostname notiert
- Cloud-Console offen (für Rescue/Konsole, falls SSH versemmelt)
- SSH-Key-Paar ed25519 auf deinem Workstation erstellt:
Terminal window ssh-keygen -t ed25519 -a 100 -C "deploy@workstation" - Public-Key (
~/.ssh/id_ed25519.pub) in der Cloud-Console als “SSH-Key” hinterlegt - 30 Minuten Zeit (kein Hot-Patch-Mode)
Faustregel: Wenn du nach dem ersten Login direkt
apt updatemachst, ohne User/SSH/Firewall gehärtet zu haben, hast du einen unsicheren Server. Erst härten, dann Dienste draufpacken.
Phase 1: Erster Login (noch alles offen)
Section titled “Phase 1: Erster Login (noch alles offen)”Cloud-Console → Cloud-Provider gibt dir initial nur root mit Passwort. Das schließen wir sofort.
# Lokal: erste SSH-Verbindung (Passwort-Auth, nur dieses eine Mal)ssh root@<server-ip>
# System auf Stand bringenapt update && apt full-upgrade -yreboot # falls Kernel-Update# wieder einloggenPhase 2: Non-root-User + SSH-Key
Section titled “Phase 2: Non-root-User + SSH-Key”# User anlegenadduser deployusermod -aG sudo deploy
# sudo ohne Passwort für deploy (optional, oft sinnvoll bei Automation)# Achtung: ohne Passwort = bequemer, aber wenn Key kompromittiert = game over.# Besser: Passwort-Prompt behalten.echo "deploy ALL=(ALL) ALL" > /etc/sudoers.d/deploy
# SSH-Key vom Workstation auf den Server übertragen# Auf der Workstation (NICHT auf dem Server):ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@<server-ip>
# Test: Login als deploy, ohne rootssh deploy@<server-ip>sudo whoami # muss "root" ausgebenPhase 3: SSH daemon härten
Section titled “Phase 3: SSH daemon härten”sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.baksudo nano /etc/ssh/sshd_configFolgende Werte setzen (suchen mit /, ändern mit i, speichern mit :wq):
PermitRootLogin noPasswordAuthentication noPermitEmptyPasswords noX11Forwarding noClientAliveInterval 300ClientAliveCountMax 2MaxAuthTries 3LoginGraceTime 30AllowUsers deployOptional, wenn statische IP / WireGuard:
Port 2222 # nur Security-through-Obscurity, nicht alleine verlassenVor dem Restart: zweite SSH-Session offen lassen! Falls die Config kaputt ist, kannst du sie in Session #1 reparieren ohne KVM/Rescue.
# Config-Syntax checkensudo sshd -t
# Restartsudo systemctl restart sshd
# In Session #2 testen: NEUE SSH-Verbindung als deploy@server# Funktioniert? → alten root-Login killen, Session #1 schließen.# Funktioniert nicht? → KVM/Rescue, sshd_config.bak zurückspielen.Phase 4: Firewall (ufw)
Section titled “Phase 4: Firewall (ufw)”Standard-Policy: alles dicht, nur was explizit erlaubt ist.
sudo apt install ufwsudo ufw default deny incomingsudo ufw default allow outgoing
# SSH (Port 22 oder den geänderten Port)sudo ufw allow 22/tcp # oder 2222/tcp
# Web (falls absehbar)sudo ufw allow 80,443/tcp
sudo ufw enablesudo ufw status verbose# Status: active, Logging: on (low), Default: deny (incoming), allow (outgoing)Vergiss nicht: wenn du ufw vor dem SSH-Config-Update aktivierst und SSH auf 2222 änderst, sperrst du dich aus.
Phase 5: Updates automatisieren
Section titled “Phase 5: Updates automatisieren”sudo apt install unattended-upgradessudo dpkg-reconfigure -plow unattended-upgrades# Dialog: "Yes" → automatische Security-Updates
# Bei Servern mit kritischen Diensten: Auto-Reboot aktivierensudo nano /etc/apt/apt.conf.d/50unattended-upgrades# Unattended-Upgrade::Automatic-Reboot "true";# Unattended-Upgrade::Automatic-Reboot-Time "04:00";
# Status prüfensudo unattended-upgrade --dry-run --debugPhase 6: Fail2ban
Section titled “Phase 6: Fail2ban”sudo apt install fail2bansudo systemctl enable --now fail2ban
# Eigene Jail-Config (überschreibt /etc/fail2ban/jail.conf)sudo nano /etc/fail2ban/jail.local[DEFAULT]bantime = 1hfindtime = 10mmaxretry = 5
[sshd]enabled = truebackend = systemdsudo systemctl restart fail2bansudo fail2ban-client status sshdPhase 7: Zeitsync + Hostname + Locale
Section titled “Phase 7: Zeitsync + Hostname + Locale”sudo hostnamectl set-hostname server-01.example.comsudo timedatectl set-timezone Europe/Berlin
sudo apt install systemd-timesyncdsudo systemctl enable --now systemd-timesyncdtimedatectl status# "System clock synchronized: yes"# "NTP service: active"
# Localesudo apt install localessudo locale-gen en_US.UTF-8 de_DE.UTF-8sudo update-locale LANG=de_DE.UTF-8Phase 8: Basis-Pakete
Section titled “Phase 8: Basis-Pakete”sudo apt install -y \ curl \ wget \ git \ vim \ htop \ iotop \ net-tools \ dnsutils \ ca-certificates \ gnupg \ rsync \ unattended-upgrades \ fail2ban \ ufw \ restic \ mtr-tiny \ tmuxPhase 9: Erste Backups einrichten
Section titled “Phase 9: Erste Backups einrichten”Nicht später. Backups ohne Restore-Test sind kein Backup. Siehe Server Backups.
Minimum-Variante (Schnellstart):
# Repo initialisieren (Hetzner Storage Box, S3, oder lokal mit zweiter Platte)restic -r sftp:backup@backup.example.com:/srv/backups init
# Erster Snapshotrestic -r sftp:backup@backup.example.com:/srv/backups backup \ /etc /home /var/log /root
# Restore üben (in /tmp/restore-test, nicht live!)restic -r sftp:backup@backup.example.com:/srv/backups restore latest \ --target /tmp/restore-testls /tmp/restore-test/etc# Wenn das Verzeichnis da ist und Inhalt hat → Backup funktioniert.
# Cron: täglich 03:00crontab -e# 0 3 * * * restic -r sftp:backup@backup.example.com:/srv/backups backup /etc /home /var/log /root --quietPhase 10: Snapshot machen + dokumentieren
Section titled “Phase 10: Snapshot machen + dokumentieren”Bevor du Dienste draufpackst, ein Snapshot des Cloud-Providers. Falls etwas schiefgeht, kannst du in 30 Sekunden zurückrollen.
# Cloud-Console → Snapshots/Images → "create snapshot"# Namen: "fresh-hardenend-2026-07-02"Notiere in deiner eigenen Doku:
- Server-IP
- SSH-Port (Standard oder geändert)
- User-Namen + Berechtigungen
- Offene Ports
- Backup-Repo-URL + Cron-Zeit
- Snapshot-ID
- Cloud-Provider-Account / Projekt-ID
Phase 11: Dienste installieren
Section titled “Phase 11: Dienste installieren”Erst jetzt. Beispiel: Docker.
# Docker installieren (Debian-Pakete, nicht snap)curl -fsSL https://get.docker.com | sudo shsudo usermod -aG docker deploy# Login als deploy neu starten (damit docker-Gruppe greift)
# Testdocker run --rm hello-worldReverse Proxy / Webhosting: Nginx Proxy Manager.
Häufige Stolpersteine
Section titled “Häufige Stolpersteine”| Problem | Ursache | Fix |
|---|---|---|
Nach ufw enable sofort ausgesperrt |
ufw aktiviert, aber SSH nicht in Allow-Liste | KVM/Rescue → ufw allow 22/tcp && ufw reload |
sshd_config kaputt, Restart schlägt fehl |
Tippfehler / fehlender AllowUsers-Eintrag | KVM/Rescue → cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config && systemctl restart sshd |
apt update mit “no public key”-Fehler |
Hetzner-Images haben veraltete Keys | sudo apt-key adv --refresh-keys oder Repos umstellen auf signed-by= |
sudo whoami → “Sorry, try again” |
deploy nicht in sudo-Gruppe, oder /etc/sudoers.d/ falsch |
usermod -aG sudo deploy, dann neu einloggen |
| Passwort-Login klappt nicht | PasswordAuthentication no gesetzt, aber kein Key hinterlegt |
KVM/Rescue → SSH-Key manuell in /home/deploy/.ssh/authorized_keys eintragen |
systemd-timesyncd synchronisiert nicht |
Server in Cloud hat NTP-Bug (manche Hetzner-Images) | apt install chrony && systemctl enable chrony |
Was du danach behältst
Section titled “Was du danach behältst”- Server härten — wenn du später was nachziehen willst
- Server Backups — Restore-Strategie, Retention, Monitoring
Nginx Proxy Manager— sobald die erste Domain drauf soll