This commit is contained in:
Mathias Schneider
2026-09-28 17:37:46 +02:00
parent 95797e4a3b
commit 50406e22d1
5 changed files with 487 additions and 3 deletions
+55
View File
@@ -99,3 +99,58 @@ ssh benutzername@192.168.178.42
--- ---
👉 Soll ich dir ein **kurzes Beispiel-Setup mit zwei Testbenutzern** schreiben, das du direkt im Heimnetz nachmachen kannst? 👉 Soll ich dir ein **kurzes Beispiel-Setup mit zwei Testbenutzern** schreiben, das du direkt im Heimnetz nachmachen kannst?
---
## 5. SSH-Tunnel für lokale Datenbankzugriffe
Mit einem lokalen SSH-Tunnel (`-L`) wird ein Port auf dem eigenen Rechner an
einen Zielhost und Zielport weitergeleitet, die aus Sicht des SSH-Servers
erreichbar sind:
```bash
ssh -L <lokaler-port>:<zielhost>:<zielport> <benutzer>@<ssh-server>
```
Beispiel für PostgreSQL:
```bash
ssh -L 15432:127.0.0.1:5432 benutzername@vm.example.org
```
Danach kann ein lokaler Client über `127.0.0.1:15432` auf PostgreSQL zugreifen.
Die Verbindung verläuft dabei so:
```text
Datenbank-Client auf dem eigenen Rechner
|
| 127.0.0.1:15432
v
SSH-Tunnel zur VM
|
| 127.0.0.1:5432 aus Sicht der VM
v
PostgreSQL auf der VM
```
`<zielhost>` wird aus Sicht der VM aufgelöst. Wenn PostgreSQL in einem
Docker-Container läuft, kann das je nach Setup beispielsweise `127.0.0.1`,
ein Docker-Service-Name oder eine Container-IP sein. Eine Container-IP wie
`172.19.0.2` sollte nicht dauerhaft vorausgesetzt werden, weil sie sich nach
dem Neuerstellen des Containers ändern kann. Siehe auch
[[DBeaver PostgreSQL via SSH-Tunnel]] und [[Docker]].
### Adressen nicht verwechseln
`hostname -I` gibt alle Adressen des Rechners aus. Darunter können sich auch
Docker-Bridge-Adressen befinden. Die Ausgabe zeigt nicht, welche Adresse für
einen bestimmten Dienst die richtige ist:
```text
10.2.0.4 Adresse der VM im Azure-Netzwerk
172.19.0.1 Docker-Bridge-Gateway
172.19.0.2 möglicherweise eine Container-IP
```
Die tatsächlich passende Adresse und der passende Port sollten mit `ss`,
`docker inspect`, `nc` oder `psql` geprüft werden.
+57
View File
@@ -28,3 +28,60 @@ docker exec -i <container_name> psql -U <username> -d <dbname> -A -F, --csv -c "
``` ```
Erklärung: Erklärung:
>The `-A` flag (unaligned output), `-F,` (field separator comma), and `--csv` together produce CSV >The `-A` flag (unaligned output), `-F,` (field separator comma), and `--csv` together produce CSV
## Verbindung zu einem bestimmten Host und Port
Für eine Verbindung zu einem PostgreSQL-Server auf einem bestimmten Host und
Port werden `-h` und `-p` verwendet:
```bash
psql -h <host> -p <port> -U <username> -d <dbname>
```
Beispiel:
```bash
psql -h 127.0.0.1 -p 15432 -U <username> -d <dbname>
```
Das ist beispielsweise der lokale Endpunkt eines SSH-Tunnels. Bei einem
Docker-Setup kann der Host dagegen eine Container-IP, ein Docker-Service-Name
oder die Loopback-Adresse der VM sein. Entscheidend ist, von wo aus die
Verbindung hergestellt wird.
## PostgreSQL-Verbindung diagnostizieren
Eine schrittweise Prüfung hilft dabei, Netzwerk-, Tunnel- und
Authentifizierungsprobleme voneinander zu unterscheiden:
```bash
# Ist der TCP-Port erreichbar?
nc -vz <host> <port>
# Lauscht auf der VM ein Prozess auf dem PostgreSQL-Port?
sudo ss -ltnp | grep 5432
# Funktioniert die PostgreSQL-Verbindung mit denselben Parametern?
psql -h <host> -p 5432 -U <username> -d <dbname>
```
Wenn `psql` direkt auf der VM funktioniert, ist damit nur bewiesen, dass die
VM diesen Endpunkt erreichen kann. Es ist noch nicht bewiesen, dass ein
externer Client denselben Weg über den SSH-Tunnel verwendet. Zu prüfen sind
deshalb zusätzlich der lokale Tunnel-Port, der entfernte Zielhost, der
entfernte Zielport und die SSL-Einstellung des Clients.
Für eine Docker-Datenbank sind außerdem hilfreich:
```bash
docker ps
docker inspect <postgres-container>
docker logs --tail 100 <postgres-container>
```
Eine Container-IP kann sich ändern, wenn der Container neu erstellt wird. Für
dauerhafte Konfigurationen sind veröffentlichte Host-Ports oder Docker-
Service-Namen meist besser geeignet als eine fest eingetragene Container-IP.
Siehe auch [[SSH Verbindung in Linux]], [[Docker]] und
[[DBeaver PostgreSQL via SSH-Tunnel]].
@@ -0,0 +1,144 @@
# PostgreSQL mit DBeaver über einen SSH-Tunnel
Ein SSH-Tunnel erlaubt den Zugriff auf eine Datenbank, die nur von einer
entfernten VM aus erreichbar ist. Der Tunnel löst dabei nicht automatisch alle
Netzwerkprobleme: Der Zielhost und Zielport werden aus Sicht der VM bewertet.
## Verbindungsweg
```text
DBeaver auf dem eigenen Rechner
|
| lokaler Tunnel-Endpunkt
v
SSH-Client ───────────────► SSH-Server auf der VM
|
| Zielhost:Zielport
v
PostgreSQL auf der VM
oder PostgreSQL-Container
```
Ein möglicher manueller Tunnel sieht so aus:
```bash
ssh -L 15432:127.0.0.1:5432 <user>@<vm-host>
```
Danach ist die Datenbank vom eigenen Rechner aus typischerweise über
`127.0.0.1:15432` erreichbar. Bei DBeaver hängen die genauen Felder von der
verwendeten SSH-Tunnel-Konfiguration ab. Wichtig ist, die lokale
Datenbankadresse nicht mit dem entfernten Ziel der Weiterleitung zu
verwechseln.
## Docker als Datenbank-Host
Wenn PostgreSQL in Docker läuft, gibt es mehrere mögliche Ziele:
| Situation | Typisches Ziel aus Sicht der VM |
| --- | --- |
| PostgreSQL läuft direkt auf der VM | `127.0.0.1:5432` |
| PostgreSQL-Port ist veröffentlicht | `127.0.0.1:<veröffentlichter Port>` |
| Zugriff aus einem anderen Container | Compose-Service-Name, z. B. `postgres:5432` |
| Direkter Zugriff auf einen Container | aktuelle Container-IP, z. B. `172.19.0.2:5432` |
Eine Container-IP sollte nur zum Testen verwendet werden. Sie kann sich nach
dem Neustart oder Neuerstellen des Containers ändern. Für eine dauerhafte
Konfiguration sind ein Compose-Service-Name innerhalb des Docker-Netzwerks
oder ein veröffentlichter Host-Port vorzuziehen.
## Schrittweise Diagnose
### 1. Den aktuellen Container und seine Ports prüfen
Auf der VM:
```bash
docker ps
docker inspect <postgres-container>
sudo ss -ltnp | grep 5432
```
Bei `docker ps` auf die Spalte `PORTS` achten. Eine Ausgabe wie
`127.0.0.1:5432->5432/tcp` bedeutet, dass PostgreSQL auf der VM lokal
veröffentlicht ist. Eine Ausgabe wie `0.0.0.0:15432->5432/tcp` bedeutet, dass
der Host-Port `15432` zum Container-Port `5432` weiterleitet.
### 2. Den Zielendpunkt von der VM aus testen
```bash
nc -vz <zielhost> <zielport>
psql -h <zielhost> -p <zielport> -U <user> -d <database>
```
Diese Tests müssen mit dem Host und Port durchgeführt werden, die der
SSH-Tunnel aus Sicht der VM erreichen soll. Ein funktionierendes `psql` ohne
`-h` kann beispielsweise über einen lokalen Unix-Socket verbinden und sagt
nichts über die TCP-Verbindung aus.
### 3. PostgreSQL-Logs beobachten
```bash
docker logs --tail 100 -f <postgres-container>
```
Dann in DBeaver den Verbindungstest ausführen:
- **Kein neuer Logeintrag:** DBeaver erreicht PostgreSQL nicht. Tunnel,
Zielhost, Zielport oder lokale/entfernte Portzuordnung prüfen.
- **Eintrag mit Authentifizierungsfehler:** Netzwerkweg funktioniert; Benutzer,
Passwort, Datenbank oder `pg_hba.conf` prüfen.
- **Verbindung wird sofort beendet:** SSL-Modus, PostgreSQL-Treiber und
Tunnelziel vergleichen.
## Typische Fehler
### `hostname -I` liefert mehrere Adressen
`hostname -I` zeigt alle Adressen der VM. Dazu können die Azure-Adresse und
mehrere Docker-Bridge-Adressen gehören. Die Ausgabe ist keine Liste von
gleichwertigen Datenbankadressen:
```text
10.2.0.4 VM-Adresse im privaten Azure-Netzwerk
172.19.0.1 Docker-Bridge-Gateway
172.19.0.2 möglicherweise PostgreSQL-Container
```
Mit `docker network inspect <network-name>` lässt sich prüfen, welchem
Container eine Docker-Adresse aktuell zugeordnet ist.
### SSH funktioniert, DBeaver meldet `EOF Exception`
Ein erfolgreicher SSH-Aufbau beweist nur, dass der SSH-Server erreichbar ist.
Der weitergeleitete TCP-Stream kann trotzdem am falschen Ziel oder Port enden.
Prüfen:
1. Welcher lokale Port wird von DBeaver verwendet?
2. Welcher entfernte Host und Port werden durch den Tunnel angesprochen?
3. Ist der PostgreSQL-Container noch unter derselben IP erreichbar?
4. Lauscht PostgreSQL auf TCP und nicht nur auf einem Unix-Socket?
5. Verwendet DBeaver denselben SSL-Modus wie `psql`?
6. Erscheint der Test in den PostgreSQL-Logs?
Die Verbindung sollte zunächst mit einer expliziten TCP-Verbindung geprüft
werden:
```bash
psql -h 127.0.0.1 -p <port> -U <user> -d <database>
```
Dabei muss `<port>` dem tatsächlich veröffentlichten Port oder dem lokalen
Port des SSH-Tunnels entsprechen.
## Sicherheits- und Wartungshinweise
- Keine Passwörter oder produktiven Zugangsdaten in Notizen oder
Verbindungsdefinitionen im Klartext speichern.
- Container-IPs nicht als langfristige Infrastrukturkonfiguration verwenden.
- Für dauerhafte Zugriffe DNS-Namen, Compose-Service-Namen oder stabile
Host-Port-Zuordnungen bevorzugen.
- Für einen Diagnosefall die verwendeten Hosts, Ports, SSL-Einstellungen und
den Verbindungsweg dokumentieren, aber sensible Werte anonymisieren.
Siehe auch [[SSH Verbindung in Linux]], [[psql]] und [[Docker]].
+164
View File
@@ -0,0 +1,164 @@
# Git-History kuerzen
Wenn ein Repository zu gross geworden ist und die alte Historie nicht mehr benoetigt wird, kann die Git-History ab einem bestimmten Commit abgeschnitten werden. Dabei wird die Historie **umgeschrieben**: Der Commit-Hash des neuen Anfangs und die Hashes aller folgenden Commits aendern sich.
> **Achtung:** Das ist eine destruktive Operation fuer die bisherige Historie. Vorher unbedingt ein Backup erstellen und mit allen anderen Personen abstimmen, die mit dem Repository arbeiten.
## Nicht verwechseln: Shallow Clone
Ein flacher Clone verbirgt alte Historie nur lokal:
```bash
git clone --shallow-since="2024-01-01" <REPOSITORY_URL>
```
Das Repository selbst wird dadurch nicht gekuerzt. Fuer eine dauerhafte Kuerzung muss die Historie umgeschrieben und anschliessend mit Force-Push auf das Remote uebertragen werden.
## Vorbereitung: Backup erstellen
Am sichersten arbeitet man mit einem Mirror-Clone:
```bash
git clone --mirror <REPOSITORY_URL> repository-backup.git
cd repository-backup.git
```
Den urspruenglichen Clone bzw. das Backup erst loeschen, wenn das Ergebnis geprueft wurde.
## `git-filter-repo` unter Arch Linux installieren
Das Arch-Paket heisst `git-filter-repo`:
```bash
sudo pacman -S git-filter-repo
```
Pruefen:
```bash
git filter-repo --version
```
Ein systemweites `pip install` funktioniert auf Arch Linux wegen PEP 668 normalerweise nicht. Die Paketinstallation ist vorzuziehen.
## Einen Commit zum neuen Root machen
Angenommen, dieser Commit soll der neue Anfang der Historie werden:
```text
464e39c1234567890abcdef1234567890abcdef
```
Dann werden seine Eltern entfernt:
```bash
git filter-repo --force \
--commit-callback 'if commit.original_id == b"464e39c1234567890abcdef1234567890abcdef": commit.parents = []'
```
`commit.original_id` enthaelt die vollstaendige 40-stellige Commit-ID. Eine kurze ID wie `464e39c` funktioniert mit `==` nicht. Alternativ kann ein eindeutiger Prefix so verwendet werden:
```bash
git filter-repo --force \
--commit-callback 'if commit.original_id.startswith(b"464e39c"): commit.parents = []'
```
Die vollstaendige ID kann vorher ermittelt werden:
```bash
git rev-parse 464e39c
```
Aus:
```text
A -- B -- C -- D -- E
```
wird dadurch sinngemaess:
```text
C' -- D' -- E'
```
Der Commit `C` bleibt inhaltlich und mit seinen Metadaten erhalten, bekommt aber wegen der entfernten Eltern einen neuen Hash. Auch `D` und `E` erhalten neue Hashes.
## Den Cutoff-Commit ebenfalls verwerfen
Wenn der Cutoff-Commit selbst nicht erhalten bleiben soll, kann ein neuer Root-Commit mit seinem Dateistand erstellt und die spaetere Historie darauf rebased werden:
```bash
git checkout --orphan temp <CUTOFF_COMMIT>
git commit -m "Start truncated history"
git rebase --onto temp <CUTOFF_COMMIT> main
git branch -D temp
```
Dabei ist `<CUTOFF_COMMIT>` der **letzte Commit, der verworfen werden soll**. Der neue Root-Commit enthaelt den Dateistand dieses Commits, ist aber ein neuer Commit. Bei Merge-Commits oder komplexen Branches kann die Rebase-Variante Konflikte verursachen. In solchen Faellen ist `git-filter-repo` in der Regel die bessere Wahl.
## Ergebnis pruefen
Vor dem Push die neue Historie kontrollieren:
```bash
git log --all --graph --oneline --decorate
git status
```
Der neue Root-Commit darf keine `parent`-Zeile haben:
```bash
git show --no-patch --pretty=raw <NEUER_ROOT_COMMIT>
```
Auch der aktuelle Dateistand sollte unveraendert sein. Einen Vergleich kann man beispielsweise vor dem Umschreiben speichern oder mit dem Backup pruefen.
## Remote wieder hinzufuegen
`git-filter-repo` entfernt das Remote oft absichtlich als Sicherheitsmassnahme. Deshalb zuerst pruefen:
```bash
git remote -v
```
Falls kein `origin` vorhanden ist:
```bash
git remote add origin <REPOSITORY_URL>
git ls-remote origin
```
`origin/main` ist eine Branch-Referenz und kein Remote-Name. Der Push verwendet daher `origin main`, nicht `origin/main`.
## Umschriebene Historie pushen
Nur den Hauptbranch pushen:
```bash
git push --force origin main
```
Alle lokalen Branches und Tags pushen:
```bash
git push --force --all origin
git push --force --tags origin
```
Das Remote kann den Push wegen Branch-Schutzregeln ablehnen. In diesem Fall muss der Schutz voruebergehend angepasst werden.
## Nacharbeiten und wichtige Folgen
- Alle Commit-Links, Pull Requests und Tags koennen durch die neuen Hashes ungueltig werden.
- Andere Clone enthalten weiterhin die alte Historie und muessen neu geklont oder manuell angepasst werden.
- Andere Branches oder Tags koennen die alte Historie weiterhin erreichbar machen.
- Ein Force-Push kann nicht ohne Weiteres rueckgaengig gemacht werden; das Backup aufbewahren.
Alte, nicht mehr erreichbare Objekte koennen nach der Pruefung lokal bereinigt werden:
```bash
git reflog expire --expire=now --all
git gc --prune=now
```
`git gc --aggressive` ist normalerweise nicht notwendig und kann bei grossen Repositories lange dauern. Auf einem Hosting-Dienst werden nicht mehr erreichbare Objekte eventuell erst spaeter durch dessen eigene Garbage Collection geloescht.
+64
View File
@@ -778,3 +778,67 @@ docker-compose up --build
- ✅ Persistente Datenspeicherung - ✅ Persistente Datenspeicherung
**Das ist die Macht von Docker! 🐳** **Das ist die Macht von Docker! 🐳**
---
## Docker-Netzwerk bei Datenbankproblemen untersuchen
Bei einer Datenbank in einem Docker-Container muss zwischen verschiedenen
Netzwerkperspektiven unterschieden werden:
- **Innerhalb eines Docker-Netzwerks:** Container erreichen sich normalerweise
über den Compose-Service-Namen, zum Beispiel `postgres:5432`.
- **Auf dem Docker-Host:** Ein veröffentlichter Port wie `5432:5432` ist über
den Host erreichbar, häufig über `127.0.0.1:5432`.
- **Von außerhalb des Hosts:** Ein SSH-Tunnel kann einen lokalen Port auf den
Host-Port oder auf einen aus Sicht des Hosts erreichbaren Container-Endpunkt
weiterleiten.
### Docker-Bridge-Adressen
Adressen wie `172.19.0.1` und `172.19.0.2` gehören häufig zu einem Docker-
Bridge-Netzwerk:
- `172.19.0.1` ist typischerweise das Gateway des Netzwerks auf dem Host.
- `172.19.0.2` kann die aktuelle IP eines Containers sein.
Container-IPs sind nicht als dauerhafte Konfiguration geeignet. Nach einem
`docker compose up`, einer Neuerstellung oder einem Deployment kann derselbe
Container eine andere IP erhalten. Innerhalb von Compose-Netzwerken sollte der
Service-Name verwendet werden. Von außerhalb sollte nach Möglichkeit ein
veröffentlichter Host-Port verwendet werden.
### Nützliche Diagnosebefehle
```bash
# Laufende Container und veröffentlichte Ports anzeigen
docker ps
# Netzwerkdetails und aktuelle Container-IP anzeigen
docker inspect <container-name>
# Vorhandene Docker-Netzwerke anzeigen
docker network ls
# Teilnehmer und IPs eines Netzwerks anzeigen
docker network inspect <network-name>
# Prüfen, ob der Host lokal auf dem PostgreSQL-Port lauscht
sudo ss -ltnp | grep 5432
# TCP-Erreichbarkeit eines bestimmten Ziels testen
nc -vz <host> 5432
# PostgreSQL-Logs während eines Verbindungsversuchs beobachten
docker logs --tail 100 -f <postgres-container>
```
Wenn ein Client eine Verbindung mit `EOF` beendet, sollte zuerst geprüft
werden, ob überhaupt ein neuer Eintrag in den PostgreSQL-Logs erscheint. Ohne
Logeintrag liegt das Problem wahrscheinlich vor PostgreSQL, beispielsweise am
Tunnel, am Zielhost oder am Zielport. Ein Logeintrag zeigt, dass PostgreSQL
erreicht wurde; dann kommen unter anderem SSL- oder
Authentifizierungsparameter als Ursache infrage.
Siehe auch [[psql]], [[SSH Verbindung in Linux]] und
[[DBeaver PostgreSQL via SSH-Tunnel]].