Ubuntu Server Ersteinrichtung: 9 Schritte für den Start auf einem frisch installierten Ubuntu Server

TestumgebungDebian-FamilieUbuntu 24.04.5 LTSroot · normales Benutzerkonto
Ersteinrichtung des Ubuntu Servers geprüft

Wenn du einen neuen Server bekommst, gehst du die Ersteinrichtung des Ubuntu Servers einmal durch, bevor du Dienste darauf bringst. Auf einem bei DigitalOcean erstellten Ubuntu 24.04 Server haben wir uns als root verbunden, der Reihe nach alles von den Paketupdates über einen sudo-Benutzer, Schlüssel-Login, Firewall, Zeitzone und automatische Sicherheitsupdates bis zum Swap eingerichtet und geprüft, dass die Einstellungen auch nach einem Neustart erhalten bleiben.

Die Ergebnisboxen unten sind die Ausgabe der Befehle in dieser Reihenfolge. Die Server-IP 203.0.113.10 ist ein Beispielwert, und der neue normale Benutzer heißt deploy.

🎯 Kernpunkte
Paketupdates und Prüfung, ob ein Neustart nötig ist
sudo freigeschaltet für den normalen Benutzer deploy
deploy (Schlüssel-Login geprüft), danach root (Login gesperrt)
ufw erlaubt nur SSH, 80 und 443
Zeitzone ändern und automatische Sicherheitsupdates prüfen
2GB Swap-Datei und Einstellungen nach dem Neustart geprüft
Voraussetzungen
Vorher lesenssh-keygenssh Befehl
Verbindungroot-Login per SSH-Schlüssel und ein Ubuntu 24.04 Server

1️⃣ Ubuntu Paketupdate

Auch auf einem neu erstellten Server warten Updates auf die Installation. Hol dir zuerst eine frische Paketliste und prüfe, was sich ändert, bevor du wirklich etwas installierst.

🔲 apt-get update

export DEBIAN_FRONTEND=noninteractive

Die apt-get-Befehle unten wurden ausgeführt, nachdem dieser Wert gesetzt war. Damit erscheinen während der Paketinstallation keine Fenster mit Rückfragen, und es gelten die Standardantworten.

apt-get update
Hit:1 http://mirrors.digitalocean.com/ubuntu noble InRelease
Hit:2 http://mirrors.digitalocean.com/ubuntu noble-updates InRelease
Hit:3 http://mirrors.digitalocean.com/ubuntu noble-backports InRelease
Hit:4 https://repos-droplet.digitalocean.com/apt/droplet-agent main InRelease
Hit:5 http://security.ubuntu.com/ubuntu noble-security InRelease
Reading package lists...

🔲 apt-get -s upgrade

apt-get -s upgrade
Calculating upgrade...
The following upgrades have been deferred due to phasing:
  libsqlite3-0
The following packages will be upgraded:
  apt apt-transport-https apt-utils bind9-dnsutils bind9-host bind9-libs
  cloud-init distro-info-data gir1.2-glib-2.0 git git-man libapt-pkg6.0t64
  libbrotli1 libglib2.0-0t64 libglib2.0-bin libglib2.0-data liblzma5
  libmspack0t64 libpcre2-8-0 python3-jwt python3-twisted tmux
  ubuntu-pro-client ubuntu-pro-client-l10n xz-utils zlib1g
26 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.

Die Option -s ist ein Probelauf, der nur das Ergebnis berechnet, ohne etwas zu installieren. Auf diesem Server standen 26 Pakete zum Upgrade an, und libsqlite3-0 wurde als [deferred due to phasing] aus diesem Upgrade herausgenommen. Die Anzahl unterscheidet sich je nach Erstellungszeitpunkt und Image von Server zu Server.

🔲 apt-get -y upgrade

apt-get -y upgrade
26 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
Need to get 15.4 MB of archives.
After this operation, 398 kB of additional disk space will be used.

Nach der Installation folgt eine Liste der neu gestarteten Dienste.

Running kernel seems to be up-to-date.

Restarting services...
 /etc/needrestart/restart.d/systemd-manager
 systemctl restart cron.service fwupd.service multipathd.service packagekit.service polkit.service ssh.service systemd-journald.service systemd-networkd.service systemd-resolved.service systemd-timesyncd.service systemd-udevd.service udisks2.service

Service restarts being deferred:
 systemctl restart ModemManager.service
 /etc/needrestart/restart.d/dbus.service
 systemctl restart systemd-logind.service
 systemctl restart unattended-upgrades.service

Wenn ein Update installiert wird, das einen Neustart braucht, entsteht die Datei /var/run/reboot-required. Diesmal erschien [Running kernel seems to be up-to-date.] und die Datei wurde nicht angelegt, also ging es ohne Neustart zum nächsten Schritt.

2️⃣ Ubuntu Benutzer hinzufügen und sudo-Rechte

Die tägliche Arbeit erledigst du als normaler Benutzer und führst nur Verwaltungsbefehle mit sudo aus. sudo erhöht die Rechte mit deinem eigenen Passwort statt mit dem root-Passwort, daher bleibt festgehalten, wer welchen Befehl ausgeführt hat.

🔲 adduser deploy

adduser deploy
info: Adding user `deploy' ...
info: Selecting UID/GID from range 1000 to 59999 ...
info: Adding new group `deploy' (1000) ...
info: Adding new user `deploy' (1000) with group `deploy (1000)' ...
info: Creating home directory `/home/deploy' ...
info: Copying files from `/etc/skel' ...
New password: 
Retype new password: 
passwd: password updated successfully
Changing the user information for deploy
Enter the new value, or press ENTER for the default
	Full Name []: 
	Room Number []: 
	Work Phone []: 
	Home Phone []: 
	Other []: 
Is the information correct? [Y/n] Y
info: Adding new user `deploy' to supplemental / extra groups `users' ...
info: Adding user `deploy' to group `users' ...

adduser ist ein Wrapper um useradd; es legt den Home-Ordner und die Gruppe an und fragt dann nacheinander nach Passwort und Benutzerangaben. Das Passwort erscheint beim Tippen nicht auf dem Bildschirm, und Angaben wie Name oder Telefonnummer kannst du mit Enter leer lassen.

🔲 usermod -aG sudo deploy

usermod -aG sudo deploy
groups deploy
deploy : deploy sudo users

🔲 su

Benutzer in der Gruppe sudo können Verwaltungsbefehle mit sudo ausführen. Wechsle mit su zum Konto deploy und prüfe die Rechte.

su - deploy
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
whoami
deploy
sudo whoami
[sudo] password for deploy: 
root
exit

Mit sudo wird das Passwort von deploy abgefragt, und wenn es stimmt, läuft der Befehl mit root-Rechten.

3️⃣ SSH-Schlüssel für den neuen Benutzer hinterlegen

Anfangs ist nur für root ein SSH-Schlüssel hinterlegt, deshalb klappt der Schlüssel-Login mit deploy nicht. Kopiere die authorized_keys von root in den Home-Ordner von deploy.

🔲 install -o deploy -g deploy

install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
install -m 600 -o deploy -g deploy /root/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys
ls -la /home/deploy/.ssh
total 12
drwx------ 2 deploy deploy 4096 Nov  5 11:48 .
drwxr-x--- 3 deploy deploy 4096 Nov  5 11:48 ..
-rw------- 1 deploy deploy  100 Nov  5 11:48 authorized_keys

install erledigt das Anlegen des Ordners, das Kopieren und das Setzen von Besitzer und Rechten in einem Schritt. sshd prüft vor dem Login die Rechte und den Besitzer der Benutzerdateien (StrictModes), deshalb setzt du den Ordner .ssh auf 700 und authorized_keys auf 600.

🔲 ssh deploy@203.0.113.10

Schließ das offene root-Fenster nicht, sondern prüfe zuerst in einem neuen Terminalfenster, ob du dich als deploy verbinden kannst.

ssh deploy@203.0.113.10
whoami
deploy
🧭 Eine Reihenfolge, die dich nicht aussperrt
Erklär-Diagramm
🧭 Schritte
🔑① Schlüssel kopierenroot-Schlüssel an deploy
➜
🪟② Neues Fenster prüfenroot-Fenster bleibt offen
➜
⛔③ root-Login sperrenPermitRootLogin no
➜
🪟④ Neues Fenster prüfendeploy-Login bleibt
✅⑤ SSH erlaubenufw allow OpenSSH
➜
🧱⑥ ufw einschaltenNur erlaubte Ports offen
➜
🪟⑦ Neues Fenster prüfenLogin bleibt
Kopiere die authorized_keys von root in den Home-Ordner von deploy.
Schließ das offene root-Fenster nicht, sondern prüfe in einem neuen Terminalfenster, ob der Schlüssel-Login als deploy klappt.
Sperre den root-Login erst, wenn der deploy-Login bestätigt ist. Klappt die Verbindung im neuen Fenster nicht, machst du die Änderung im offen gelassenen Fenster rückgängig.
Lade die SSH-Einstellungen neu und prüfe in einem neuen Fenster, ob der deploy-Login weiterhin klappt.
Bevor du die Firewall einschaltest, fügst du zuerst die Regel hinzu, die SSH erlaubt.
Sobald sie eingeschaltet ist, wird jede nicht erlaubte Verbindung blockiert, deshalb muss die SSH-Regel vorher stehen.
Prüfe nach dem Einschalten der Firewall in einem neuen Fenster, ob du dich wieder als deploy verbinden kannst.

4️⃣ SSH root-Login sperren

Unter Ubuntu 24.04 lädt die Include-Zeile ganz oben in sshd_config zuerst die Dateien im Ordner /etc/ssh/sshd_config.d/, und bei derselben Einstellung gilt der zuerst gelesene Wert. Prüfe deshalb vor jeder Änderung den aktuell geltenden Wert und die Datei, in der er steht.

/etc/ssh└─ sshd_config  ganz oben: Include /etc/ssh/sshd_config.d/*.conf   ├─ ① sshd_config.d/50-cloud-init.conf         PasswordAuthentication no   ├─ ② sshd_config.d/60-cloudimg-settings.conf  PasswordAuthentication no   └─ ③ sshd_config Zeile 42                     PermitRootLogin yes → no

🔲 sshd -T

sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication) '
permitrootlogin yes
passwordauthentication no
sudo grep -rn 'PasswordAuthentication' /etc/ssh/sshd_config.d/
/etc/ssh/sshd_config.d/60-cloudimg-settings.conf:1:PasswordAuthentication no
/etc/ssh/sshd_config.d/50-cloud-init.conf:1:PasswordAuthentication no

Der Passwort-Login ist in zwei Dateien in sshd_config.d bereits ausgeschaltet; zu ändern ist nur die root-Login-Zeile in der Hauptdatei.

🔲 sed -i PermitRootLogin

sudo grep -n '^PermitRootLogin' /etc/ssh/sshd_config
42:PermitRootLogin yes
sudo sed -i 's/^PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo grep -n '^PermitRootLogin' /etc/ssh/sshd_config
42:PermitRootLogin no

🔲 systemctl reload ssh

sudo sshd -t
sudo systemctl reload ssh
sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication) '
permitrootlogin no
passwordauthentication no

sshd -t prüft die Syntax der Konfiguration, und wenn nichts ausgegeben wird, gibt es keine Fehler. Bestätige nach dem Neuladen in einem neuen Fenster, dass der deploy-Login weiterhin klappt, und verbinde dich dann als root, um zu sehen, dass es abgelehnt wird.

ssh root@203.0.113.10
root@203.0.113.10: Permission denied (publickey).

Auch mit dem richtigen Schlüssel kommst du als root nicht hinein; Verwaltungsarbeit erledigst du, indem du dich als deploy verbindest und sudo nutzt.

5️⃣ Ubuntu Firewall ufw

ufw ist das Standard-Firewall-Werkzeug von Ubuntu, ist anfangs aber ausgeschaltet. Sobald es eingeschaltet ist, wird jede nicht erlaubte Verbindung blockiert, deshalb fügst du zuerst die SSH-Regel hinzu und schaltest es zuletzt ein.

sudo ufw status verbose
Status: inactive

🔲 ufw allow OpenSSH

sudo ufw app list
Available applications:
  OpenSSH
sudo ufw allow OpenSSH
Rules updated
Rules updated (v6)
sudo ufw allow 80/tcp
Rules updated
Rules updated (v6)
sudo ufw allow 443/tcp
Rules updated
Rules updated (v6)
sudo ufw show added
Added user rules (see 'ufw status' for running firewall):
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp

OpenSSH ist ein Profil, das Port 22 öffnet, und 80 und 443 sind die Ports für einen Webserver. Die Regeln gelten für IPv4 und IPv6 gemeinsam.

🔲 ufw enable

sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp (OpenSSH)           ALLOW IN    Anywhere                  
80/tcp                     ALLOW IN    Anywhere                  
443/tcp                    ALLOW IN    Anywhere                  
22/tcp (OpenSSH (v6))      ALLOW IN    Anywhere (v6)             
80/tcp (v6)                ALLOW IN    Anywhere (v6)             
443/tcp (v6)               ALLOW IN    Anywhere (v6)             

Eingehende Verbindungen werden standardmäßig blockiert, nur die drei erlaubten Ports sind offen, und die Firewall startet auch beim Booten. Verbinde dich nach dem Einschalten in einem neuen Fenster wieder als deploy und prüfe die Regelnummern.

sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] OpenSSH                    ALLOW IN    Anywhere                  
[ 2] 80/tcp                     ALLOW IN    Anywhere                  
[ 3] 443/tcp                    ALLOW IN    Anywhere                  
[ 4] OpenSSH (v6)               ALLOW IN    Anywhere (v6)             
[ 5] 80/tcp (v6)                ALLOW IN    Anywhere (v6)             
[ 6] 443/tcp (v6)               ALLOW IN    Anywhere (v6)             

6️⃣ Ubuntu Zeitzone einstellen

Die anfängliche Zeitzone ist Etc/UTC. Damit die Zeiten in Logs und geplanten Aufgaben zur Region des Servers passen, wurde dieser in der Region Singapur erstellte Server auf Asia/Singapore gestellt.

timedatectl
               Local time: Thu 2026-11-05 12:00:31 UTC
           Universal time: Thu 2026-11-05 12:00:31 UTC
                 RTC time: Thu 2026-11-05 12:00:31
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

🔲 timedatectl list-timezones

timedatectl list-timezones | grep Singapore
Asia/Singapore

🔲 timedatectl set-timezone

sudo timedatectl set-timezone Asia/Singapore
timedatectl
               Local time: Thu 2026-11-05 20:00:32 +08
           Universal time: Thu 2026-11-05 12:00:32 UTC
                 RTC time: Thu 2026-11-05 12:00:32
                Time zone: Asia/Singapore (+08, +0800)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

Es ändern sich nur die Zeilen Local time und Time zone; die Uhrzeitsynchronisierung (NTP) und die UTC-Zeit bleiben gleich.

7️⃣ unattended upgrades: automatische Sicherheitsupdates

Ubuntu installiert Sicherheitsupdates automatisch mit dem Paket unattended-upgrades, das von Anfang an installiert und aktiv ist. In diesem Schritt prüfst du deshalb, ob es aktiv ist und was es automatisch installiert.

🔲 dpkg-query -W

dpkg-query -W unattended-upgrades
unattended-upgrades	2.9.1+nmu4ubuntu1
systemctl is-enabled unattended-upgrades apt-daily.timer apt-daily-upgrade.timer
enabled
enabled
enabled

🔲 cat 20auto-upgrades

cat /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

Die 1 in beiden Werten bedeutet einmal am Tag, und mit 0 schaltest du die automatischen Updates aus. Was installiert wird, legt die Datei 50unattended-upgrades fest.

grep -vE '^[[:space:]]*(//|$)' /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Allowed-Origins {
	"${distro_id}:${distro_codename}";
	"${distro_id}:${distro_codename}-security";
	"${distro_id}ESMApps:${distro_codename}-apps-security";
	"${distro_id}ESM:${distro_codename}-infra-security";
};
Unattended-Upgrade::Package-Blacklist {
};
Unattended-Upgrade::DevRelease "auto";

Unter den erlaubten Quellen steht -security, aber nicht -updates, deshalb werden normale Updates nicht automatisch installiert, sondern nur Sicherheitsupdates. Wenn du auch normale Updates automatisch bekommen willst, entfernst du in dieser Datei das Kommentarzeichen vor der Zeile -updates.

🔲 unattended-upgrade

sudo unattended-upgrade --dry-run --debug
Starting unattended upgrades script
Allowed origins are: o=Ubuntu,a=noble, o=Ubuntu,a=noble-security, o=UbuntuESMApps,a=noble-apps-security, o=UbuntuESM,a=noble-infra-security

Das sind die letzten zwei Zeilen desselben Laufs.

No packages found that can be upgraded unattended and no pending auto-removals
The list of kept packages can't be calculated in dry-run mode.

--dry-run berechnet nur, was das automatische Update tun würde, ohne etwas zu installieren. Da die Paketupdates schon erledigt waren, gab es keine Pakete, die automatisch installiert werden müssten. Die Protokolle der echten Läufe liegen im Ordner /var/log/unattended-upgrades/.

sudo ls -l /var/log/unattended-upgrades/
total 32
-rw-r--r-- 1 root root     0 Nov  5 20:00 unattended-upgrades-dpkg.log
-rw-r--r-- 1 root root     0 Nov  5 17:34 unattended-upgrades-shutdown.log
-rw-r--r-- 1 root root 29093 Nov  5 20:04 unattended-upgrades.log

8️⃣ Ubuntu Swap-Speicher einrichten

Dieser Server hat 1GB Speicher und anfangs keinen Swap. Bevor du Apps darauf bringst, legst du eine 2GB Swap-Datei an und trägst sie in /etc/fstab ein, damit sie auch nach einem Neustart aktiv ist.

free -h
               total        used        free      shared  buff/cache   available
Mem:           961Mi       328Mi       161Mi       4.0Mi       631Mi       633Mi
Swap:             0B          0B          0B
df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        24G  2.0G   22G   9% /

🔲 fallocate -l 2G /swapfile

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
ls -lh /swapfile
-rw------- 1 root root 2.0G Nov  5 20:04 /swapfile

🔲 mkswap /swapfile

sudo mkswap /swapfile
Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
no label, UUID=0b43ccd8-5b4a-4048-9b84-eee12667b387

🔲 swapon /swapfile

sudo swapon /swapfile
swapon --show
NAME      TYPE SIZE USED PRIO
/swapfile file   2G   0B   -2
free -h
               total        used        free      shared  buff/cache   available
Mem:           961Mi       328Mi       160Mi       4.0Mi       632Mi       632Mi
Swap:          2.0Gi          0B       2.0Gi

🔲 tee -a /etc/fstab

swapon schaltet den Swap nur für jetzt ein; damit er auch nach einem Neustart aktiv ist, fügst du in fstab eine Zeile hinzu.

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
/swapfile none swap sw 0 0

9️⃣ Ubuntu Server Ersteinrichtung prüfen

Wenn du geprüft hast, dass die Einstellungen einen Neustart überstehen, ist die Ersteinrichtung von Ubuntu abgeschlossen.

🔲 systemctl reboot

sudo systemctl reboot

🔲 uptime -p

Verbinde dich nach dem Neustart wieder als deploy.

uptime -p
up 2 minutes
swapon --show
NAME      TYPE SIZE USED PRIO
/swapfile file   2G   0B   -2
sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication) '
permitrootlogin no
passwordauthentication no
sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp (OpenSSH)           ALLOW IN    Anywhere                  
80/tcp                     ALLOW IN    Anywhere                  
443/tcp                    ALLOW IN    Anywhere                  
22/tcp (OpenSSH (v6))      ALLOW IN    Anywhere (v6)             
80/tcp (v6)                ALLOW IN    Anywhere (v6)             
443/tcp (v6)               ALLOW IN    Anywhere (v6)             
timedatectl | head -n 4
               Local time: Thu 2026-11-05 20:06:35 +08
           Universal time: Thu 2026-11-05 12:06:35 UTC
                 RTC time: Thu 2026-11-05 12:06:35
                Time zone: Asia/Singapore (+08, +0800)
systemctl is-active unattended-upgrades ssh.socket
active
active

Swap, SSH-Einstellungen, Firewall, Zeitzone und automatische Updates sind alle wie vor dem Neustart. Als Nächstes kommt auf diesen Server eine Node.js-App mit PM2 und Nginx.

🔢 FAQ & empfohlene Inhalte

Du kannst es so lassen. Ein Paket, das als [deferred due to phasing] ausgelassen wird, ist ein Update in einer schrittweisen Verteilung. Ubuntu verteilt manche Updates zuerst nur an einen Teil der Server und weitet die Verteilung auf alle Server aus, wenn es keine Probleme gibt. Sicherheitsupdates werden nicht schrittweise verteilt, und das ausgelassene Paket wird beim nächsten Upgrade mitinstalliert, sobald die Verteilung ausgeweitet ist.

Die automatische Update-Aufgabe läuft einmal am Tag, und die zwei Timer apt-daily.timer und apt-daily-upgrade.timer starten sie mit einer zufälligen Verzögerung nach einer festen Uhrzeit. Auf diesem Server war der nächste Lauf von apt-daily-upgrade.timer für den nächsten Tag um 06:27:59 (+08) geplant. Wenn der Server aus ist und die Zeit verpasst, kann die Aufgabe direkt beim nächsten Booten laufen, deshalb warten apt-Aufgaben kurz nach dem Booten manchmal einen Moment.

Mit den Standardeinstellungen nicht. Der Standardwert von Automatic-Reboot in 50unattended-upgrades ist false, und auch in den Einstellungen dieses Servers ist diese Zeile nicht aktiv. Wenn ein Update installiert wird, das einen Neustart braucht, entsteht die Datei /var/run/reboot-required; liegt diese Datei vor, startest du selbst neu.

ℹ️ Affiliate-Hinweis
Die Inhalte dieser Website enthalten Affiliate-Links. Kauft ein Besucher über einen dieser Links ein Produkt oder eine Dienstleistung, erhält die Website vom Verkäufer eine Provision. Der Betrag, den der Käufer zahlt(bei Aktionsrabatten sinkt er ↓), steigt dadurch nicht. Angegebene Preise, Rabatte und Lagerbestände entsprechen dem Stand bei Erstellung und können abweichen; prüfe sie daher vor dem Kauf beim Verkäufer. Produkte werden nach eigenen Kriterien ausgewählt und bewertet, und Provisionen beeinflussen weder die Reihenfolge noch den Inhalt der Bewertungen.

Schreibe einen Kommentar

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

Beweisen Sie, dass Sie ein Mensch sind: 6   +   2   =