No description
Find a file
Frank 553ee31082 Skip migration tasks in check mode (require user to exist)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 19:27:15 +01:00
.ansible yes2 true 2026-03-15 19:05:20 +01:00
group_vars Migrate Podman to rootless with dedicated podman user 2026-03-15 19:24:18 +01:00
inventory Fix samba boolean values and complete APU inventory settings 2026-03-15 17:27:33 +01:00
roles Skip migration tasks in check mode (require user to exist) 2026-03-15 19:27:15 +01:00
vault Persist Forgejo INTERNAL_TOKEN in Vault 2026-03-15 16:42:21 +01:00
.gitignore Initial infrastructure setup: Traefik + Forgejo + Podman on Hetzner 2026-03-15 15:34:00 +01:00
README.md Initial infrastructure setup: Traefik + Forgejo + Podman on Hetzner 2026-03-15 15:34:00 +01:00
site.yml yes2 true 2026-03-15 19:05:20 +01:00

infra-ansible — Hetzner Server Infrastructure

Ansible Playbooks für den Hetzner-Server zentral (195.201.29.96). Betrieb mit Podman (rootful) und Traefik als Reverse Proxy.


Architektur

graph TD
    Internet((Internet))

    subgraph Hetzner ["🖥️ Hetzner Server zentral — 195.201.29.96"]
        UFW[UFW Firewall\nPort 80, 443, 2222, 22022]

        subgraph PodmanNet ["Podman Network: proxy-net 10.89.0.0/24"]
            Traefik["🔀 Traefik v3.3\nHTTP→HTTPS Redirect\nLet's Encrypt ACME\nDocker Provider via podman.sock"]
            Forgejo["🐙 Forgejo 10\nPort 3000 intern\nSSH Port 22 intern\nUID 1000 git"]
            Postgres["🐘 PostgreSQL 16\nPort 5432 intern"]
        end

        SSHD["sshd\nPort 22022\nCurve25519"]
    end

    subgraph HomeServer ["🏠 Home Server (geplant)"]
        Immich["📷 Immich\nnoch nicht deployed"]
    end

    Internet -->|":80 HTTP"| UFW
    Internet -->|":443 HTTPS"| UFW
    Internet -->|":2222 Git SSH"| UFW
    Internet -->|":22022 Admin SSH"| UFW
    UFW --> Traefik
    UFW --> SSHD
    Traefik -->|"git.freemind.de\nX-Forwarded-Proto: https"| Forgejo
    Traefik -.->|"immich.freemind.de\ngeplant"| HomeServer
    Forgejo -->|"postgres-forgejo:5432"| Postgres

Netzwerk & Ports

flowchart LR
    Browser["🌐 Browser"]
    GitClient["💻 Git Client"]
    Admin["🔑 Admin"]

    Browser -->|"HTTP :80"| Traefik
    Browser -->|"HTTPS :443"| Traefik
    GitClient -->|"SSH :2222"| Traefik
    Admin -->|"SSH :22022"| SSHD["sshd Host"]

    Traefik -->|"HTTP :3000"| Forgejo["Forgejo\n10.89.0.x"]
    Traefik -->|"TCP :22"| Forgejo
    Forgejo -->|"TCP :5432"| Postgres["PostgreSQL\n10.89.0.x"]

Repo-Struktur

infra-ansible/
├── inventory/
│   └── localhost.yml              # Ansible Inventory (localhost)
├── group_vars/
│   └── all.yml                    # Globale Variablen (Images, Ports, Pfade)
├── vault/
│   └── secrets.yml                # Ansible Vault (verschlüsselt)
├── roles/
│   ├── common/                    # System-Grundkonfiguration
│   │   ├── tasks/main.yml         # Packages, UFW, Podman, aardvark-dns
│   │   └── handlers/main.yml
│   ├── traefik/                   # Traefik Reverse Proxy
│   │   ├── tasks/main.yml
│   │   ├── handlers/main.yml
│   │   └── templates/
│   │       ├── traefik.yml.j2     # Traefik Hauptkonfig
│   │       └── traefik.service.j2 # systemd Service
│   └── forgejo/                   # Forgejo Git Server
│       ├── tasks/main.yml
│       ├── handlers/main.yml
│       └── templates/
│           ├── app.ini.j2         # Forgejo Konfiguration
│           ├── forgejo.service.j2 # systemd Service
│           └── postgres.service.j2
├── site.yml                       # Master Playbook
├── .vault_pass                    # Vault-Passwort (nicht im Repo!)
└── .gitignore

Deployment

Voraussetzungen

apt install ansible podman aardvark-dns ufw

Erstes Deployment

# 1. Domain in group_vars anpassen
nano group_vars/all.yml

# 2. Secrets anlegen
ansible-vault create vault/secrets.yml --vault-password-file .vault_pass
# Inhalt: vault_acme_email, vault_db_password, vault_forgejo_secret_key, vault_domain

# 3. DNS A-Record setzen (beim Provider)
# git.freemind.de → 195.201.29.96

# 4. Playbook ausführen
ansible-playbook -i inventory/localhost.yml site.yml --vault-password-file .vault_pass

Updates & Wiederholung

ansible-playbook -i inventory/localhost.yml site.yml --vault-password-file .vault_pass

Das Playbook ist idempotent — mehrfach ausführen ist sicher.


Variablen (group_vars/all.yml)

Variable Wert Beschreibung
domain git.freemind.de Hauptdomain Forgejo
traefik_image docker.io/traefik:v3.3 Traefik Image — kein latest!
forgejo_image codeberg.org/forgejo/forgejo:10 Forgejo Image — kein latest!
postgres_image docker.io/postgres:16-alpine PostgreSQL Image
podman_network proxy-net Podman Bridge Network
traefik_data_dir /opt/traefik Traefik Daten (acme.json)
forgejo_data_dir /opt/forgejo Forgejo Repos & Daten
postgres_data_dir /opt/forgejo/db PostgreSQL Daten
ssh_port 2222 Forgejo Git SSH Port
web_port 80 HTTP Port
web_secure_port 443 HTTPS Port

Vault Secrets (vault/secrets.yml)

Variable Beschreibung
vault_acme_email E-Mail für Let's Encrypt
vault_db_password PostgreSQL Passwort für Forgejo
vault_forgejo_secret_key Forgejo interner Secret Key
vault_domain Domain (muss mit domain übereinstimmen)

Secrets generieren:

python3 -c "import secrets; print(secrets.token_hex(32))"

Container-Management

# Status
systemctl status traefik forgejo postgres-forgejo

# Logs
journalctl -u forgejo -f
journalctl -u traefik -f

# Alle Container
podman ps

# Restart
systemctl restart forgejo

# Update (Image-Version in group_vars anpassen, dann):
ansible-playbook -i inventory/localhost.yml site.yml --vault-password-file .vault_pass

SSH Zugang

# Admin-Zugang zum Server
ssh root@195.201.29.96 -p 22022

# Git via SSH (nach SSH-Key in Forgejo hinterlegen)
git clone ssh://git@git.freemind.de:2222/USERNAME/repo.git

# ~/.ssh/config empfehlenswert:
# Host git.freemind.de
#   Port 2222
#   User git
#   IdentityFile ~/.ssh/forgejo_ed25519

Bekannte Fixes & Gotchas

timeline
    title Deployment-Probleme und Lösungen
    section DNS
        aardvark-dns fehlte      : Container konnten sich nicht gegenseitig auflösen
        UFW blockierte Port 53   : ufw allow in on podman1 nötig
    section Netzwerk
        UFW FORWARD DROP         : Container hatten kein Internet
                                 : DEFAULT_FORWARD_POLICY=ACCEPT in /etc/default/ufw
    section Traefik
        Falscher Socket-Pfad     : unix varrun podman.sock statt docker.sock
                                 : Mount als /var/run/docker.sock im Container
        X-Forwarded-Proto fehlt  : Forgejo dachte es läuft auf HTTP
                                 : Middleware Label + USE_PROXY_HEADERS=true
    section Forgejo
        Volume-Pfad falsch       : /etc/gitea/conf statt /data/gitea/conf
        Permissions              : Verzeichnisse brauchen owner 1000 git-user
        Theme 404                : forgejo-auto statt auto in Forgejo v10
        DB User-Theme            : UPDATE user SET theme=forgejo-auto in PostgreSQL

Geplante Erweiterungen

  • Immich auf Home Server deployen
  • Traefik Ingress für Immich via Reverse Proxy einrichten
  • Auf Podman rootless migrieren
  • Backup-Strategie für Forgejo Repos + PostgreSQL
  • SSH-Keys für Workstation und Laptop in Forgejo hinterlegen
  • Dieses Repo in Forgejo selbst pushen 🐙

Lizenz

MIT