PostgreSQL
<h3 id="bkmrk-1.1.-einleitung"><span class="nh-number">1.
1. </span>Einleitung</h3>
<p>
PostgreSQL ist ein relationales Open-Source-Datenbanksystem. Es eignet sich sowohl für klassische Anwendungsdatenbanken als auch für komplexere Fachverfahren.</p><p>
Gegenüber <strong>MySQL</strong> bietet PostgreSQL in der Regel einen größeren Funktionsumfang für anspruchsvollere Datenmodelle. Dazu gehören unter anderem eine stärkere Orientierung am SQL-Standard, eine feinere Rechteverwaltung, Schemas zur logischen Trennung von Objekten sowie erweiterte Mechanismen für Transaktionen und Erweiterungen.</p><p>
Gegenüber <strong>Oracle Database</strong> ist PostgreSQL lizenzkostenfrei und offen. Gleichzeitig stellt es viele vergleichbare Grundkonzepte bereit, zum Beispiel Rollen, Schemas, Views, Trigger und Transaktionen. Oracle ist dagegen stärker proprietär geprägt und wird häufig in großen Enterprise-Umgebungen mit herstellerspezifischen Werkzeugen und Lizenzmodellen betrieben.</p><p>
In Docker- und Ansible-basierten Umgebungen ist PostgreSQL besonders attraktiv, weil es sich gut automatisieren, standardisieren und wartbar betreiben lässt.</p>
<h3
1.1. id="bkmrk-1.2.-allgemein"><spanAllgemein
Beispielsystem:</strong></p><ul><li>
srv3306.lej.eis.network</code></li>
<li>
Port: 5432</code></li>
<li>
Datenbank: postgres</code></li>
<li>
Benutzer: postgres</code></li>
<li>
Passwort: siehe Serverpool oder docker-compose</code></li>
</ul>
<p>
Ziel ist eine saubere Trennung zwischen administrativen Rollen, Applikationsrollen, Datenbanken, Schemas sowie Dump- und Restore-Prozessen.</p>
<h3
1.2. id="bkmrk-1.3.-rollen-und-namenskonzept"><span class="nh-number">1.3. </span>Rollen- und Namenskonzept</h3>
<p>
Für den Betrieb wird empfohlen, administrative Rollen und Applikationsrollen sauber zu trennen.</p>
<p><strong>
1.2.1. Administrative Rolle</strong></p>
<p>
Die administrative Rolle ist für Verwaltungsaufgaben zuständig, zum Beispiel:</p><ul><li>
Beispiele für Namenskonventionen:</p><ul><li><code>sachdev</code></li><li><code>sachtest</code></li><li><code>sachpilot</code></li><li><code>sachprod</code></li><li><code>beratungdev</code></li><li><code>beratungtest</code></li><li><code>beratungpilot</code></li><li><code>beratungprod</code></li></ul>
sachdev
sachtest
sachpilot
sachprod
beratungdev
beratungtest
beratungpilot
beratungprod
<p><strong>Applikationsrolle</strong></p><p>Die Applikationsrolle wird von der Anwendung im Tagesbetrieb verwendet.</p><p>Typische Rechte:</p><ul><li><code>LOGIN</code></li><li><code>CONNECT</code></li><li><code>USAGE</code> auf das Anwendungsschema</li><li><code>SELECT</code></li><li><code>INSERT</code></li><li><code>UPDATE</code></li><li><code>DELETE</code></li><li>bei Bedarf <code>USAGE, SELECT</code> auf Sequenzen</li><li>nur bei echtem Bedarf <code>CREATE</code> im Anwendungsschema</li></ul><p>Beispiele für Namenskonventionen:</p><ul><li><code>sachworkdev</code></li><li><code>sachworktest</code></li><li><code>sachworkpilot</code></li><li><code>sachworkprod</code></li><li><code>beratungworkdev</code></li><li><code>beratungworktest</code></li><li><code>beratungworkpilot</code></li><li><code>beratungworkprod</code></li></ul><p><strong>Best Practice:</strong> Rollenattribute wie <code>CREATEDB oder </code><code>CREATEROLE nur vergeben, wenn sie tatsächlich benötigt werden. Eine allgemeine Vergabe von </code><code>CREATEROLE ist in den meisten Betriebsfällen nicht erforderlich.</code></p>
1.2.2. Applikationsrolle
Die Applikationsrolle wird von der Anwendung im Tagesbetrieb verwendet.
<h3Typische id="bkmrk-Rechte:
LOGIN
CONNECT
USAGE auf das Anwendungsschema
SELECT
INSERT
UPDATE
DELETE
bei Bedarf USAGE, SELECT auf Sequenzen
nur bei echtem Bedarf CREATE im Anwendungsschema
Beispiele für Namenskonventionen:
sachworkdev
sachworktest
sachworkpilot
sachworkprod
beratungworkdev
beratungworktest
beratungworkpilot
beratungworkprod
1.4.-beispiel-keycloak-datenbank"><span3. class="nh-number">1.4. </span>Beispiel: Keycloak-Datenbank</h3>
<p><strong>
1.3.1. Administrative Rolle anlegen</strong></p>
<pre><code>
CREATE USER keycloaktest WITH PASSWORD '<<ADMIN_PASSWORT>>';</code></pre>
<p>Nur wenn die Rolle selbst Datenbanken anlegen soll:</p><pre><code>
CREATE USER keycloaktest WITH LOGIN CREATEDB PASSWORD '<<ADMIN_PASSWORT>>';</code></pre>
<p><code>CREATEROLE sollte nur vergeben werden, wenn die Rolle tatsächlich weitere Rollen verwalten muss.</code></p>
<p><strong>
1.3.2. Datenbank anlegen</strong></p>
<pre><code>
CREATE DATABASE keycloakdb;</code></pre>
<p>Optional Eigentümer setzen:</p><pre><code>
ALTER DATABASE keycloakdb OWNER TO keycloaktest;</code></pre>
<p><strong>
1.3.3. Verbindungsrecht vergeben</strong></p>
<pre><code>
GRANT CONNECT ON DATABASE keycloakdb TO keycloaktest;</code></pre>
<p><strong>
1.3.4. Applikationsrolle anlegen</strong></p>
<pre><code>
CREATE USER keycloakworktest WITH PASSWORD '<<APP_PASSWORT>>';
GRANT CONNECT ON DATABASE keycloakdb TO keycloakworktest;</code></pre>
<h3
1.4. id="bkmrk-1.5.-arbeiten-mit-schemas"><span class="nh-number">1.5. </span>Arbeiten mit Schemas</h3>
<p><strong>
1.4.1. Vorhandene Schemas anzeigen</strong></p>
<pre><code>
\dn</code></pre>
<p><strong>
1.4.2. Eigenes Schema anlegen</strong></p>
<pre><code>
CREATE SCHEMA keycloak AUTHORIZATION keycloaktest;</code></pre>
<p>Das Schema gehört damit der administrativen Rolle. Das ist meist sauberer, als das Schema direkt der Applikationsrolle zu überlassen.</p>
<p><strong>
1.4.3. Rechte auf Schema und Tabellen setzen</strong></p>
<pre><code>
GRANT USAGE ON SCHEMA keycloak TO keycloakworktest;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA keycloak TO keycloakworktest;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA keycloak TO keycloakworktest;</code></pre>
<p>Damit neu angelegte Tabellen und Sequenzen ebenfalls passend berechtigt werden:</p><pre><code>
ALTER DEFAULT PRIVILEGES FOR ROLE keycloaktest IN SCHEMA keycloak
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO keycloakworktest;
ALTER DEFAULT PRIVILEGES FOR ROLE keycloaktest IN SCHEMA keycloak
GRANT USAGE, SELECT ON SEQUENCES TO keycloakworktest;</code></pre>
<p><strong>
1.4.4. Wichtiger Hinweis zu GRANT</strong></p>
<p>
Dieser Befehl ist fachlich nicht korrekt:</p><pre><code>
GRANT SELECT, INSERT, UPDATE, DELETE ON keycloakdb TO keycloakworktest;</code></pre>
<p><code>SELECT, </code><code>INSERT, </code><code>UPDATE und </code><code>DELETE gelten für Tabellen oder Views, nicht für die Datenbank selbst.</code></p>
<p>Korrekt ist auf Datenbankebene zum Beispiel:</p><pre><code>
GRANT CONNECT ON DATABASE keycloakdb TO keycloakworktest;</code></pre>
<h3
1.5. id="bkmrk-1.6.-ssl-gesicherte-verbindungen"><span class="nh-number">1.6. </span>SSL-gesicherte Verbindungen</h3>
<p>
Je nach Umgebung werden Verbindungsinformationen und Zertifikate getrennt bereitgestellt.</p>
<pre><code>
database_public_ip = 35.198.170.75
database_ca_certificates = {
shareddb = <<CA-Zertifikat>
>
}
database_private_keys = {
shareddb = <<Client-Private-Key>
>
}
database_public_keys = {
shareddb = <<Client-Zertifikat>
>
}</code></pre>
<p>Für den Client werden typischerweise benötigt:</p><ul><li>
Beispielhafte psql-Verbindung:
<p>Beispielhafte <code>psql</code>-Verbindung:</p><pre><code>
psql -W "port=5432 host=35.198.170.75 user=keycloaktest dbname=keycloakdb sslcert=client.crt sslkey=client.key sslrootcert=root.crt sslmode=verify-ca"</code></pre>
<p>Für produktive Umgebungen ist <code>verify-ca oder </code><code>verify-full in der Regel sinnvoller als </code><code>prefer.</code></p>
<h3
1.6. id="bkmrk-1.7.-import-und-restore"><span class="nh-number">1.7. </span>Import und Restore</h3>
<p>
Die Dump-Files werden je nach Quelle entweder als SQL-Skript, Custom-Format-Archiv, Directory-Format oder TAR-Archiv bereitgestellt.</p>
<p><strong>Wichtige Unterscheidung:</strong></p><ul><li><strong>
psql</code> eingespielt.pg_dump</code></strong> werden mit pg_restore</code> eingespielt.<p><strong>
1.6.1. Dateien vorbereiten</strong></p>
<pre><code>
mkdir /srv/postgresql/data/import_dump/
cp -r ../exx/z_backups/postgresql/rollenerfassung* /srv/postgresql/data/import_dump/</code></pre>
<p><strong>
1.6.2. Berechtigungen setzen</strong></p>
<p>
Falls der PostgreSQL-Container mit UID/GID <code>70:70 arbeitet:</code></p><pre><code>
chown -R 70:70 /srv/postgresql/data/import_dump</code></pre>
<p><strong>
1.6.3. In den Container wechseln</strong></p>
<pre><code>
docker exec -it postgres bash</code></pre>
<p>Beispielpfad im Container:</p><pre><code>
cd /var/lib/postgresql/data/import_dump/rollenerfassung_raspberrypi/</code></pre>
<p><strong>
1.6.4. Restore-SQL prüfen</strong></p>
<pre><code>
sed -e 's/\$\$PATH\$\$/\/tmp\/dvdrental/g' restore.sql | grep --color dvdrental</code></pre>
<p>Zusätzlich kann der Anfang der Datei geprüft werden:</p><pre><code>
head -n 50 restore.sql</code></pre>
<p>So lässt sich feststellen:</p><ul><li>
<h3
1.8.-beispiel-rollenerfassung"><span7. class="nh-number">1.8. </span>Beispiel: Rollenerfassung</h3>
<p><strong>
1.7.1. Rolle anlegen</strong></p>
<pre><code>
CREATE USER rollenerfassung WITH PASSWORD '<<PASSWORT>>';</code></pre>
<p><strong>
1.7.2. Datenbanken anlegen</strong></p>
<p>
Für allgemeine Dokumentation besser ohne starre Locale-Vorgabe arbeiten, da diese plattform- und umgebungsabhängig ist:</p><pre><code>
CREATE DATABASE rollenerfassung_server TEMPLATE template0 ENCODING 'UTF8';
CREATE DATABASE rollenerfassung_raspberrypi TEMPLATE template0 ENCODING 'UTF8';</code></pre>
<p>Wenn in einer konkreten Umgebung eine bestimmte Locale erforderlich ist, sollte sie explizit passend zur Zielplattform dokumentiert werden.</p>
<p><strong>
1.7.3. Eigentümer setzen</strong></p>
<pre><code>
ALTER DATABASE rollenerfassung_raspberrypi OWNER TO rollenerfassung;
ALTER DATABASE rollenerfassung_server OWNER TO rollenerfassung;</code></pre>
<p><strong>
1.7.4. Connect-Rechte vergeben</strong></p>
<pre><code>
GRANT CONNECT ON DATABASE rollenerfassung_server TO rollenerfassung;
GRANT CONNECT ON DATABASE rollenerfassung_raspberrypi TO rollenerfassung;</code></pre>
<h3
1.8. id="bkmrk-1.9.-restore-eines-sql-skripts-mit-psql"><span class="nh-number">1.9. </span>Restore eines SQL-Skripts mit psql</h3>
<p>
Wenn <code>restore.sql ein Plain-SQL-Skript ist, kann der Pfad beim Einspielen ersetzt werden.</code></p>
<pre><code>
sed -e 's/\$\$PATH\$\$/\/var\/lib\/postgresql\/data\/import_dump\/rollenerfassung/g' restore.sql | psql -h localhost -p 5432 -U postgres -d rollenerfassung_server</code></pre>
<p>Dabei wird:</p><ul><li><code>
$$PATH$$</code> durch den echten Pfad ersetztpsql</code> übergeben<h3
1.10.-restore-eines-archivs-mit-pg_restore"><span9. class="nh-number">1.10. </span>Restore eines Archivs mit pg_restore</h3>
<p>
Wenn ein Dump mit <code>pg_dump -Fc oder in einem anderen Archivformat erstellt wurde, wird </code><code>pg_restore verwendet.</code></p>
<pre><code>
docker exec -i postgres pg_restore --clean -U postgres -d rollenerfassung_server << restore.dump</code></pre>
<p><strong>
1.9.1. Erklärung</strong></p>
<ul>
<li><code>
docker exec -i postgres</code> führt den Befehl im Container auspg_restore</code> stellt einen Archiv-Dump wieder her--clean</code> entfernt vorhandene Objekte vor dem Restore-U postgres</code> nutzt die Rolle postgres</code></li>
<li><code>
-d rollenerfassung_server</code> gibt die Zieldatenbank an<h3
1.11.-dump-erstellen"><span10. class="nh-number">1.11. </span>Dump erstellen</h3>
<p>
Ein Dump im Custom-Format kann aus dem Container heraus mit <code>pg_dump erzeugt werden.</code></p>
<pre><code>
docker exec $CONTAINER pg_dump -Fc -U postgres $DATABASE >> $OUTPUT/$DATABASE-$DATE.dump</code></pre>
<p><strong>
1.10.1. Erklärung</strong></p>
<ul>
<li><code>
$CONTAINER</code> ist der Name des PostgreSQL-Containers-Fc</code> erzeugt ein Custom-Format für pg_restore</code></li>
<li><code>
-U postgres</code> verwendet die Rolle postgres</code></li>
<li><code>
$DATABASE</code> ist die zu sichernde Datenbank$OUTPUT/$DATABASE-$DATE.dump</code> ist die Zieldatei<p>Hinweis: Für Custom-Format ist <code>.dump oder </code><code>.backup als Dateiendung verständlicher als </code><code>.psql.</code></p>
<h3
1.11. id="bkmrk-1.12.-einfacher-funktionstest"><span class="nh-number">1.12. </span>Einfacher Funktionstest</h3>
<p>
Nach Einrichtung von Rolle und Rechten kann ein Funktionstest durchgeführt werden.</p>
<p><strong>
1.11.1. Testtabelle anlegen</strong></p>
<pre><code>
CREATE TABLE persons (
personid int PRIMARY KEY,
firstname varchar(50),
lastname varchar(50)
);</code></pre>
<p><strong>
1.11.2. Tabellen anzeigen</strong></p>
<pre><code>
\d</code></pre>
<p><strong>
1.11.3. Datensatz einfügen</strong></p>
<pre><code>
INSERT INTO persons VALUES (1, 'Alex', 'Hofmann');</code></pre>
<p><strong>
1.11.4. Daten prüfen</strong></p>
<pre><code>
SELECT * FROM persons;</code></pre>
<p><strong>
1.11.5. Tabelle wieder löschen</strong></p>
<pre><code>
DROP TABLE persons;</code></pre>
<p><strong>
1.11.6. Sitzung beenden</strong></p>
<pre><code>
\q</code></pre>
<h3
1.12. id="bkmrk-1.13.-empfohlenes-betriebsmodell"><span class="nh-number">1.13. </span>Empfohlenes Betriebsmodell</h3>
<p><strong>
1.12.1. Administrative Rolle</strong></p>
<ul>
<li>
<p><strong>
1.12.2. Applikationsrolle</strong></p>
<ul>
<li>
<p>Dadurch wird vermieden, dass Anwendungen mit überprivilegierten Rollen laufen.</p>
<h3
1.13. id="bkmrk-1.14.-sicherheitshinweise"><spanSicherheitshinweise
CREATEROLE</code> und CREATEDB</code> nur bei echtem Bedarf vergebenverify-ca</code> oder verify-full</code> bevorzugen1.14. Zusammenfassung
<h3 id="bkmrk-1.15.-zusammenfassung"><span class="nh-number">1.15. </span>Zusammenfassung</h3><p>Für PostgreSQL in Docker-Umgebungen empfiehlt sich ein einheitliches Vorgehen:</p><ul><li>
psql</code>-Restore und pg_restore</code></li>
<li>
dokumentierte Pfade und Container-BefehleSo bleibt die Umgebung übersichtlich, wartbar und sicher.</p>