Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Datenbanken 15.06.2026 · 9 min Lesezeit

PostgreSQL nativ installieren und absichern: PGDG-APT-Repository, systemd und pg_hba.conf (Ubuntu/Debian)

PostgreSQL 18 nativ auf Ubuntu oder Debian aufsetzen: PGDG-APT-Repository einbinden, systemd-Dienst verwalten und mit listen_addresses, pg_hba.conf, eigenen Rollen, SSL und ufw absichern, ohne Docker.

Geprüft am 30.09.2026 · für postgresql 18.6

WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Blauer Glaselefant vor einem Serverrack mit blau leuchtenden Einschüben, im Hintergrund eine Stadtsilhouette

Für den Produktivbetrieb auf Ubuntu oder Debian empfiehlt sich das offizielle PGDG-APT-Repository von postgresql.org: Es liefert die aktuelle Hauptversion (Stand September 2026: PostgreSQL 18.6) und zeitnahe Minor-Updates, während Ubuntu LTS teils mehrere Hauptversionen zurückliegt. Diese Anleitung richtet das Repository ein, installiert PostgreSQL 18 als systemd-Dienst ohne Docker und sichert die Datenbank in drei Schichten ab: Netzwerkbindung, Authentifizierungsregeln und Datenbankrechte.

Voraussetzungen

  1. Ubuntu 22.04, 24.04 oder 26.04 LTS bzw. Debian 12 (Bookworm) oder 13 (Trixie), amd64 oder arm64 (vom PGDG-Repository unterstützt, Stand 30.09.2026)
  2. Mindestens 1 CPU-Kern, 1 GB RAM und 10 GB freier Speicher für kleine Anwendungen; für produktive Datenbanken 2 Kerne und 4 GB RAM
  3. Root- oder sudo-Zugang auf dem Zielserver
  4. Internetzugang für den Download vom PGDG-APT-Repository (apt.postgresql.org)
  5. Dokumentation der Anwendungs-IP-Bereiche, die später in pg_hba.conf eingetragen werden
  6. Für SSL mit eigenem Zertifikat: TLS-Zertifikat und privater Schlüssel (selbst signiert mit openssl oder von einer CA)

Schritt 1: PGDG-APT-Repository einrichten

Das Paket postgresql-common enthält ein offizielles Installationsskript, das Repository-Schlüssel, APT-Quelle und PGDG-Signierschlüssel (ID: ACCC4CF8) automatisch einrichtet. Empfohlener Weg:

sudo apt update
sudo apt install -y postgresql-common
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh

Das Skript erkennt die Distribution (z. B. noble-pgdg für Ubuntu 24.04) und legt /etc/apt/sources.list.d/pgdg.sources an. Alternativ der manuelle Weg:

sudo apt install -y curl ca-certificates
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
  --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc

Dann die APT-Quelle anlegen (Beispiel Ubuntu 24.04; Suites und Architectures ggf. anpassen):

# /etc/apt/sources.list.d/pgdg.sources
Types: deb deb-src
URIs: https://apt.postgresql.org/pub/repos/apt
Suites: noble-pgdg
Architectures: amd64
Components: main
Signed-By: /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc

Dann PostgreSQL 18 installieren:

sudo apt update
sudo apt install -y postgresql-18

Verifizieren: Der Dienst läuft direkt nach der Installation. Prüfen Sie:

pg_lsclusters

Erwartete Ausgabe: eine Zeile mit Version 18, Cluster main, Port 5432, Status online. apt-cache policy postgresql-18 zeigt als Quelle apt.postgresql.org.

Schritt 2: systemd-Service verstehen und verwalten

Auf Debian und Ubuntu heißt die systemd-Unit postgresql@18-main (Schema postgresql@VERSION-CLUSTER). pg_ctlcluster leitet Root-Aufrufe ebenfalls an systemctl weiter; direkt mit systemctl zu arbeiten ist transparenter:

# Status prüfen:
sudo systemctl status postgresql@18-main

# Autostart beim Booten aktivieren (ist nach Installation meist schon aktiv):
sudo systemctl enable postgresql@18-main

# Starten / Stoppen:
sudo systemctl start  postgresql@18-main
sudo systemctl stop   postgresql@18-main

# Neustart (nötig nach listen_addresses-Änderung):
sudo systemctl restart postgresql@18-main

# Reload (reicht für pg_hba.conf-Änderungen):
sudo systemctl reload postgresql@18-main

reload sendet ein SIGHUP und liest pg_hba.conf und alle nicht neustartpflichtigen Parameter neu ein, ohne Verbindungen zu trennen. Parameter mit dem Kommentar # (change requires restart) in postgresql.conf, etwa listen_addresses, brauchen einen restart.

Verifizieren: sudo systemctl status postgresql@18-main zeigt active (running) und den Pfad zum PGDATA-Verzeichnis.

Schritt 3: Netzwerkbindung konfigurieren (postgresql.conf)

Die Datei /etc/postgresql/18/main/postgresql.conf steuert, auf welchen Interfaces PostgreSQL lauscht. Standard ist localhost, also nur lokale Verbindungen. Greifen Anwendungsserver aus dem internen Netz zu, geben Sie die interne IP des Datenbankservers zusätzlich an:

# /etc/postgresql/18/main/postgresql.conf

# Variante A: nur localhost (Standard, für Anwendungen auf demselben Server)
listen_addresses = 'localhost'

# Variante B: zusätzlich die interne IP des Servers (nur EINE Zeile aktiv lassen)
#listen_addresses = '127.0.0.1,10.0.0.5'

port = 5432

Vermeiden Sie listen_addresses = '*' (alle Schnittstellen inklusive öffentlicher IP). Nach der Änderung ist ein Neustart nötig:

sudo systemctl restart postgresql@18-main

Verifizieren: sudo ss -tlnp | grep 5432 zeigt nur 127.0.0.1:5432 (und bei Variante B 10.0.0.5:5432), nicht 0.0.0.0:5432.

Schritt 4: pg_hba.conf – Authentifizierungsregeln

Die Datei /etc/postgresql/18/main/pg_hba.conf steuert, wer sich wie anmelden darf. Es gilt: die erste passende Zeile gewinnt, spezifische Regeln stehen deshalb vor allgemeinen. Grundkonfiguration:

# /etc/postgresql/18/main/pg_hba.conf
# Reihenfolge beachten: erste passende Zeile gewinnt!

# Lokaler postgres-Admin via Peer-Auth (OS-Level, kein Passwort nötig):
local   all             postgres                                peer

# Lokale Unix-Socket-Verbindungen mit scram-sha-256:
local   all             all                                     scram-sha-256

# Loopback TCP (IPv4 und IPv6):
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             ::1/128                 scram-sha-256

# Bestimmte Anwendungsrolle aus dem internen Netz:
host    myapp_db        app_user        10.0.0.0/24             scram-sha-256

# Externer Zugriff nur mit SSL und nur aus einem festen Netz (Beispiel):
hostssl myapp_db        app_user        203.0.113.0/24          scram-sha-256

# Alles andere explizit ablehnen:
host    all             all             0.0.0.0/0               reject
host    all             all             ::/0                    reject

host erlaubt TCP-Verbindungen mit und ohne SSL, hostssl nur mit SSL. Im vertrauenswürdigen internen Netz ist host vertretbar, für externe Zugriffe verwenden Sie immer hostssl. Öffnen Sie hostssl nie für 0.0.0.0/0 und all, sonst ist jede Rolle aus dem ganzen Internet per Passwort angreifbar.

Die Authentifizierungsmethoden im Überblick:

MethodeSicherheitPasswort übertragenEmpfehlung
trustKeineNeinNur lokale Dev-Umgebungen
peerOS-LevelNeinLokaler Unix-Socket-Admin
scram-sha-256HochGehasht (Challenge)Produktion – empfohlen
md5NiedrigMD5-gehashtVeraltet, nicht verwenden
passwordKeineKlartextNie verwenden
certSehr hochNein (Zertifikat)Hochsicherheits-Umgebungen
rejectAbsolut–Explizites Sperren

Nach dem Speichern die Konfiguration zunächst auf Syntaxfehler prüfen, dann erst laden:

# Syntaxfehler prüfen (als postgres-User):
sudo -u postgres psql -c "SELECT * FROM pg_hba_file_rules WHERE error IS NOT NULL;"

# Konfiguration ohne Neustart einlesen:
sudo systemctl reload postgresql@18-main

Verbindungstypen auf einen Blick:

TypProtokollSSLTypischer Einsatz
localUnix-Domain-SocketNicht möglichAdmin-Zugriff vom gleichen Host
hostTCP/IPOptionalAnwendungen im internen Netz
hostsslTCP/IPErzwungenExterne Verbindungen, Produktion
hostnosslTCP/IPVerbotenLegacy-Clients ohne SSL

Verifizieren: Die Abfrage auf pg_hba_file_rules liefert 0 Zeilen mit Fehler. psql -h 127.0.0.1 -U app_user -d myapp_db fragt nach dem Passwort (nach Schritt 6), sudo -u postgres psql verbindet ohne Passwort.

Schritt 5: SSL aktivieren

SSL schützt Zugangsdaten und Abfragen vor Mitlesen, sobald PostgreSQL über ein Netzwerk erreichbar ist. Auf Debian und Ubuntu legt pg_createcluster den Cluster bereits mit ssl = on und dem selbst signierten „snakeoil“-Zertifikat des Pakets ssl-cert an. Für ein eigenes Zertifikat tragen Sie die Pfade ein:

# /etc/postgresql/18/main/postgresql.conf
ssl = on
ssl_min_protocol_version = 'TLSv1.2'
ssl_cert_file = '/etc/ssl/certs/postgresql.crt'
ssl_key_file  = '/etc/ssl/private/postgresql.key'
# Debian-Vorgabe ohne eigene Pfade: ssl-cert-snakeoil.pem / .key

Der private Schlüssel darf nicht für andere lesbar sein, sonst startet PostgreSQL nicht: 0600 mit Besitzer postgres oder 0640 mit Besitzer root und einer Gruppe, der postgres angehört:

sudo chmod 0600 /etc/ssl/private/postgresql.key
sudo chown postgres:postgres /etc/ssl/private/postgresql.key

ssl = on allein erzwingt nichts: Erst hostssl-Einträge in pg_hba.conf (Schritt 4) lehnen unverschlüsselte Verbindungen ab.

sudo systemctl restart postgresql@18-main

Verifizieren: sudo -u postgres psql -c "SHOW ssl;" zeigt on. Eine TCP-Verbindung mit psql "host=127.0.0.1 dbname=myapp_db user=app_user sslmode=require" meldet beim Start SSL connection (protocol: TLSv1.3 …).

Schritt 6: Rollen, Datenbank und Schema anlegen

Der postgres-Superuser dient nur der Administration. Anwendungen erhalten eigene Rollen mit genau den Rechten, die sie benötigen.

Ab PostgreSQL 15 hat das public-Schema standardmäßig kein CREATE-Recht mehr für alle Nutzer. Nach einem Upgrade von PostgreSQL 14 oder älter bleibt das alte Recht erhalten und muss manuell entzogen werden. Die folgende Einrichtung trennt die Anwendung zusätzlich in ein eigenes Schema:

sudo -u postgres psql <<'SQL'
-- Anwendungsrolle ohne Superuser-Rechte:
CREATE ROLE app_user
  LOGIN
  PASSWORD 'sicheres_passwort_hier_ersetzen'
  CONNECTION LIMIT 20
  NOCREATEDB
  NOSUPERUSER;

-- Datenbank anlegen:
CREATE DATABASE myapp_db OWNER app_user;

-- Schema-Isolation einrichten:
\c myapp_db
CREATE SCHEMA app AUTHORIZATION app_user;
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
REVOKE ALL   ON SCHEMA public FROM PUBLIC;
GRANT USAGE  ON SCHEMA app TO app_user;
GRANT CREATE ON SCHEMA app TO app_user;

-- search_path für die Rolle setzen (bevorzugt app-Schema):
ALTER ROLE app_user SET search_path TO app, public;
SQL

CONNECTION LIMIT 20 verhindert, dass ein Verbindungsleck der Anwendung alle Verbindungen (max_connections, Standard 100) belegt. Passen Sie den Wert an den Connection-Pool der Anwendung an.

Setzen Sie auch für postgres ein Passwort, für den Fall einer späteren TCP-Regel:

sudo -u postgres psql -c "\password postgres"

Verifizieren: sudo -u postgres psql -c "\dg" listet app_user ohne „Superuser“ und mit „20 connections“. Als app_user scheitert CREATE TABLE public.t(i int); mit „permission denied for schema public“.

Schritt 7: Firewall mit ufw absichern

Die Firewall ergänzt listen_addresses und pg_hba.conf: Nicht freigegebene Absender erreichen Port 5432 gar nicht erst. Ist ufw noch inaktiv, erlauben Sie vor sudo ufw enable unbedingt SSH (sudo ufw allow OpenSSH), sonst sperren Sie sich aus.

# PostgreSQL-Port nur aus dem internen Netz erlauben:
sudo ufw allow from 10.0.0.0/24 to any port 5432 proto tcp

# Alle anderen Verbindungen auf Port 5432 ablehnen:
sudo ufw deny 5432

# Status prüfen:
sudo ufw status verbose

ufw wertet Regeln in Einfügereihenfolge aus: erst die Allow-Regel, dann die Deny-Regel anlegen.

Verifizieren: Von einem Rechner außerhalb des erlaubten IP-Bereichs: nc -zv <server-ip> 5432 scheitert mit Timeout oder „Connection refused“. Aus dem erlaubten Netz meldet es „succeeded“.

Troubleshooting / Typische Fehler

PostgreSQL startet nicht nach SSL-Aktivierung

Meist ist der private Schlüssel zu offen lesbar oder für postgres nicht lesbar. Das Log nennt den Grund:

sudo tail -n 20 /var/log/postgresql/postgresql-18-main.log
ls -la /etc/ssl/private/postgresql.key
# erwartet: -rw------- postgres postgres
sudo chmod 0600 /etc/ssl/private/postgresql.key
sudo chown postgres:postgres /etc/ssl/private/postgresql.key
sudo systemctl start postgresql@18-main

pg_hba.conf-Änderungen ohne Wirkung

Änderungen an pg_hba.conf wirken erst nach einem Reload. Prüfen Sie außerdem, ob eine weiter oben stehende Zeile bereits passt (erste passende Zeile gewinnt).

sudo systemctl reload postgresql@18-main
# Alternativ aus psql:
sudo -u postgres psql -c "SELECT pg_reload_conf();"

listen_addresses-Änderung hat keine Wirkung trotz reload

listen_addresses erfordert einen Neustart: sudo systemctl restart postgresql@18-main.

Verbindung schlägt mit „FATAL: password authentication failed“ fehl

Mögliche Ursachen: (1) Die Client-Bibliothek ist zu alt für scram-sha-256 (libpq vor Version 10): aktualisieren. (2) Das Passwort wurde noch als MD5-Hash gespeichert: mit \password rollenname in psql neu setzen.

Syntaxfehler in pg_hba.conf finden

sudo -u postgres psql -c \
  "SELECT line_number, type, address, error FROM pg_hba_file_rules WHERE error IS NOT NULL;"

Distro-Paket statt PGDG installiert

Zeigt psql --version eine ältere Version als 18, ist das Distributionspaket installiert. apt-cache policy postgresql muss als Candidate eine Version von apt.postgresql.org zeigen; sonst Schritt 1 wiederholen.

Häufige Fragen

Was bringt das PGDG-Repository gegenüber dem Ubuntu-Paket?

Es liefert alle unterstützten Hauptversionen (Stand September 2026: 14 bis 18) mit zeitnahen Minor-Updates. Ubuntu 22.04 enthält PostgreSQL 14, Ubuntu 24.04 PostgreSQL 16. Mehrere Hauptversionen lassen sich parallel installieren.

Wie lesen Sie pg_hba.conf neu ein, ohne PostgreSQL zu stoppen?

Mit sudo systemctl reload postgresql@18-main oder in psql mit SELECT pg_reload_conf();. Das gilt für pg_hba.conf und Parameter ohne Neustartpflicht wie log_min_messages, nicht für listen_addresses.

Können Sie PostgreSQL 17 und 18 gleichzeitig betreiben?

Ja. Jeder Cluster erhält automatisch einen eigenen Port (5432, 5433 …), pg_lsclusters zeigt Version, Port und Status.

Was hat sich am public-Schema ab PostgreSQL 15 geändert?

Ab PostgreSQL 15 hat PUBLIC kein CREATE-Recht mehr auf dem public-Schema. Nach einem Upgrade von 14 oder älter bleibt das alte Recht bestehen; ziehen Sie REVOKE CREATE ON SCHEMA public FROM PUBLIC; nach. Sonst können alle Benutzer dort Objekte anlegen, etwa gleichnamige Funktionen, die andere Rollen versehentlich aufrufen.

Wie erzwingen Sie ausschließlich SSL-Verbindungen?

ssl = on in postgresql.conf und alle TCP-Einträge in pg_hba.conf als hostssl statt host.

Was ist der Unterschied zwischen GRANT USAGE und GRANT CREATE auf einem Schema?

GRANT USAGE ON SCHEMA app erlaubt, Objekte im Schema anzusprechen; das Lesen einer Tabelle erfordert zusätzlich GRANT SELECT. GRANT CREATE ON SCHEMA app erlaubt zusätzlich das Anlegen neuer Tabellen, Funktionen und anderer Objekte. Eine Leserolle braucht USAGE plus SELECT, eine Rolle, die Tabellen anlegt, zusätzlich CREATE.

Fazit

Das PGDG-Repository hält PostgreSQL aktuell, die drei Schichten begrenzen den Zugriff: listen_addresses bestimmt die erreichbaren Adressen, pg_hba.conf wer sich wie anmeldet, eigene Rollen mit minimalen Rechten begrenzen den Schaden eines kompromittierten Anwendungskontos. Firewall und SSL ergänzen das. Als Nächstes richten Sie Backups und ein Performance-Tuning ein (Links unten).

Weiterführende Anleitungen und Quellen

  1. PostgreSQL pg_dump und pg_restore: Anleitung für Backup und Migration per Kommandozeile
  2. MySQL & PostgreSQL Backup automatisieren mit cron: mysqldump, pg_dump, Rotation und rclone-Cloud-Sync
  3. PostgreSQL-Performance-Tuning für Einsteiger
  4. VPS absichern und härten: Anleitung mit UFW, SSH-Keys und Fail2Ban
  5. PostgreSQL: Linux Downloads (Ubuntu) – offizielle PGDG-Repository-Anleitung
  6. PostgreSQL Docs: The pg_hba.conf File (Kap. 20.1)
  7. PostgreSQL Docs: Role Attributes (Kap. 21.2)
  8. PostgreSQL Docs: SSL Support (Kap. 19.9)