PostgreSQL auf Debian und Ubuntu installieren und einrichten

Veröffentlicht am 16 Min. Lesezeit

Installation aus dem Distributionspaket oder aus dem PGDG-Repo, erster Zugriff über den Benutzer postgres, Datenbank und Rolle anlegen, pg_hba.conf verstehen und eine Sicherung, die wirklich trägt.

PostgreSQL ist auf Debian und Ubuntu in zwei Minuten installiert. Die restlichen zwei Stunden gehen meistens dafür drauf, dass sich niemand anmelden kann. Dieser Artikel führt die Installation zu Ende: Paketwahl, erster Zugriff, Datenbank und Benutzer, die Zugriffsregeln in pg_hba.conf und eine Sicherung, von der man weiß, dass sie sich zurückspielen lässt.

Alle Befehle laufen als root. Wer sich als normaler Benutzer anmeldet, stellt sudo voran. Die Versionsnummer 17 in Pfaden ersetzt du durch die Version, die auf deinem System tatsächlich installiert ist.

Welche PostgreSQL-Version steckt in welcher Distribution

Der wichtigste Unterschied zwischen den vier gängigen Systemen ist die Hauptversion, die aus dem Distributionsrepo kommt. Sie ist fest an das Release gebunden und wechselt über die Laufzeit der Distribution nicht mehr.

DistributionPostgreSQL aus dem Distributionsrepo
Debian 13 (trixie)17
Debian 12 (bookworm)15
Ubuntu 24.04 LTS (noble)16
Ubuntu 22.04 LTS (jammy)14

Diese Streuung hat praktische Folgen. Ein Dump aus Debian 13 lässt sich nicht ohne Weiteres in Ubuntu 22.04 einspielen. Und wer auf Ubuntu 22.04 arbeitet, sollte wissen, dass PostgreSQL 14 laut Versionierungsrichtlinie der PostgreSQL Global Development Group am 12. November 2026 aus dem Community-Support fällt. Ubuntu liefert für 22.04 zwar weiterhin Sicherheitsaktualisierungen im Rahmen des LTS-Zyklus, aber es fließen keine Upstream-Fixes mehr nach. Für neue Projekte auf 22.04 ist das ein starkes Argument, gleich zum PGDG-Repo zu greifen.

Was auf deinem System bereitsteht, sagt dir ein Blick in die Paketdatenbank, bevor du irgendetwas installierst:

apt update
apt-cache policy postgresql

Die Zeile Kandidat beziehungsweise Candidate zeigt eine Versionsnummer wie 17+283. Die Zahl vor dem Pluszeichen ist die Hauptversion von PostgreSQL, der Rest ist die Versionsnummer des Debian-Metapakets.

Installation aus dem Distributionspaket

Für die meisten Anwendungsfälle ist das Distributionspaket die richtige Wahl. Es ist in die Sicherheitsaktualisierungen der Distribution eingebunden, es funktioniert mit den Bibliotheken des Systems und es macht bei einem Release-Upgrade keine Probleme.

apt install -y postgresql postgresql-contrib

postgresql-contrib bringt die mitgelieferten Erweiterungen mit, darunter pgcrypto, uuid-ossp und pg_stat_statements. Ohne das Paket scheitern viele Anwendungen später an einem ERROR: could not open extension control file, und die Fehlersuche dauert länger als die Installation.

Debian und Ubuntu legen bei der Installation automatisch einen ersten Cluster namens main an und starten ihn. Cluster bedeutet hier eine laufende Instanz mit eigenem Datenverzeichnis, eigenem Port und eigener Konfiguration. Ob das geklappt hat, beantwortet nicht der Exitcode von apt, sondern das:

pg_lsclusters

Die Ausgabe muss in der Spalte Status ein online zeigen:

Ver Cluster Port Status Owner    Data directory              Log file
17  main    5432 online postgres /var/lib/postgresql/17/main /var/log/postgresql/postgresql-17-main.log

Steht dort down, startest du den Dienst nach. service postgresql start funktioniert auf allen vier Systemen, auch in Containern ohne systemd. Auf einem normalen Server tut es systemctl start postgresql genauso.

service postgresql start
pg_isready

pg_isready antwortet mit /var/run/postgresql:5432 - accepting connections und liefert Exitcode 0. Das ist der erste harte Beweis, dass der Server erreichbar ist, und er lässt sich in Monitoring-Skripten weiterverwenden.

Wann sich das PGDG-Repo lohnt und wie man es sauber einbindet

Das offizielle Repo unter apt.postgresql.org liefert alle unterstützten Hauptversionen parallel für trixie, bookworm, noble und jammy. Es ist die richtige Wahl, wenn du eine bestimmte Hauptversion brauchst, weil die Anwendung sie voraussetzt, wenn du Erweiterungen benötigst, die Debian nicht paketiert, oder wenn dein Distributionsstand auf eine Version zeigt, die bald aus dem Support läuft.

Der Schlüssel gehört in eine eigene Datei, nicht mehr in den abgekündigten apt-key-Schlüsselbund. Debian 13 und Ubuntu 24.04 bevorzugen außerdem das deb822-Format mit der Endung .sources, das aber auch auf Debian 12 und Ubuntu 22.04 funktioniert:

apt install -y curl ca-certificates
install -d /usr/share/postgresql-common/pgdg
curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
cat > /etc/apt/sources.list.d/pgdg.sources <<EOF
Types: deb
URIs: https://apt.postgresql.org/pub/repos/apt
Suites: $(. /etc/os-release && echo $VERSION_CODENAME)-pgdg
Components: main
Signed-By: /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc
EOF

Die Zeile mit $(. /etc/os-release ...) setzt automatisch trixie-pgdg, bookworm-pgdg, noble-pgdg oder jammy-pgdg ein. Danach:

apt update
apt-cache policy postgresql-18

Das Paket postgresql-common bringt für denselben Zweck ein Fertigskript mit, /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh. Es ist eine Alternative zum Schlüssel und zur pgdg.sources von oben, keine Ergänzung. Führst du beides aus, legt das Skript zusätzlich eine /etc/apt/sources.list.d/pgdg.list an, und apt warnt danach bei jedem Lauf: W: Target Packages (main/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/pgdg.list:1 and /etc/apt/sources.list.d/pgdg.sources:1. Wer das Skript den Handgriffen oben vorzieht, installiert vorher gnupg mit, also apt install -y curl ca-certificates gnupg. Die ältere Skriptfassung auf Ubuntu 22.04 importiert den Schlüssel nämlich noch über apt-key und bricht ohne gnupg mit E: gnupg, gnupg2 and gnupg1 do not seem to be installed, but one of them is required for this operation und Exitcode 255 ab. Auf Debian 13, Debian 12 und Ubuntu 24.04 legt die neuere Fassung den Schlüssel direkt als .asc ab und läuft ohne Zusatzpaket durch.

Die Falle: zwei Cluster, zwei Ports

Wenn du auf einem System mit bereits installiertem Distributionspaket nun eine neue Hauptversion installierst, entsteht ein zweiter Cluster. Der bekommt nicht Port 5432, sondern den nächsten freien, also 5433. Anwendungen verbinden sich weiter zur alten Version, ohne dass eine Fehlermeldung darauf hinweist. Das ist die häufigste Ursache für den Satz "ich habe doch PostgreSQL 18 installiert, aber SELECT version() zeigt 15".

apt install -y postgresql-18
pg_lsclusters

Jetzt stehen dort zwei Zeilen mit unterschiedlichen Ports. Willst du die Daten in die neue Version übernehmen, ist pg_upgradecluster das richtige Werkzeug, nicht ein Dump von Hand. Es setzt voraus, dass beide Serverpakete installiert sind, und es lässt den alten Cluster gestoppt liegen, statt ihn zu löschen:

pg_upgradecluster 15 main

Prüfe danach mit pg_lsclusters, welcher Cluster auf Port 5432 liegt, und teste die Anwendung, bevor du den alten Cluster mit pg_dropcluster --stop 15 main endgültig entfernst. Dieser Befehl löscht das Datenverzeichnis ohne Rückfrage.

Der erste Zugriff, und warum root kein psql darf

Der klassische Stolperstein direkt nach der Installation:

psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  role "root" does not exist

Das ist kein Fehler, sondern das erwartete Verhalten. Debian und Ubuntu konfigurieren lokale Socket-Verbindungen mit der Methode peer. PostgreSQL fragt dabei den Kernel, unter welchem Systembenutzer die Verbindung geöffnet wurde, und verlangt, dass es eine gleichnamige Datenbankrolle gibt. Es existiert nur die Rolle postgres, also musst du zuerst in diesen Systembenutzer wechseln.

su - postgres

Danach startest du psql ohne Argumente. Zum Verlassen der Shell dient exit. Für einzelne Befehle aus einem Skript heraus ist ein Wechsel pro Befehl praktischer:

runuser -u postgres -- psql -c "SELECT version();"

Wer sudo installiert hat, schreibt stattdessen sudo -u postgres psql -c "SELECT version();". Beide Varianten sind gleichwertig. Bei sudo erscheint häufig die Warnung could not change directory to "/root": Permission denied. Sie ist folgenlos, weil der Benutzer postgres das Arbeitsverzeichnis von root nicht betreten darf, der Befehl aber trotzdem ausgeführt wird.

Diese drei Abfragen sagen dir, womit du es zu tun hast, und sie sind bei jeder Fehlersuche der erste Schritt:

runuser -u postgres -- psql -c "SHOW server_version;"
runuser -u postgres -- psql -c "SHOW config_file;"
runuser -u postgres -- psql -c "SHOW hba_file;"

Der letzte Befehl ist besonders nützlich. Er nennt den Pfad, den der laufende Server wirklich liest, typischerweise /etc/postgresql/17/main/pg_hba.conf. Wenn du eine Datei bearbeitest und sich nichts ändert, hast du fast immer die Konfiguration eines anderen Clusters vor dir.

Innerhalb von psql helfen die Meta-Befehle: \l listet Datenbanken, \du die Rollen, \dt die Tabellen der aktuellen Datenbank, \conninfo zeigt, als wer und wohin du verbunden bist, und \q beendet die Sitzung.

Datenbank und Benutzer anlegen

Für jede Anwendung gehören eine eigene Rolle und eine eigene Datenbank angelegt. Die Reihenfolge ist wichtig, denn die Datenbank soll der Rolle direkt gehören.

runuser -u postgres -- psql -c "CREATE ROLE appuser LOGIN PASSWORD 'DeinStarkesPasswort';"
runuser -u postgres -- psql -c "CREATE DATABASE appdb OWNER appuser;"

Seit PostgreSQL 14 werden Passwörter standardmäßig mit scram-sha-256 gespeichert, das gilt also auf allen vier hier behandelten Systemen. Das Passwort landet dabei nicht im Klartext in der Datenbank, aber es steht in deiner Shell-History. Wer das vermeiden will, nutzt in psql stattdessen \password appuser, das interaktiv abfragt.

Die Falle seit PostgreSQL 15: permission denied for schema public

Ein Verhalten, das viele ältere Anleitungen noch nicht kennen: Ab PostgreSQL 15 darf nicht mehr jeder Benutzer Objekte im Schema public anlegen. Betroffen sind Debian 12, Debian 13 und Ubuntu 24.04. Nur Ubuntu 22.04 mit PostgreSQL 14 verhält sich noch nach altem Muster. Der Fehler sieht so aus:

ERROR:  permission denied for schema public
LINE 1: CREATE TABLE kunden (id serial primary key);

Der saubere Weg ist der oben gezeigte: Die Datenbank gehört der Rolle. Das Schema public gehört seit Version 15 der Rolle pg_database_owner, und der jeweilige Eigentümer der Datenbank ist darin implizit Mitglied. Wer die Datenbank hingegen ohne OWNER angelegt hat, holt die Berechtigung nach. Beachte, dass diese Anweisung in der betroffenen Datenbank ausgeführt werden muss, nicht in postgres:

runuser -u postgres -- psql -d appdb -c "GRANT ALL ON SCHEMA public TO appuser;"

Nachweis, dass die Rechte stimmen

Ein CREATE ROLE ohne Fehler bedeutet noch nicht, dass sich die Anwendung anmelden kann. Der Beweis ist eine echte Anmeldung über TCP mit anschließendem Schreibzugriff. PGPASSWORD ist hier nur zum Testen gedacht, für den Dauerbetrieb siehe weiter unten:

PGPASSWORD='DeinStarkesPasswort' psql -h 127.0.0.1 -U appuser -d appdb -c "SELECT current_user, current_database();"
PGPASSWORD='DeinStarkesPasswort' psql -h 127.0.0.1 -U appuser -d appdb -c "CREATE TABLE probe (id int);"

Läuft beides durch, ist die Kombination aus Rolle, Passwort, Datenbank und Schemarechten vollständig. Die Tabelle probe bleibt bewusst stehen, denn der Sicherungstest weiter unten braucht wenigstens ein Objekt in der Datenbank, sonst prüft er ins Leere. Zur Kontrolle listest du die Objekte:

runuser -u postgres -- psql -c "\du"
runuser -u postgres -- psql -c "\l"

Ein Wort zur Zeichenkodierung: Ist das Systemgebietsschema beim Anlegen des Clusters nicht auf UTF-8 gestanden, kann die Vorlagendatenbank SQL_ASCII sein. Ein CREATE DATABASE ... ENCODING 'UTF8' scheitert dann mit ERROR: new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII). Der Ausweg ist TEMPLATE template0 beim Anlegen, die saubere Lösung ist ein System mit UTF-8-Gebietsschema.

pg_hba.conf verstehen, die häufigste Fehlerquelle

Die Datei pg_hba.conf (host-based authentication) entscheidet vor jeder Passwortprüfung, ob eine Verbindung überhaupt zugelassen wird. Sie wird von oben nach unten gelesen, und die erste passende Zeile gewinnt. Passt keine, wird die Verbindung abgelehnt. Eine großzügige Regel weiter unten hilft dir nicht, wenn eine strengere weiter oben zuerst greift. Das ist der mit Abstand häufigste Konfigurationsfehler.

Der Auslieferungszustand auf Debian und Ubuntu sieht so aus:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             postgres                                peer
local   all             all                                     peer
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             ::1/128                 scram-sha-256

So steht es auf den vier hier behandelten Systemen. Auf älteren Ständen, etwa Debian 11 mit PostgreSQL 13, tragen die beiden host-Zeilen noch md5 statt scram-sha-256. Die Anmeldung über TCP funktioniert in beiden Fällen, aber verlassen solltest du dich auf md5 nicht mehr.

Die Spalten bedeuten: local steht für den Unix-Socket, host für TCP mit oder ohne TLS, hostssl nur für TLS-Verbindungen. Danach folgen Datenbank, Rolle, Netzbereich in CIDR-Schreibweise und die Methode. Wichtig sind vier Methoden. peer prüft den Systembenutzer und funktioniert nur über den Socket. scram-sha-256 ist die moderne Passwortmethode und die richtige Wahl für alles über TCP. md5 ist abgekündigt und sollte in neuen Konfigurationen nicht mehr auftauchen. trust lässt jeden ohne Prüfung herein und hat auf einem erreichbaren Server nichts verloren.

Die Fehlermeldungen im Wortlaut

Wer sie einmal auseinanderhalten kann, spart sich viel Raten:

FATAL:  Peer authentication failed for user "appuser"

Du bist über den Socket verbunden, aber dein Systembenutzer heißt anders als die Rolle. Entweder Benutzer wechseln oder über -h 127.0.0.1 verbinden, damit die host-Zeile greift.

FATAL:  no pg_hba.conf entry for host "198.51.100.4", user "appuser", database "appdb", no encryption

Der Server ist erreichbar, aber keine Regel passt auf diese Kombination aus Quelladresse, Rolle und Datenbank. Es fehlt eine Zeile, oder das Netz in der vorhandenen Zeile deckt die Adresse nicht ab.

FATAL:  password authentication failed for user "appuser"

Die Regel greift, das Passwort stimmt nicht. Häufig, weil die Rolle ohne LOGIN angelegt wurde oder das Passwort noch aus einer früheren Installation stammt.

psql: error: connection to server at "203.0.113.10", port 5432 failed: Connection refused

Hier war pg_hba.conf nie im Spiel. Entweder läuft der Server nicht, oder er lauscht nicht auf dieser Adresse, oder eine Firewall blockt. Dazu gleich mehr.

Änderungen prüfen, bevor du neu lädst

PostgreSQL bietet eine Systemsicht, die die geparsten Regeln zeigt, samt Zeilennummer und Syntaxfehlern. Sie beantwortet die Frage, welche Regel der Server tatsächlich sieht, statt welche du geschrieben zu haben glaubst:

runuser -u postgres -- psql -c "SELECT line_number, type, database, user_name, address, auth_method FROM pg_hba_file_rules;"

Änderungen an pg_hba.conf brauchen keinen Neustart, ein Neuladen genügt und trennt keine bestehenden Verbindungen:

runuser -u postgres -- psql -c "SELECT pg_reload_conf();"

Alternativ service postgresql reload. Ein echter Neustart ist nur nötig, wenn du Parameter wie listen_addresses, port oder shared_buffers geändert hast.

Zugriff von außen freischalten

Ab Werk lauscht PostgreSQL nur auf localhost. Das ist eine gute Voreinstellung, und du solltest sie nur aufgeben, wenn es wirklich nötig ist. Zwei Dinge müssen zusammenkommen: Der Server muss auf der Adresse lauschen, und pg_hba.conf muss die Quelle erlauben. Fehlt das eine, bekommst du Connection refused, fehlt das andere, bekommst du no pg_hba.conf entry.

Die Konfiguration liegt unter /etc/postgresql/17/main/postgresql.conf. Debian liefert dafür das Werkzeug pg_conftool mit, das die Datei zuverlässiger bearbeitet als ein Editor-Suchlauf:

pg_conftool 17 main show listen_addresses
pg_conftool 17 main set listen_addresses '10.0.0.5,127.0.0.1'

Trage konkrete Adressen ein statt *. Auf einem Server mit öffentlicher und interner Adresse bindest du so nur an das interne Netz. Danach ergänzt du eine Regel in pg_hba.conf, so eng wie möglich gefasst:

host    appdb    appuser    10.0.0.0/24    scram-sha-256

Nach einem Neustart mit service postgresql restart prüfst du zuerst, worauf der Prozess wirklich lauscht. ss -lntp | grep 5432 zeigt die gebundenen Adressen. Steht dort nur 127.0.0.1:5432, hat die Änderung nicht gegriffen, meist weil ein zweiter Cluster gemeint war oder eine Datei unter conf.d den Wert überschreibt.

Die Firewall braucht ebenfalls eine Regel, und zwar eine mit Quellangabe. Ein pauschal offener Port 5432 im Internet wird innerhalb von Stunden gescannt:

ufw allow from 10.0.0.0/24 to any port 5432 proto tcp

Ehrlicher Rat: In den meisten Fällen ist die bessere Lösung, den Port gar nicht zu öffnen. Ein SSH-Tunnel mit ssh -L 5432:127.0.0.1:5432 benutzer@server reicht für Wartungszugriffe völlig aus. Für dauerhafte Verbindungen zwischen mehreren Servern ist ein WireGuard-Netz die sauberere Wahl, weil die Datenbank dann weiterhin nur auf einer privaten Adresse lauscht. Debian und Ubuntu aktivieren TLS übrigens standardmäßig mit einem selbstsignierten Zertifikat, deshalb funktioniert sslmode=require sofort. Echten Schutz vor einem Angreifer in der Leitung bietet aber erst sslmode=verify-full mit einem Zertifikat, dem der Client vertraut.

Sicherung mit pg_dump, und der Nachweis, dass sie etwas taugt

Für einzelne Datenbanken ist das Custom-Format die beste Wahl. Es ist komprimiert, es lässt sich selektiv zurückspielen und es kann parallel eingelesen werden:

runuser -u postgres -- pg_dump -Fc -d appdb -f /var/lib/postgresql/appdb.dump

Ein häufig übersehener Punkt: pg_dump sichert keine Rollen und keine Passwörter. Die liegen clusterweit und müssen getrennt gesichert werden, sonst fehlen nach einer Wiederherstellung genau die Benutzer, die die Anwendung braucht:

runuser -u postgres -- pg_dumpall --globals-only -f /var/lib/postgresql/globals.sql

Wenn die Versionen nicht zusammenpassen

pg_dump: error: server version: 17.5; pg_dump version: 15.10
pg_dump: error: aborting because of server version mismatch

Die Regel lautet: pg_dump darf neuer sein als der Server, niemals älter. Auf Debian und Ubuntu ist das leicht zu lösen, weil /usr/bin/pg_dump nur ein Wrapper ist, der die passende Programmversion auswählt. Installiere das Paket postgresql-client-18, dann steht die neuere Fassung bereit. Und mit der Debian-Erweiterung --cluster zwingst du den Wrapper gezielt auf einen bestimmten Cluster, hier auf Version 17, Cluster main:

pg_dump --version
runuser -u postgres -- pg_dump --cluster 17/main -Fc -d appdb -f /var/lib/postgresql/appdb.dump

Passwörter aus dem Skript heraushalten

Für automatische Sicherungen gehört das Passwort in eine .pgpass im Format host:port:datenbank:benutzer:passwort. PostgreSQL ignoriert die Datei kommentarlos, wenn die Rechte zu weit sind. Genauso wichtig ist, in wessen Home-Verzeichnis sie liegt, denn gelesen wird immer die Datei des Benutzers, unter dem der Befehl tatsächlich läuft. Ein ~/.pgpass als root bleibt wirkungslos, solange die Sicherung wie in diesem Artikel über runuser -u postgres läuft. Dann zählt das Home von postgres:

touch /var/lib/postgresql/.pgpass
chown postgres:postgres /var/lib/postgresql/.pgpass
chmod 0600 /var/lib/postgresql/.pgpass

Leer bleibt die Datei ebenfalls wirkungslos. Trag eine Zeile pro Verbindung ein, etwa 127.0.0.1:5432:appdb:appuser:DeinStarkesPasswort. Läuft dein Sicherungsjob stattdessen direkt als root ohne Benutzerwechsel, gehört dieselbe Datei nach /root/.pgpass.

Die Sicherung überprüfen

Eine Sicherungsdatei, die noch nie zurückgespielt wurde, ist eine Vermutung. Der Test dauert eine Minute. Erst das Inhaltsverzeichnis anschauen, dann in eine Wegwerf-Datenbank einlesen und die Tabellen zählen:

runuser -u postgres -- pg_restore -l /var/lib/postgresql/appdb.dump | head -n 20
runuser -u postgres -- createdb appdb_restore_test
runuser -u postgres -- pg_restore -d appdb_restore_test /var/lib/postgresql/appdb.dump
runuser -u postgres -- psql -d appdb_restore_test -c "\dt"
runuser -u postgres -- dropdb appdb_restore_test

Zeigt \dt dieselben Tabellen wie im Original, hier also mindestens die Tabelle probe, ist die Sicherung brauchbar. Meldet der Befehl dagegen Did not find any relations., war die gesicherte Datenbank leer und der Test beweist nichts. In appdb räumst du die Probetabelle danach mit runuser -u postgres -- psql -d appdb -c "DROP TABLE probe;" wieder weg. Für den täglichen Betrieb genügt ein Eintrag in /etc/cron.d, der beide Dateien mit Datum im Namen ablegt und ältere aufräumt. Wichtig ist, dass die Dateien anschließend den Server verlassen. Eine Sicherung auf derselben Platte hilft gegen ein versehentliches DROP TABLE, nicht gegen einen Ausfall der Hardware.

Wenn der Cluster nicht startet

Startet der Dienst nicht, sagt dir der Dienstestatus meist nur, dass etwas fehlgeschlagen ist. Die eigentliche Ursache steht im Cluster-Log:

tail -n 30 /var/log/postgresql/postgresql-*-main.log

Eine Zeile darfst du dabei getrost überlesen. Die aus dem ersten Abschnitt bekannte Meldung FATAL: role "root" does not exist stammt meist von pg_isready: Das Werkzeug baut seinen Verbindungsversuch mit dem angemeldeten Systembenutzer auf, also als root, und der Server protokolliert die unbekannte Rolle. Der Rückgabewert bleibt trotzdem 0, die Ausgabe lautet accepting connections, und der Cluster ist völlig in Ordnung.

Auf Systemen mit systemd liefert journalctl -u postgresql@17-main --no-pager -n 50 dieselben Zeilen. Beachte die versionsbehaftete Unit: postgresql.service ist nur eine Hülle, die alle Cluster startet, und sie meldet auch dann Erfolg, wenn ein einzelner Cluster gescheitert ist. Deshalb ist pg_lsclusters die verlässlichere Kontrolle.

Drei Meldungen decken die meisten Fälle ab. could not bind IPv4 address "0.0.0.0": Address already in use bedeutet, dass ein anderer Cluster den Port belegt, siehe den Abschnitt zu den zwei Clustern. Eine Meldung über No space left on device beim Schreiben der postmaster.pid heißt schlicht volle Platte, was du mit df -h bestätigst. Und Fehler zu ungültigen Rechten am Datenverzeichnis treten nach unbedachten chmod- oder chown-Läufen auf: /var/lib/postgresql/17/main muss dem Benutzer postgres gehören und den Modus 0700 tragen.

Zum Abschluss noch ein Hinweis zum Betrieb: PostgreSQL läuft in der Grundeinstellung konservativ und nutzt den Arbeitsspeicher eines Servers bei Weitem nicht aus. Bevor du an shared_buffers und work_mem drehst, aktiviere pg_stat_statements aus dem contrib-Paket und schau dir an, welche Abfragen tatsächlich Zeit kosten. In der Praxis liegt der Engpass fast immer bei einem fehlenden Index, nicht bei den Speicherparametern.

Häufige Fragen

Welche PostgreSQL-Version bekomme ich auf meiner Distribution?
Aus dem Distributionsrepo liefert Debian 13 die Version 17, Debian 12 die Version 15, Ubuntu 24.04 die Version 16 und Ubuntu 22.04 die Version 14. Diese Zuordnung ist an das jeweilige Release gebunden und ändert sich über dessen Laufzeit nicht mehr. Wer eine andere Hauptversion braucht, bindet das offizielle PGDG-Repo unter apt.postgresql.org ein, das trixie, bookworm, noble und jammy unterstützt.
Warum bekomme ich beim Start von psql die Meldung "role root does not exist"?
Debian und Ubuntu nutzen für lokale Socket-Verbindungen die Methode peer. PostgreSQL vergleicht dabei den Systembenutzer mit dem Rollennamen, und eine Rolle namens root existiert nicht. Wechsle mit su - postgres in den Systembenutzer postgres oder führe einzelne Befehle mit runuser -u postgres -- psql aus, mit sudo entsprechend sudo -u postgres psql.
Was bedeutet "no pg_hba.conf entry for host" und wie behebe ich das?
Der Server ist erreichbar, aber keine Zeile in pg_hba.conf passt auf die Kombination aus Quelladresse, Rolle und Datenbank. Ergänze eine host-Zeile mit dem passenden CIDR-Netz und der Methode scram-sha-256. Da die erste passende Zeile gewinnt, muss sie vor jeder allgemeineren Ablehnung stehen. Prüfe das Ergebnis mit einer Abfrage auf die Sicht pg_hba_file_rules und lade die Konfiguration mit SELECT pg_reload_conf() neu.
Warum kann mein Benutzer keine Tabellen anlegen, obwohl er die Datenbank nutzen darf?
Ab PostgreSQL 15 darf nicht mehr jeder Benutzer im Schema public schreiben, der Fehler lautet "permission denied for schema public". Betroffen sind Debian 12, Debian 13 und Ubuntu 24.04. Am saubersten legst du die Datenbank direkt mit CREATE DATABASE appdb OWNER appuser an, denn das Schema public gehört der Rolle pg_database_owner. Nachträglich hilft GRANT ALL ON SCHEMA public TO appuser, ausgeführt in der betroffenen Datenbank.
Muss ich PostgreSQL nach einer Änderung an pg_hba.conf neu starten?
Nein, ein Neuladen genügt und trennt keine bestehenden Verbindungen. Das geht mit SELECT pg_reload_conf() oder mit service postgresql reload. Ein echter Neustart ist nur bei Parametern nötig, die beim Start gelesen werden, etwa listen_addresses, port oder shared_buffers.
Reicht pg_dump als vollständige Sicherung?
Nein. pg_dump sichert eine einzelne Datenbank, aber keine Rollen und keine Passwörter, weil die clusterweit gespeichert sind. Ergänze deshalb pg_dumpall --globals-only. Und prüfe die Sicherung, indem du sie mit pg_restore in eine Wegwerf-Datenbank einliest und die Tabellen mit \dt vergleichst. Die gesicherte Datenbank muss dafür überhaupt Tabellen enthalten, sonst meldet \dt nur "Did not find any relations." und der Test beweist nichts. Eine nie zurückgespielte Sicherung ist nur eine Vermutung.

PostgreSQL Debian Ubuntu Datenbank pg_hba.conf pg_dump Linux Server-Administration