Podman - Forgejo Server aufsetzen
-
Vorwort
Ich habe mir mal am Karnevalswochenende vorgenommen, mir ein wenig Podman, als Docker Ersatz, näher zu bringen. Es war fordernd
Mein Plan ist es einen Forgejo Server aufzusetzen. Die Dienste sollen alle als Podman Container laufen. Dafür brauche ich
- Forgejo
- Postgres
- Nginx
Los geht's
Installation Server
Ich nutze eine VM von Hetzner. Darauf läuft ein Debian 13 "Trixie". Also, die nächste Version die kommt.
deb http://deb.debian.org/debian trixie main contrib non-free-firmware # deb-src http://deb.debian.org/debian bookworm main contrib non-free-firmware deb http://deb.debian.org/debian trixie-updates main contrib non-free-firmware # deb-src http://deb.debian.org/debian bookworm-updates main contrib non-free-firmware # deb http://deb.debian.org/debian bookworm-backports main contrib non-free-firmware # deb-src http://deb.debian.org/debian bookworm-backports main contrib non-free-firmware deb http://security.debian.org/debian-security trixie-security main contrib non-free-firmware # deb-src http://security.debian.org/debian-security bookworm-security main contrib non-free-firmware
Warum Trixie? Mein Profi Berater meint, die uralte Podman Version sollte man nicht mehr benutzen, man braucht etwas Frisches
root@forgejo:/etc/apt# podman -v podman version 5.3.2
Security Server
- Firewall wird über Hetzner gemacht. Port 22, 80, 443
- Crowdsec benutze ich um ungebetene Gäste eine Zeit lang auszusperren. (Crowdsec ist eine Alternative zu fail2ban)
Voraussetzungen
Nachinstallierte Pakete.
apt install crowdsec crowdsec-firewall-bouncer git socat catatonit
Ich hoffe, ich habe hier nichts vergessen. Wenn doch kommt ja eine Meldung, dann kann man das einfach nachinstallieren.
Catatonit
@forgejo:~# apt search catatonit catatonit/testing,now 0.2.1-1 amd64 [installed] init process for containers
Wird benötigt für die Anlage von Pods. (Hoffe das ist richtig, wie gesagt, war ein langes Wochenende)
ACME
Wird benötigt für das SSL Zertifikat. @Nico schwört ja immer drauf
git clone --depth 1 https://github.com/acmesh-official/acme.sh.git cd acme.sh/ ./acme.sh --server letsencrypt --standalone --issue -d forgejo.linux-nerds.org ./acme.sh --install-cert -d forgejo.linux-nerds.org --cert-file /root/nginx/letsencrypt/live/forgejo.linux-nerds.org/cert.pem --key-file /root/nginx/letsencrypt/live/forgejo.linux-nerds.org/key.pem --fullchain-file /root/nginx/letsencrypt/live/forgejo.linux-nerds.org/fullchain.pem
git und socat sind für acme nötig.
Crontab zur Aktualisierung des Zertifikates anlegen
Crontab anlegen
crontab -e
Inhalt
# m h dom mon dow command 03 09 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" --reloadcmd "systemctl restart nginx.service" > /dev/null
Test auf der Konsole
root@forgejo:~/acme.sh# ./acme.sh --cron --home "/root/.acme.sh" --reloadcmd "systemctl restart nginx.service" [Fri Feb 28 01:37:11 PM UTC 2025] ===Starting cron=== [Fri Feb 28 01:37:11 PM UTC 2025] Renewing: 'forgejo.linux-nerds.org' [Fri Feb 28 01:37:11 PM UTC 2025] Renewing using Le_API=https://acme-v02.api.letsencrypt.org/directory [Fri Feb 28 01:37:11 PM UTC 2025] Skipping. Next renewal time is: 2025-04-28T07:23:28Z [Fri Feb 28 01:37:11 PM UTC 2025] Add '--force' to force renewal. [Fri Feb 28 01:37:11 PM UTC 2025] Skipped forgejo.linux-nerds.org_ecc [Fri Feb 28 01:37:11 PM UTC 2025] ===End cron===
User
Ich brauche ein paar User auf dem Host.
useradd -m -d /home/pguser pguser useradd -m -d /home/forgejo forgejo
Secrets erstellen
podman secret create POSTGRES_PASSWORD /root/secrets/POSTGRES_PASSWORD.txt
Hier liegt das Postgres Passwort drin. Ich erläutere in einem anderen Artikel was Podamn Secret ist.
1. Einen Pod erstellen
Zuerst erstellen wir einen Pod mit den entsprechenden Port-Mappings.
podman pod create --name forgejo-pod -p 3000:3000 -p 222:22 -p 80:80 -p 443:443
Dieser Befehl legt einen Pod namens forgejo-pod an, der die Ports 3000, 222, 80 und 443 vom Host an den Pod weiterleitet.
Die Ports sind für
- 22 SSH
- 80, 443 Web
- 3000 Forgejo
NGINX dient als Proxy.
Der Systemd Dienst für den Pod
/etc/systemd/system/forgejo-pod.service
GNU nano 8.3 forgejo-pod.service [Unit] Description=Forgejo Pod Requires=network.target After=network-online.target [Service] Type=oneshot RemainAfterExit=yes ExecStartPre=-/usr/bin/podman pod rm -f forgejo-pod ExecStart=/usr/bin/podman pod create --name forgejo-pod -p 3000:3000 -p 222:22 -p 80:80 -p 443:443 ExecStop=/usr/bin/podman pod rm -f forgejo-pod [Install] WantedBy=multi-user.target[Pod] Name=forgejo-pod PublishPort=3000:3000 PublishPort=222:22 PublishPort=80:80 PublishPort=443:443 [Service] TimeoutStartSec=90 [Install] WantedBy=multi-user.target
Danach
systemctl start forgejo-pod.service systemctl enable forgejo-pod.service
Jetzt startet der Pod auch nach einem Server Reboot.
2. Container im Pod starten
Hier starten wir die einzelnen Container, mit der Angabe in welchem POD sie laufen sollen.
Ich nutze die Podman Funktion quatlet, diese ist in Podman integriert. Dazu legt man unter /etc/containers/systemd folgende Files an.
Datenbank (Postgres)
Wir benötigen einen leeren Ordner unter /home/pguser/db-data. An die Benutzerrechte denken.
/etc/containers/systemd/postgres.container
[Unit] Description=Postgres Container im Pod forgejo-pod After=network.target After=forgejo-pod.service Requires=forgejo-pod.service Restart=always [Container] Image=docker.io/library/postgres:17 AutoUpdate=registry Label=PODMAN_SYSTEMD_UNIT=%n User=1000:1000 PodmanArgs=--pod=forgejo-pod --name=postgres --secret=POSTGRES_PASSWORD,type=env,target=POSTGRES_PASSWORD Volume=/home/pguser/db-data:/var/lib/postgresql/data [Install] WantedBy=multi-user.target
Forgejo Server
/etc/containers/systemd/forgejo.container
[Unit] Description=Forgejo Container im Pod forgejo-pod After=network.target After=forgejo-pod.service Requires=forgejo-pod.service Restart=always [Container] Image=codeberg.org/forgejo/forgejo:10.0.1 AutoUpdate=registry Label=PODMAN_SYSTEMD_UNIT=%n PodmanArgs=--pod=forgejo-pod --name=forgejo Environment=USER_UID=1001 Environment=USER_GID=1001 Volume=/home/forgejo:/data Volume=/etc/timezone:/etc/timezone:ro Volume=/etc/localtime:/etc/localtime:ro [Install] WantedBy=multi-user.target
Hier wird der Forgejo-Server-Container in den Pod integriert. Bei der Instalaltion von Forgejo muss man folgende Daten eingeben.
- Datenbank Adresse: postgres:5432
- DB User: postgres
- DB Name: postgres
- Beide URL mit https://
Nginx
Für NGINX brauchen wir folgende Files
/etc/nginx/default.conf
server { listen 80; server_name forgejo.linux-nerds.org; return 301 https://$server_name$request_uri; } server { listen 443 ssl; listen [::]:443 ssl; http2 on; server_name forgejo.linux-nerds.org; # Use Mozilla's guidelines for SSL/TLS settings # https://mozilla.github.io/server-side-tls/ssl-config-generator/ ssl_certificate /etc/nginx/letsencrypt/live/forgejo.linux-nerds.org/fullchain.pem; ssl_certificate_key /etc/nginx/letsencrypt/live/forgejo.linux-nerds.org/key.pem; ssl_dhparam /etc/nginx/letsencrypt/live/forgejo.linux-nerds.org/dhparam.pem; # enables TLSv1.2 & TLSv1.3 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; # Prevent nginx HTTP Server Detection server_tokens off; # HSTS settings # WARNING: Only add the preload option once you read about # the consequences in https://hstspreload.org/. This option # will add the domain to a hardcoded list that is shipped # in all major browsers and getting removed from this list # could take several months. # add_header Strict-Transport-Security "max-age=15552000; includeSubDomains;" always; # set max upload size and increase upload timeout: client_max_body_size 512M; client_body_timeout 300s; fastcgi_buffers 64 4K; # The settings allows you to optimize the HTTP2 bandwitdth. # See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/ # for tunning hints client_body_buffer_size 512k; # Remove X-Powered-By, which is an information leak fastcgi_hide_header X-Powered-By; location / { proxy_pass http://138.199.209.222:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
und einen Ordner
/etc/nginx/letsencrypt/live/forgejo.linux-nerds.org/
Darin liegen die Zertifikate
root@forgejo:# ls -lha /etc/nginx/letsencrypt/live/forgejo.linux-nerds.org/ total 24K drwxr-xr-x 2 999 996 4.0K Mar 2 18:36 . drwxr-xr-x 3 999 996 4.0K Feb 28 07:49 .. -rw-r--r-- 1 999 996 1.3K Feb 28 07:49 cert.pem -rw-r--r-- 1 999 996 428 Mar 2 18:30 dhparam.pem -rw-r--r-- 1 999 996 2.8K Feb 28 07:49 fullchain.pem -rw------- 1 999 996 227 Feb 28 07:49 key.pem
/etc/containers/systemd/nginx.container
[Unit] Description=NGINX Container im Pod forgejo-pod After=network.target After=forgejo-pod.service Requires=forgejo-pod.service Restart=always [Container] Image=docker.io/library/nginx:latest AutoUpdate=registry Label=PODMAN_SYSTEMD_UNIT=%n PodmanArgs=--pod=forgejo-pod --name=nginx Volume=/etc/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro Volume=/etc/nginx/letsencrypt/live/forgejo.linux-nerds.org/:/etc/nginx/letsencrypt/live/forgejo.linux-nerds.org:ro [Install] WantedBy=multi-user.target
Auch der Nginx-Container wird im selben Pod gestartet. Dadurch nutzen alle Container denselben Netzwerk-Namespace, was u. a. bedeutet, dass sie sich über ihre Containernamen (z. B. postgres) erreichen können. Wichtig bei der Installation von Forgejo, dort gibt man dann postgres:5432 an.
Nachdem alle Files erstellt wurden, lädt man mal den Daemon neu
systemctl daemon-reload
Jetzt sollten die Dienste angelegt worden sein.
- postgres.service
- forgejo.service
- nginx.service
Das kann man mit
systemctl status nginx.service
kontrollieren. Auch eine gute Hilfe, wenn was nicht startet.
3. Überprüfen des Pods und der Container
Mit den folgenden Befehlen kannst Du sicherstellen, dass der Pod und alle Container korrekt laufen:
podman pod ps podman ps
podman pod ps listet alle Pods und deren Port-Zuordnungen, während podman ps die laufenden Container anzeigt.
4. Systemd Unit-Datei generieren (Deprecated)
Podman bietet die Möglichkeit, systemd Service-Dateien automatisch zu generieren. Für Deinen Pod erstellst Du beispielsweise eine Unit-Datei mit:
podman generate systemd --name forgejo-pod --files --new
Dieser Befehl generiert vier Dateien.
root@debian-4gb-nbg1-2-forgejo:~# podman generate systemd --name forgejo-pod --files --new DEPRECATED command: It is recommended to use Quadlets for running containers and pods under systemd. Please refer to podman-systemd.unit(5) for details. /root/container-forgejo.service /root/container-nginx-proxy.service /root/pod-forgejo-pod.service /root/container-postgres.service
5. Systemd Unit-Datei aktivieren und starten (Deprecated)
Kopiere die generierten Systemd-Dateien in das systemweite systemd-Verzeichnis, aktiviere sie und starte den Service:
cp *.service /etc/systemd/system/ systemctl daemon-reload systemctl enable container-forgejo-pod.service systemctl enable container-nginx-proxy.service systemctl enable pod-forgejo-pod.service systemctl enable container-postgres.service systemctl start container-forgejo-pod.service
Nun wird Dein Pod zusammen mit allen enthaltenen Containern über systemd verwaltet und startet beim Systemstart automatisch.
6. Rechte
Ein Thema was ich nicht wirklich verstehe, aber man kann ja dran arbeiten. Schauen wir uns mal die einzelnen Container an.
nginx-proxy
root@forgejo:/home/pguser# podman top nginx USER PID PPID %CPU ELAPSED TTY TIME COMMAND root 1 0 0.000 11h22m59.211971839s ? 0s nginx: master process nginx -g daemon off; nginx 16 1 0.000 11h22m59.212103517s ? 0s nginx: worker process nginx 17 1 0.000 11h22m59.21219268s ? 0s nginx: worker process
NGINX läuft als root, die Worker als User nginx.
postgres
root@forgejo:/home/pguser# podman top postgres USER PID PPID %CPU ELAPSED TTY TIME COMMAND pguser 1 0 0.005 11h23m46.923566147s ? 2s postgres pguser 9 1 0.000 11h23m46.923736112s ? 0s postgres: checkpointer pguser 10 1 0.000 11h23m46.923826476s ? 0s postgres: background writer pguser 12 1 0.000 11h23m45.923891884s ? 0s postgres: walwriter pguser 13 1 0.000 11h23m45.923977432s ? 0s postgres: autovacuum launcher pguser 14 1 0.000 11h23m45.92404386s ? 0s postgres: logical replication launcher pguser 350 1 0.003 8h53m41.924108998s ? 1s postgres: postgres postgres 127.0.0.1(51406) idle pguser 1372 1 0.000 53m41.924171702s ? 0s postgres: postgres postgres 127.0.0.1(53832) idle
Postgres läuft wie eingestellt, mit dem User pguser.
forgejo
root@forgejo:/home/pguser# podman top forgejo USER PID PPID %CPU ELAPSED TTY TIME COMMAND root 1 0 0.000 11h24m30.390732597s ? 0s /bin/s6-svscan /etc/s6 root 11 1 0.000 11h24m30.390842417s ? 0s s6-supervise openssh root 12 1 0.000 11h24m30.390906629s ? 0s s6-supervise gitea git 13 12 0.285 11h24m30.390967669s ? 1m57s /usr/local/bin/gitea web root 14 11 0.000 11h24m30.391030954s ? 0s sshd: /usr/sbin/sshd -D -e [listener] 0 of 10-100 startups
Forgejo läuft als root, aber die Dienste, die nach außen kommunizieren, werden als forgejo gestartet. Kann man sich mit htop ansehen.
Backups
Für Backups braucht ihr nur diese beiden Ordner sichern.
- /home/pguser/db-data/
- /home/forgero
Anmerkungen
Wer hier Fehler oder Verbesserungsvorschläge hat, schreibt es gerne hier unten drunter. Ich freue mich über jeden Tipp.
Teile dieser Doku sind mit Text von ChatGPT erstellt worden. Dürfte aber mittlerweile nicht mehr viel von über sein, aber wegen der Transparenz sei dies hier erwähnt.
-
F FrankM hat dieses Thema angepinnt
-
Bei der Installation wird die Registrierung ausgeschaltet, es sei denn ihr habt das bei der Installation geändert. Ok, was machen, wenn man das ändern möchte?
Zwei Möglichkeiten.
Volume
Wir legen die ganze app.ini in ein Volume.
Volume=/home/forgejo/conf/app.ini:/data/gitea/conf/app.ini
In /home/forgejo/conf/app.ini erstellt man das File. Den Inhalt holt man sich vorher aus dem Container.
podman exec -it forgejo bash vi data/gitea/conf/app.ini
Environment
Wir steuern den gewünschten Wert über eine Environment Variable.
Environment=FORGEJO__SERVICE__DISABLE_REGISTRATION=false
Danach
systemctl daemon-reload systemctl restart forgejo.service
und die Registrierung ist eingeschaltet.
Was ich festgestellt habe ist, das ich keinen Mailer aktiv habe. Der Test-Account war ohne E-Mail-Verifizierung aktiv. Das schaue ich mir dann auch noch mal an.
-
F FrankM hat auf dieses Thema verwiesen
-
-
-
-
-
-
Wichtige Links
Angeheftet Ansible -
-