← Blog

Einen neuen Ubuntu-Server absichern, bevor du Apps darauf betreibst

Railyard

18. April 2026 · 10 Min. Lesezeit

Folge dem auf deinem eigenen Server. Kostenlos starten, keine Karte nötig

Ein frischer Ubuntu-Server von jedem Cloud-Anbieter kommt mit einem Account (root), einem Zugangsweg (ein Passwort oder ein vom Anbieter generierter Key) und überhaupt keinen Firewall-Regeln. Das ist okay für die ersten fünf Minuten, während du dich orientierst, aber es ist noch kein Server, auf dem du irgendetwas laufen lassen solltest. Jeder, der das Internet nach offenen SSH-Ports scanned, findet ihn innerhalb von Stunden, und ein per Passwort erreichbarer Root-Account ist genau das, worauf sie hoffen. Am Ende dieses Guides hast du einen Nicht-Root-User mit eigenem SSH-Key, Root-Login und Passwort-Authentifizierung beide deaktiviert, eine Firewall, die nur die Ports durchlässt, die du tatsächlich nutzt, fail2ban, das nach Brute-Force-Versuchen schaut, Sicherheitsupdates, die sich selbst installieren, und eine kurze Checkliste, um zu bestätigen, dass alles davon tatsächlich wirkt.

Was du brauchst

  • Einen frischen Ubuntu-24.04-LTS-Server von irgendeinem Anbieter, mit seinen initialen Root-SSH-Zugangsdaten (ein Passwort oder ein vom Anbieter generierter Key).
  • Dein eigenes SSH-Keypaar auf deinem Rechner (ssh-keygen -t ed25519, falls du noch keins hast).
  • Einen Nicht-Root-Benutzernamen, den du auf dem Server anlegen willst (dieser Guide nutzt deploy).
  • Etwa zwanzig Minuten, die meiste Zeit davon mit Lesen von Ausgaben statt Tippen.

Schritt 1: Einen Nicht-Root-Sudo-User anlegen

Alles als Root laufen zu lassen bedeutet, dass ein einziger verschriebener Befehl, ein kompromittiertes Skript oder ein durchgesickerter Key die gesamte Maschine übergibt. Ein separater Account mit sudo gibt dir dieselbe Fähigkeit, den Server zu verwalten, aber nur, wenn du bewusst danach fragst, und es ist der Account, den Railyard (oder jedes andere Deploy-Tool) später tatsächlich nutzt.

Als root:

adduser deploy
usermod -aG sudo deploy

adduser führt dich durch das Setzen eines Passworts und einiger optionaler Details; usermod -aG sudo fügt den neuen Account der sudo-Gruppe hinzu, die auf Ubuntu bereits so verdrahtet ist, dass sie volle administrative Rechte gewährt.

Prüfe, dass es funktioniert hat: führe id deploy aus und bestätige, dass sudo in der Gruppenliste erscheint. Dann sollte su - deploy gefolgt von sudo whoami nach dem Passwort des deploy-Users fragen und root ausgeben.

Schritt 2: Deinen SSH-Key übertragen und den Login testen

Bevor du irgendetwas in sshd_config anfasst, bring den Key-basierten Login für den neuen User zum Funktionieren und bestätige ihn aus einem brandneuen Terminal-Fenster, während deine ursprüngliche Root-Session als Sicherheitsnetz offen bleibt.

Der einfache Weg, von deinem eigenen Rechner:

ssh-copy-id deploy@YOUR_SERVER_IP

Falls ssh-copy-id nicht verfügbar ist, mach es von Hand als deploy-User auf dem Server:

mkdir -p ~/.ssh
echo "ssh-ed25519 AAAA... your-public-key-here" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Versuche jetzt, in einem zweiten Terminal-Fenster, ohne deine bestehende Root-Session zu schließen, dich als neuer User einzuloggen:

ssh deploy@YOUR_SERVER_IP

Du solltest direkt in eine Shell als deploy landen (es kann nach der Passphrase deines Keys fragen, falls du eine gesetzt hast, aber nicht nach einem Passwort für den Account). Falls das aus irgendeinem Grund fehlschlägt, behebe es jetzt, immer noch aus deiner ursprünglichen Root-Session. Geh nicht zum nächsten Schritt über, bevor das funktioniert.

Schritt 3: Root-Login und Passwort-Authentifizierung deaktivieren

Mit bestätigtem Key-basiertem Login sind Root-Zugang und Passwort-Authentifizierung keine Türen mehr, die du offen brauchst, und sie offen zu lassen ist genau das, wonach die meisten automatisierten SSH-Scanner tatsächlich suchen.

Bearbeite /etc/ssh/sshd_config:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

Prüfe, bevor du irgendetwas neu lädst, ob die Datei syntaktisch gültig ist:

sudo sshd -t

Falls das saubere Ergebnis zurückkommt, lade den Service neu (auf Ubuntu heißt die systemd-Unit ssh, nicht sshd):

sudo systemctl reload ssh

Prüfe, dass es funktioniert hat, aus einem dritten, frischen Terminal (halte wieder deine funktionierende Session offen): ssh root@YOUR_SERVER_IP sollte rundweg abgelehnt werden, und ssh deploy@YOUR_SERVER_IP mit falschem Passwort sollte sofort fehlschlagen, ganz ohne Passwort-Prompt, da Passwort-Authentifizierung komplett deaktiviert ist. Dein ursprünglicher Key-basierter Login als deploy sollte weiterhin genau wie vorher funktionieren.

Schritt 4: ufw einrichten

Eine Firewall, die standardmäßig alles verweigert und dann nur die Ports, die du nutzt, explizit erlaubt, bedeutet, dass ein Port, den du vergessen hast zu schließen (oder ein Service, den du installiert und vergessen hast), nicht einfach aus dem Internet erreichbar ist, nur weil er zufällig lauscht.

sudo apt update
sudo apt install ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

22/tcp hält SSH erreichbar (du kannst stattdessen sudo ufw allow OpenSSH nutzen, falls du das benannte Anwendungsprofil bevorzugst), 80/tcp und 443/tcp decken normales HTTP und HTTPS für das ab, was du später deployst. Falls du weißt, dass du nichts über HTTP ausliefern wirst, kannst du die 80/tcp-Regel weglassen, obwohl die meisten TLS-Setups Port 80 trotzdem kurz für die Zertifikatsausstellung nutzen.

Prüfe, dass es funktioniert hat: sudo ufw status verbose sollte Status: active, Default: deny (incoming), allow (outgoing) und die drei gerade hinzugefügten Regeln als ALLOW gelistet zeigen.

Schritt 5: fail2ban installieren und konfigurieren

Auch mit deaktivierter Passwort-Authentifizierung akzeptiert dein SSH-Port weiterhin Verbindungsversuche, und ein stetiger Strom automatisierter Login-Versuche verstopft deine Logs und verbrät etwas CPU ohne Grund. fail2ban beobachtet das Auth-Log und sperrt temporär IPs, die zu oft bei der Authentifizierung scheitern.

sudo apt install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

fail2bans eigene Konvention ist, jail.conf unberührt zu lassen (es wird bei Paket-Upgrades überschrieben) und deine Änderungen in jail.local zu packen, die danach gelesen wird und Vorrang hat. Öffne /etc/fail2ban/jail.local und stelle sicher, dass der sshd-Abschnitt so aussieht:

[sshd]
enabled = true
port = ssh
maxretry = 5
bantime = 1h
findtime = 10m

Das sperrt eine IP für eine Stunde nach fünf fehlgeschlagenen Versuchen innerhalb eines Zehn-Minuten-Fensters. Aktiviere und starte dann den Service:

sudo systemctl enable --now fail2ban

Prüfe, dass es funktioniert hat: sudo fail2ban-client status sshd sollte das laufende Jail zeigen, mit Zählern für aktuell fehlgeschlagene und aktuell gesperrte Adressen.

Schritt 6: Automatische Sicherheitsupdates aktivieren

Die meisten Server-Kompromittierungen sind keine Zero-Days, es sind bekannte Schwachstellen in Paketen, die niemand aktualisiert hat. unattended-upgrades wendet Sicherheitspatches automatisch, nach einem Zeitplan an, ohne dass du dich daran erinnern musst, dich per SSH einzuloggen und apt upgrade auszuführen.

sudo apt install unattended-upgrades

Ubuntu liefert das mit bereits aktivierten Sicherheitsupdates für das aktuelle Release, sobald es installiert ist. Bestätige (und passe falls nötig an) die zwei Konfigurationsdateien:

/etc/apt/apt.conf.d/20auto-upgrades sollte enthalten:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

/etc/apt/apt.conf.d/50unattended-upgrades listet, welche Paketquellen automatisch aktualisiert werden dürfen; die Sicherheits-Pocket für dein Release ist standardmäßig enthalten.

Prüfe, dass es funktioniert hat: sudo unattended-upgrade --dry-run --debug gibt aus, was beim nächsten Lauf passieren würde, ohne tatsächlich etwas zu ändern. Nachdem der Service wirklich gelaufen ist (er prüft einmal täglich), zeigt /var/log/unattended-upgrades/unattended-upgrades.log, was installiert wurde.

Schritt 7: Zeitzone und Hostname des Servers setzen

Dieser hier geht nicht um Angreifer, sondern um deine eigene Vernunft später: Log-Zeitstempel, die zu deiner eigenen Uhr passen, und ein Hostname, der dir sagt, welchen Server du vor dir hast, wenn du mehr als einen in verschiedenen Terminal-Tabs offen hast.

sudo timedatectl set-timezone America/Montreal
sudo hostnamectl set-hostname myapp-server-01

Tausche die IANA-Zeitzone und den Hostnamen gegen das, was für dich sinnvoll ist; timedatectl list-timezones listet die gültigen Werte, falls du sich beim genauen Namen nicht sicher bist.

Prüfe, dass es funktioniert hat: timedatectl zeigt die gesetzte Zeitzone unter “Time zone”, und hostnamectl zeigt den neuen Hostnamen unter “Static hostname”.

Schritt 8: Finale Verifikationsrunde

Bevor du den Server als bereit betrachtest, logge dich komplett aus und bestätige, dass das gesamte Setup von einem sauberen Zustand aus hält, nicht nur aus der Session, die du die ganze Zeit offen hattest:

  • Öffne ein brandneues Terminal und führe ssh deploy@YOUR_SERVER_IP aus. Du solltest in einer Shell landen, nur mit deinem Key, kein Passwort-Prompt.
  • ssh root@YOUR_SERVER_IP aus demselben frischen Terminal sollte abgelehnt werden.
  • sudo ufw status verbose zeigt weiterhin active mit exakt den Ports, die du offen haben willst.
  • sudo fail2ban-client status sshd zeigt das laufende Jail.
  • sudo whoami als deploy-User gibt nach einem Passwort-Prompt weiterhin root zurück.

Wenn alle diese Punkte stimmen, ist der Server in einem vernünftigen Zustand, um etwas darauf zu betreiben.

Die Abkürzung: mit Railyard

Keiner der obigen Schritte ist etwas, das Railyard für dich macht. Es rührt sshd_config nicht an, es konfiguriert ufw oder fail2ban nicht, und es setzt deine Zeitzone nicht. Was es von einem Server braucht, den du schon wie oben abgesichert hast, ist schmal: Der SSH-User hat passwortloses sudo, die Ports 22, 80 und 443 sind aus dem Internet erreichbar (exakt die Regeln, die du gerade hinzugefügt hast), und der Server hat mindestens 1 GB RAM (2 GB oder mehr, falls du auch App-Images darauf baust).

Ein Detail, das es sich lohnt zu fixen, bevor du einen Server verbindest: Die Standard-Kombination aus adduser plus usermod -aG sudo aus Schritt 1 fragt deploy immer noch nach seinem Passwort, jedes Mal wenn es sudo ausführt, und Railyard braucht das ohne Prompt. Füge ein Sudoers-Drop-in dafür hinzu:

echo "deploy ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/deploy
sudo chmod 440 /etc/sudoers.d/deploy

Von dort: Servers → Add a server → Bring your own server, richte es auf die IP dieses Servers mit dem privaten Key, der zum öffentlichen Key passt, den du in Schritt 2 übertragen hast. Dieser private Key wird einmalig für die Installation genutzt und nicht gespeichert. Der Server erscheint innerhalb einiger Minuten in deinem Dashboard, bereit für das Deployment einer App.

Falls du lieber keine Box von Hand provisionieren möchtest, kann Railyard auch direkt einen Server auf deinem eigenen Cloud-Account (DigitalOcean, Vultr, Hetzner, AWS oder OVH) erstellen und automatisch einrichten, der genauso in deinem Dashboard erscheint. Beide Wege lassen das obige Hardening weiterhin in deiner Verantwortung: Railyard automatisiert App-Deployment, Zero-Downtime-Releases und Datenbank- und Backup-Verwaltung auf einem Server, der schon abgesichert ist, es ist eine Abkürzung am Deploy-Tooling vorbei, nicht am Hardening selbst.

Troubleshooting

Du hast dich selbst ausgesperrt, nachdem du die Passwort-Authentifizierung deaktiviert hast. Das passiert, wenn PasswordAuthentication no neu geladen wird, bevor der Key-basierte Login tatsächlich bestätigt wurde, dass er funktioniert. Falls dein Anbieter eine Web-Konsole oder einen Recovery-Modus anbietet, nutze ihn, um dich lokal einzuloggen und entweder PasswordAuthentication yes temporär wieder zu aktivieren oder den Key in ~/.ssh/authorized_keys zu fixen, dann aus einem frischen Terminal erneut testen, bevor du es wieder deaktivierst.

ufw blockiert einen Port, den deine App braucht. Falls etwas, das du später deployst, einen Port jenseits von 22, 80 und 443 braucht (eine Datenbank, die du bewusst exponierst, einen anderen App-Port), füge ihn explizit hinzu: sudo ufw allow 5432/tcp, dann erneut mit sudo ufw status verbose prüfen. Es ist meist sicherer, Datenbanken ganz vom öffentlichen Internet fernzuhalten und sie stattdessen über ein privates Netzwerk zu erreichen, statt einen weiteren Port zu öffnen.

fail2ban hat deine eigene IP gesperrt. Falls du beim Testen ein paar Mal ein Passwort falsch eintippst (oder von einem Skript testest, das schnell wiederholt), kann fail2ban die IP sperren, von der du arbeitest. Entsperre sie aus einer Session, die noch verbunden ist, oder von der Konsole des Servers: sudo fail2ban-client set sshd unbanip YOUR_IP.

Du kannst dich von der Konsole des Servers selbst per SSH einloggen, aber nicht aus dem Internet. Die meisten Cloud-Anbieter legen ihre eigene netzwerkbasierte Firewall (eine “Security Group” oder “Cloud Firewall”) vor den Server, separat von ufw. Falls ein Port in ufw offen, aber trotzdem unerreichbar ist, prüfe auch die Firewall-Einstellungen des Anbieters, beide müssen dieselben Ports erlauben, damit Traffic durchkommt.

FAQ

Muss ich das machen, wenn mein Anbieter schon eine eigene Firewall hat? Ja. Die Netzwerk-Firewall eines Anbieters ist eine nützliche erste Schicht, aber sie gibt dir kein Key-only-SSH, sie sperrt keine Brute-Force-Versuche, und sie patcht dir kein verwundbares Paket. Behandle ufw als zweite Schicht, nicht als Ersatz.

Auf welchen Port sollte ich SSH verschieben? Du musst ihn nicht verschieben. Sobald Root-Login und Passwort-Authentifizierung deaktiviert sind und fail2ban zuschaut, ist Port 22 kein nennenswerter Schwachpunkt mehr, ein Scanner, der einen offenen Port 22 findet, kann ohne gültigen Key wenig anfangen. SSH auf einen nicht-standardmäßigen Port zu verschieben reduziert vor allem Log-Rauschen von automatisierten Scans; falls du es tust, denk daran, sowohl die Port-Direktive in sshd_config als auch die passende ufw-Regel zu aktualisieren und den neuen Port zu testen, bevor du 22 schließt.

Wie oft sollte ich den Server aktualisieren? unattended-upgrades wendet täglich von selbst Sicherheitspatches an, was die wichtigsten Updates abdeckt. Es lohnt sich trotzdem, hin und wieder von Hand sudo apt update && sudo apt upgrade für Nicht-Sicherheits-Paketupdates auszuführen, und nach einem Kernel-Update neu zu starten, damit der neue tatsächlich lädt.

Brauche ich fail2ban noch, wenn die Passwort-Authentifizierung schon deaktiviert ist? Es lohnt sich trotzdem, es laufen zu lassen. Es reduziert Log-Rauschen und die (kleinen) Ressourcenkosten ständiger fehlgeschlagener Verbindungsversuche, und es wendet denselben Schutz auf jeden anderen Service an, für den du später ein Jail hinzufügst, nicht nur SSH.

Gilt das auch für neuere Ubuntu-LTS-Releases? Der generelle Ansatz (ein Nicht-Root-Sudo-User, SSH nur per Key, ufw, fail2ban, automatische Updates) übertragt sich auf andere aktuelle Ubuntu-LTS-Releases; die Befehle und Dateipfade in diesem Guide sind das, was aktuell für 24.04 gilt. Falls du auf einem anderen Release bist, lohnt sich ein kurzer Check gegen Ubuntus eigene aktuelle Dokumentation für alles, was sich geändert hat, bevor du einen Hardening-Schritt festlegst.

Keiner dieser Schritte dauert für sich lange, und sobald sie erledigt sind, musst du bis zum nächsten Server nicht mehr darüber nachdenken. Was du davon hast, ist eine Maschine, bei der ein streunender Scanner eine geschlossene Tür findet statt einer offenen, und das ist die Basis, von der aus jeder Server, auf dem du etwas Echtes betreibst, starten sollte.

Warum Leute sich dafür Railyard entscheiden

  • Dein eigenes Cloud-Konto. Deploye auf DigitalOcean, Hetzner, Vultr, AWS, OVHcloud oder jedem Linux-Server per SSH, direkt von deinem Anbieter abgerechnet, ohne Aufschlag.
  • Ein fester Preis pro Team. Free ist für immer kostenlos: ein Server plus ein Datenbankserver, drei Apps, keine Karte. Pro kostet 19 $ im Monat für bis zu fünf Server und unbegrenzte Apps. Team kostet 49 $ im Monat mit unbegrenzten Servern. Keine Kosten pro App, pro Deployment, pro Sitz oder pro Gigabyte.
  • Templates mit einem Klick. Deploye Open-Source-Apps, wie Datenbanken, Analytics und Dev-Tools, mit einem Klick auf deinem eigenen Server.
  • Verwaltete Datenbanken. Postgres, MySQL und Redis mit geplanten, wiederherstellungsgeprüften Backups und Point-in-Time-Recovery.
  • Push-to-Deploy. Deploye von GitHub, GitLab oder der CLI, mit automatischem HTTPS und Releases ohne Ausfallzeit.

Deploye, sobald der Server abgesichert ist

Richte Railyard auf den Server, den du gerade abgesichert hast, und deploye deine erste App, ohne die Kommandozeile noch einmal anzufassen.

Kostenloser Plan, keine Kreditkarte, und 14 Tage Pro für jedes neue Team. Ein fester Preis pro Team.