Eine Neuigkeit des Releases ist folgendes
- Save As
- Export As
Save As ermöglicht das erneute speichern unter einem neuen Namen.
Export As ermöglicht das Speichern als .pdf und .epub
Eine Neuigkeit des Releases ist folgendes
Save As ermöglicht das erneute speichern unter einem neuen Namen.
Export As ermöglicht das Speichern als .pdf und .epub
OpenCloud v3.1.0 released
This is the main repository of the OpenCloud server. It contains the golang codebase for the backend services. - Release 3.1.0 · opencloud-eu/opencloud
GitHub (github.com)
Releasenotes OpenCloud 3.1.0
Collabora: New “Export As” and “Save As” Options
Working in Collabora just got more powerful:
📝 Save As You can now save a copy of the current file directly from within Collabora. 📤 Export As Export your currently edited document into another format (e.g. PDF) — no extra tools needed.
These improvements let you convert and copy documents without ever leaving the editor.
️ Simplified "Open" Context Menu for Files
The file context menu has been redesigned for a cleaner and more intuitive experience. A single "Open" entry replaces multiple "Open with..." options. This feature is fully accessible with keyboards.
Extended File Format Support in Text Editor
The text editor now supports a wider range of text-based file formats:
Markup & Web: .html, .css, .scss, .sass, .less Scripts & Code: .c, .cpp, .java, .sh, .bat, .asm, .ts, .tsx, .jsx, .vue Config & Environment: .yml, .yaml, .toml, .ini, .conf, .env Structured Data: .csv, .tsv, .xml Other Text Formats: .log, .rtf, .ics, .dockerfile, .makefile
Für das Updaten, hier mal reinlesen.
Release v11.0.3
forgejo - Beyond coding. We forge.
Codeberg.org (codeberg.org)
Ein Traum, wie einfach man das aktualisieren kann.
root@forgejo:~# nano /etc/containers/systemd/forgejo.container
In der Datei die Version anpassen
[Container]
Image=codeberg.org/forgejo/forgejo:11.0.3
AutoUpdate=registry
Label=PODMAN_SYSTEMD_UNIT=%n
PodmanArgs=--pod=forgejo-pod --name=forgejo
Dann ein paar systemd Befehle
systemctl daemon-reload
systemctl restart forgejo.service
Kurze Kontrolle
systemctl status forgejo.service
Dann sieht man diese Zeile in der Ausgabe
Jul 10 14:24:55 debian-4gb-nbg1-2-forgejo forgejo[791814]: 2025/07/10 14:24:55 cmd/web.go:112:showWebStartupMessage() [I] Forgejo version: 11.0.3+gitea-1.22.0 built with GNU Make 4.4.1, go1.24.5 : bindata, timetzdata, sqlite, sqlite_unlock_notify
Oder in der Webzeile im Browser
Gestern morgen bekam ich eine Mail, das mein Forgejo Dienst down ist. Häh, warum? Ich hatte überhaupt nichts verändert. Ich hatte einige Mühe damit, zu verstehen was passiert ist. Das hatte ich dann gesehen.
dependency failed for postgres.service - Postgres Container im Pod forgejo-pod.
Jul 05 11:09:53 debian-4gb-nbg1-2-forgejo systemd[1]: postgres.service: Job postgres.service/start failed with result 'dependency'.
Jul 05 11:09:53 debian-4gb-nbg1-2-forgejo systemd[1]: Dependency failed for postgres.service - Postgres Container im Pod forgejo-pod.
Jul 05 11:09:53 debian-4gb-nbg1-2-forgejo systemd[1]: postgres.service: Job postgres.service/start failed with result 'dependency'.
Ich hatte immer noch keine Ahnung warum? Pod lief nicht und kein Container. Also alles mal mit der KI abklopfen.
Mit diesem Befehl
journalctl -u forgejo-pod-pod.service --no-pager -n 50
bekam ich diese Ausgabe.
Jul 05 11:38:35 debian-4gb-nbg1-2-forgejo forgejo-pod-pod[852]: Error: building local pause image: finding pause binary: exec: "catatonit": executable file not found in $PATH
Jul 05 11:38:35 debian-4gb-nbg1-2-forgejo systemd[1]: forgejo-pod-pod.service: Control process exited, code=exited, status=125/n/a
Jul 05 11:38:35 debian-4gb-nbg1-2-forgejo forgejo-pod-pod[954]: Error: reading pod ID file: open /run/forgejo-pod-pod.pod-id: no such file or directory
Jul 05 11:38:35 debian-4gb-nbg1-2-forgejo systemd[1]: forgejo-pod-pod.service: Control process exited, code=exited, status=125/n/a
Jul 05 11:38:35 debian-4gb-nbg1-2-forgejo systemd[1]: forgejo-pod-pod.service: Failed with result 'exit-code'.
Jul 05 11:38:35 debian-4gb-nbg1-2-forgejo systemd[1]: Failed to start forgejo-pod-pod.service - Forgejo Pod.
Jul 05 11:38:35 debian-4gb-nbg1-2-forgejo systemd[1]: forgejo-pod-pod.service: Scheduled restart job, restart counter is at 1.
Jul 05 11:38:35 debian-4gb-nbg1-2-forgejo systemd[1]: Starting forgejo-pod-pod.service - Forgejo Pod...
Jul 05 11:38:35 debian-4gb-nbg1-2-forgejo forgejo-pod-pod[980]: Error: building local pause image: finding pause binary: exec: "catatonit": executable file not found in $PATH
Nun hatten wir den Übeltäter. Das Paket catatonit war nicht installiert!?
Also schnell ein
apt install catatonit
und alles lief wieder. Doch warum? Die KI befragt
Das Problem wurde ursprünglich als Debian Bug #971815 dokumentiert, wo catatonit nur als "schwache Abhängigkeit" (Recommends) und nicht als harte Abhängigkeit in Podman definiert war #971815 - podman: --init is broken: /usr/libexec/podman/catatonit not found - Debian Bug report logs
Ok, das habe ich dann mal ein wenig recherchiert. Das Paket catatonit ist in Debian 12 & 13 nur ein recommended Package. Irgendwas muss bei einem Debian Update kaputt gegangen sein. Moment, welches Update? Ich hatte ja nichts gemacht. Mir ist aber schon längere Zeit aufgefallen, das ich im pstree den Dienst unattended-upgr am Laufen habe.
Seit einiger Zeit, macht das Hetzner bei einer neuen Debian VM mit rein. Alle meine alten VMs kennen den Dienst nicht, nur die zuletzt neu angelegten. Ok, weiter.
Es stellte sich heraus, das auf meinem System jetzt mit dieser Podman Version läuft.
Version: 5.4.2+ds1-1+b4
Und die braucht zwingend catatonit.
Meine Lösung letztendlich war, auf allen neuen Debian VMs, die ich installiert hatte, das
unattended-upgrade
zu deinstallieren. Das schont meine Nerven. Ich hatte eben auch nochmal nachgeschaut, wann das Tool die Upgrades macht. Eingestellt ist 06:00 Serverzeit, entspricht 08:00 meiner Zeit. Dann gibt es noch ein zufällige Verzögerung von bis zu 60 Minuten.
### Editing /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf
### Anything between here and the comment below will become the contents of the drop-in file
### Edits below this comment will be discarded
### /usr/lib/systemd/system/apt-daily-upgrade.timer
# [Unit]
# Description=Daily apt upgrade and clean activities
# After=apt-daily.timer
#
# [Timer]
# OnCalendar=*-*-* 6:00
# RandomizedDelaySec=60m
# Persistent=true
#
# [Install]
# WantedBy=timers.target
Die Downtime Mail hat mich um 09:08 erreicht. Passt also. Wieder was gelernt. Und im Ansible Script unbedingt die Deinstallation von unattended-upgrade aufnehmen.
Release v11.0.2
forgejo - Beyond coding. We forge.
Codeberg.org (codeberg.org)
Ein Traum, wie einfach man das aktualisieren kann.
root@forgejo:~# nano /etc/containers/systemd/forgejo.container
In der Datei die Version anpassen
[Container]
Image=codeberg.org/forgejo/forgejo:11.0.2
AutoUpdate=registry
Label=PODMAN_SYSTEMD_UNIT=%n
PodmanArgs=--pod=forgejo-pod --name=forgejo
Dann ein paar systemd Befehle
systemctl daemon-reload
systemctl restart forgejo.service
Kurze Kontrolle
systemctl status forgejo.service
Dann sieht man diese Zeile in der Ausgabe
Jun 18 17:52:45 forgejo forgejo[3035]: 2025/06/18 17:52:45 cmd/web.go:112:showWebStartupMessage() [I] Forgejo version: 11.0.2+gitea-1.22.0 built with GNU Make 4.4>
Oder in der Webzeile im Browser
Dann mal flott aktualisieren. Update verlief ohne Probleme.
We have released NodeBB versions v2.8.19, v3.12.6, and v4.4.3 to address a security issue involving a potential XSS vector.
Github
Node.js based forum software built for the modern web - Release v4.4.3 · NodeBB/NodeBB
GitHub (github.com)
Forum
We have released NodeBB versions v2.8.19, v3.12.6, and v4.4.3 to address a security issue involving a potential XSS vector. v4.4.3 Release Notes v3.12.6 ...
NodeBB Community (community.nodebb.org)
Schauen wir uns mal an, wie man die Container aktuell hält.
In der postgres.container steht das hier (als Beispiel)
[Container]
Image=docker.io/library/postgres:17
AutoUpdate=registry
Das AutoUpdate=registry ist die Voraussetzung, dass der Container aktualisiert werden darf.
Mit diesem Befehl kann man sich anschauen, wie der Stand der DInge ist.
root@debian-4gb-nbg1-2-forgejo:~# podman auto-update --dry-run
UNIT CONTAINER IMAGE POLICY UPDATED
forgejo-pod.service 6486189fb10c (postgres) docker.io/library/postgres:17 registry false
forgejo-pod.service 7d5627e2d434 (forgejo) codeberg.org/forgejo/forgejo:11.0.1 registry false
forgejo-pod.service 7fb26d4f8b58 (nginx) docker.io/library/nginx:latest registry false
Podman hat aber standardmäßig einen systemd Dienst, der sich darum kümmert
root@forgejo:/etc/containers/systemd# systemctl status podman-auto-update.service
○ podman-auto-update.service - Podman auto-update service
Loaded: loaded (/usr/lib/systemd/system/podman-auto-update.service; enabled; preset: enabled)
Active: inactive (dead) since Mon 2025-06-09 00:02:57 UTC; 12h ago
Invocation: a098f0054b254a0888ee789200ac9507
TriggeredBy: ● podman-auto-update.timer
Docs: man:podman-auto-update(1)
Process: 68939 ExecStart=/usr/bin/podman auto-update (code=exited, status=0/SUCCESS)
Process: 68947 ExecStartPost=/usr/bin/podman image prune -f (code=exited, status=0/SUCCESS)
Main PID: 68939 (code=exited, status=0/SUCCESS)
Mem peak: 14.4M
CPU: 292ms
Jun 09 00:02:55 forgejo systemd[1]: Starting podman-auto-update.service - Podman auto-update service...
Jun 09 00:02:55 forgejo podman[68939]: 2025-06-09 00:02:55.368941 +0000 UTC m=+0.059687227 system auto-update
Jun 09 00:02:57 forgejo podman[68939]: UNIT CONTAINER IMAGE POLICY UPDATED
Jun 09 00:02:57 forgejo podman[68939]: forgejo-pod.service 6486189fb10c (postgres) docker.io/library/postgres:17 registry false
Jun 09 00:02:57 forgejo podman[68939]: forgejo-pod.service 7d5627e2d434 (forgejo) codeberg.org/forgejo/forgejo:11.0.1 registry false
Jun 09 00:02:57 forgejo podman[68939]: forgejo-pod.service f2e9eee72017 (nginx) docker.io/library/nginx:latest registry false
Jun 09 00:02:57 forgejo systemd[1]: podman-auto-update.service: Deactivated successfully.
Jun 09 00:02:57 forgejo systemd[1]: Finished podman-auto-update.service - Podman auto-update service.
Ok, die Container sollten automatisch aktualisiert werden.
docker.io/library/postgres:17
Die Postgres DB ist auf die Version 17 festgezurrt. Aktuell ist
root@forgejo:/etc/containers/systemd# podman exec postgres postgres --version
postgres (PostgreSQL) 17.5 (Debian 17.5-1.pgdg120+1)
Eine Version 17.6 wird jetzt automatisch installiert, eine Version 18 aber nicht.
docker.io/library/nginx:latest
NGINX zieht sich also immer die letzte "latest" Version, die zur Verfügung gestellt wird.
root@forgejo:/etc/containers/systemd# podman exec nginx nginx -v
nginx version: nginx/1.27.5
Gerade mal gecheckt, 1.27.5 ist die letzte Mainline Version. Also sind wir aktuell.
Der Eintrag
codeberg.org/forgejo/forgejo:11.0.1
aktuelle Version, die installiert ist.
root@forgejo:/etc/containers/systemd# podman exec forgejo forgejo -v
Forgejo version 11.0.1+gitea-1.22.0 (release name 11.0.1) built with GNU Make 4.4.1, go1.24.2 : bindata, timetzdata, sqlite, sqlite_unlock_notify
Ok, wir sind auf Version 11.0.1 Wenn jetzt die Version 11.0.2 herauskommt, wird diese nicht installiert, da wir im forgejo.container folgendes stehen haben.
[Container]
Image=codeberg.org/forgejo/forgejo:11.0.1
Das ist aber erst mal nicht so schlimm, ich lese da mit und bekomme das mit. Das mache ich auch lieber von Hand, dann kann ich besser sehen wo es klemmt
Ich habe ja hier berichtet, wie man einen Forgejo Server aufsetzen kann.
Meinen ersten Versuch findet man hier. Mittlerweile habe ich das Setup verfeinert und bin zufrieden. Das wollte ich hier teilen. Der Plan ist es einen Forgej...
linux-nerds.org (linux-nerds.org)
Da ich da sehr lange dran rum gewerkelt habe, habe ich am Anfang mal die Firewall in der Hetzner Cloud Software aktiviert mit den Standard Ports, die man so braucht.
Eine Kontrolle mit nmap ergibt dann auch nur folgende Ports.
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
Ich hatte am Anfang ziemlich viele Probleme mit meinen Podman Containern, bis ich gelernt hatte, das mit nftables sich vieles von alleine erledigt. Warum? Es gibt auf einer Debian Trixie Installation folgendes Paket.
root@forgejo:/etc/containers/systemd# apt search netavark
aardvark-dns/testing 1.14.0-3 amd64
Container-focused DNS server
netavark/testing,now 1.14.0-2 amd64 [installed,automatic]
Rust based network stack for containers
podman/testing,now 5.4.2+ds1-1+b3 amd64 [installed]
tool to manage containers and pods
podman-docker/testing 5.4.2+ds1-1+b3 amd64
tool to manage containers and pods (Docker CLI)
podman-remote/testing 5.4.2+ds1-1+b3 amd64
tool to manage containers and pods (remote CLI)
Ich spreche von netavark. Dieses Paket ist auf Debian Trixie 13 eine Abhängigkeit von Podman, wird also mitinstalliert.
Netavark is a rust based network stack for containers. It is being designed to work with Podman but is also applicable for other OCI container management applications.
Und dieses Tool trägt dann in Zusammenhang alle Regeln die man braucht, in nftables ein. Vollautomatisch!
Ein Beispiel ist DNAT
chain NETAVARK-HOSTPORT-DNAT {
tcp dport 80 jump nv_1126fa6c_10_89_0_0_nm16_dnat
tcp dport 222 jump nv_1126fa6c_10_89_0_0_nm16_dnat
tcp dport 443 jump nv_1126fa6c_10_89_0_0_nm16_dnat
tcp dport 3000 jump nv_1126fa6c_10_89_0_0_nm16_dnat
}
Nachdem ich das alles wusste, war es auch relativ simpel, die Container dazu bewegen sinnvolles zu machen
Für die Installation von nftables macht man wie gewohnt
apt install nftables
systemd Kontrolle
systemd enable nftables # Erst einschalten, wenn ihr wisst das ihr noch auf die Kiste kommt!
systemctl start nftables
systemctl status nftables
Wann man was standardmäßig in die Konfiguration eintragen möchte, geht das mit
nano /etc/nftables.conf
Konfiguration testen
nft -f /etc/nftables.conf
Die Liste, der Regeln, kann man sich so anschauen
nft list ruleset
Ausgabe (gekürzt)
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
}
chain forward {
type filter hook forward priority filter; policy accept;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
table inet netavark {
chain INPUT {
type filter hook input priority filter; policy accept;
ip saddr 10.92.0.0/16 meta l4proto { tcp, udp } th dport 53 accept
}
Das schöne ist, das man nun auch fail2ban dazu bewegen kann seine Bans vollautomatisch in diese Liste einzutragen, dazu gibt es einen eigene Beitrag.
table inet f2b-table {
set addr-set-sshd {
type ipv4_addr
elements = { 13.67.94.200, 14.22.88.255,
14.103.119.118, 14.103.123.75,
14.103.236.35, 36.133.184.250,
36.134.2.209, 41.58.186.132,
46.101.8.63, 64.226.119.233,
64.227.110.144, 94.182.227.191,
101.126.135.80, 103.56.114.54,
117.149.247.143, 119.45.128.125,
125.124.106.113, 125.164.14.241,
128.199.33.46, 142.93.204.139,
157.245.71.30, 157.245.144.151,
161.132.43.198, 180.76.105.165,
185.93.89.118, 185.213.165.36,
193.32.162.146, 193.168.173.177,
199.188.103.179, 202.179.66.26,
220.80.197.180 }
}
Man, da sind aber schon wieder viele Script Kiddies unterwegs
Gestern hat das OpenCloud Team den Desktop Clienten v2.0.0-rc.1 released.
🖥️ The OpenCloud Desktop application. Contribute to opencloud-eu/desktop development by creating an account on GitHub.
GitHub (github.com)
Da fiel mir ein, das sollte man auch mal antesten. Leider gibt es nur ein AppImage, ich bevorzuge Flatpaks. Kommt ja vielleicht noch. Aber, ich wusste aktuell gar nicht, ob ich das AppImage auf meinem Manjaro gestartet bekomme. Versuch macht klug.
Also heruntergeladen und mal gestartet. Kommt eine kurze Nachfrage, ob man dem Herausgeber vertraut usw. Danach startet das AppImage. Das erste Fenster fragt nach der Serveradresse. Nach der Eingabe kann man sich auf dem Server einloggen und die entsprechenden Rechte freigeben. So wie man das auch von anderen Tools her kennt.
Man hat halt die Grundfunktionen, die man auch von anderen Tools her kennt.
So, das lasse ich jetzt hier mal zum Testen laufen. Mal sehen, wie es sich so schlägt.
Meinen ersten Versuch findet man hier. Mittlerweile habe ich das Setup verfeinert und bin zufrieden. Das wollte ich hier teilen.
Der Plan ist es einen Forgejo Server aufzusetzen. Die Dienste sollen alle als Podman Container laufen. Die Podman Installation soll auf Quadlet basieren.
Ich brauche also einen Forgejo Pod mit folgenden Containern
Das ganze soll auf Quadlet basieren. Was ist das?
Quadlet is a tool for running Podman containers under systemd in an optimal way by allowing containers to run under systemd in a declarative way. It has been merged into Podman 4.4.
Ok, wenn wir schon dran sind, was ist Podman?
Podman (kurz für POD-Manager) ist ein Open Source-Tool, mit dem Sie Container entwickeln, managen und ausführen können. Das Tool wurde von Red Hat
Engineers in Zusammenarbeit mit der Open Source Community entwickelt, und es verwaltet das gesamte Container-IT-Ökosystem mithilfe der libpod-Library.
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
Meine produktive Installation wird
Nachinstallierte Pakete.
apt install podman podman-compose fail2ban nftables git socat
Ich hoffe, ich habe hier nichts vergessen. Wenn doch kommt ja eine Meldung, dann kann man das einfach nachinstallieren.
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 anlegen
crontab -e
Inhalt
03 09 1 * * /root/renew_new.sh >> /var/log/acme-renewal.log 2>&1
Script (mit KI Hilfe)
#!/bin/bash
# Optimized SSL Certificate Renewal Script
LOG_FILE="/var/log/acme-renewal.log"
DOMAIN="forgejo.example.com"
CERT_DIR="/etc/nginx/letsencrypt/live/${DOMAIN}"
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
log "=== Starting SSL certificate renewal ==="
# Check if force renewal is requested
FORCE_RENEWAL=false
if [[ "$1" == "--force" ]]; then
FORCE_RENEWAL=true
log "Force renewal requested"
fi
# Only stop nginx
log "Stopping nginx service..."
systemctl stop nginx.service
sleep 2
# Renew certificate
log "Renewing certificate for $DOMAIN..."
cd /root/acme.sh
if [[ "$FORCE_RENEWAL" == true ]]; then
RENEW_CMD="./acme.sh --renew -d $DOMAIN --standalone --server letsencrypt --home /root/.acme.sh --force"
else
RENEW_CMD="./acme.sh --renew -d $DOMAIN --standalone --server letsencrypt --home /root/.acme.sh"
fi
if $RENEW_CMD; then
log "Certificate renewal successful"
# Copy certificates
cp /root/.acme.sh/${DOMAIN}_ecc/fullchain.cer "${CERT_DIR}/fullchain.pem"
cp /root/.acme.sh/${DOMAIN}_ecc/${DOMAIN}.key "${CERT_DIR}/key.pem"
chown -R 999:996 "${CERT_DIR}"
chmod 644 "${CERT_DIR}/fullchain.pem"
chmod 600 "${CERT_DIR}/key.pem"
log "Certificates installed successfully"
else
log "ERROR: Certificate renewal failed!"
systemctl start nginx.service
exit 1
fi
# Start nginx
log "Starting nginx service..."
systemctl start nginx.service
log "=== SSL renewal completed successfully ==="
Test auf der Konsole
2025-06-06 13:54:47 - Renewing certificate for forgejo.example.org...
[Fri Jun 6 01:54:47 PM UTC 2025] The domain 'forgejo.example.org' seems to already have an ECC cert, let's use it.
[Fri Jun 6 01:54:47 PM UTC 2025] Renewing: 'forgejo.example.org'
[Fri Jun 6 01:54:47 PM UTC 2025] Renewing using Le_API=https://acme-v02.api.letsencrypt.org/directory
[Fri Jun 6 01:54:47 PM UTC 2025] Skipping. Next renewal time is: 2025-07-27T18:24:25Z
[Fri Jun 6 01:54:47 PM UTC 2025] Add '--force' to force renewal.
2025-06-06 13:54:47 - ERROR: Certificate renewal failed!
Passt, Zertifikat noch gültig.
Ich brauche ein paar User auf dem Host.
useradd -m -d /home/pguser pguser
useradd -m -d /home/forgejo forgejo
podman secret create POSTGRES_PASSWORD /root/secrets/POSTGRES_PASSWORD.txt
Hier liegt das Postgres Passwort drin. Ich erläutere in einem anderen Artikel was Podman Secret ist.
/etc/containers/systemd/forgejo.pod
Kurz nochmal der Hinweis, ich baue jetzt eine komplette Quadlet Installation. Dafür legt man verschiedene Textfiles an, die dann von systemd in DIenste umgewandelt werden und das alles starten und verwalten.
Wir brauchen einen forgejo.pod
[Unit]
Description=Forgejo Pod
Requires=network.target
After=network-online.target
[Pod]
PodName=forgejo-pod
Network=systemd-podman-ipv4
PublishPort=3000:3000
PublishPort=222:22
PublishPort=80:80
PublishPort=443:443
#PublishPort=[::]:3000:3000
#PublishPort=[::]:222:22
#PublishPort=[::]:80:80
#PublishPort=[::]:443:443
[Install]
WantedBy=multi-user.target
Hier im Beispiel ist der POD nur IPv4 tauglich.
/etc/containers/systemd/podman-ipv4.network
Man sieht ja oben im Pod, das dort das Network systemd-podman-ipv4 aufgerufen. Dann erstellen wir das mal. Dazu brauchen wir das File podman-ipv4.network mit folgendem Inhalt.
# /etc/containers/systemd/podman-ipv4.network
[Unit]
Description=Podman IPv4 Network
Before=forgejo-pod.service
[Network]
Subnet=10.89.0.0/16
Gateway=10.89.0.1
IPRange=10.89.0.0/24
DisableDNS=true
[Install]
WantedBy=multi-user.target
Etwas verwirrend ist die Namensgebung. Hier sieht man aber was passiert.
root@debian-4gb-nbg1-2-forgejo:/etc/containers/systemd# systemctl status podman-ipv4-network.service
● podman-ipv4-network.service - Podman IPv4 Network
Loaded: loaded (/etc/containers/systemd/podman-ipv4.network; generated)
Active: active (exited) since Wed 2025-06-04 18:19:25 UTC; 1 day 19h ago
Invocation: 4c270a199fbd4ac08bc25e1cbc0bf316
Main PID: 854 (code=exited, status=0/SUCCESS)
Mem peak: 18.1M
CPU: 74ms
Jun 04 18:19:24 debian-4gb-nbg1-2-forgejo systemd[1]: Starting podman-ipv4-network.service - Podman IPv4 Network...
Jun 04 18:19:25 debian-4gb-nbg1-2-forgejo podman[854]: 2025-06-04 18:19:25.448483441 +0000 UTC m=+0.459031549 network create 1126fa6c1a9d35a035846e3710f9d1f9e7311d594487f6256487d060f4915>
Jun 04 18:19:25 debian-4gb-nbg1-2-forgejo podman-ipv4-network[854]: systemd-podman-ipv4
Jun 04 18:19:25 debian-4gb-nbg1-2-forgejo systemd[1]: Finished podman-ipv4-network.service - Podman IPv4 Network.
Wer wissen will warum, kann ja mal das bei einer KI seiner Wahl eingeben.
Im Pod steht "Network=systemd-podman-ipv4", der resultierende systemd Dienst "podman-ipv4-network.service" Warum ist das so?
Das hier
DisableDNS=true
hat mich sehr viel Zeit gekostet. Eigentlich wird der DNS im POD bzw. in dem resultierenden Netzwerk verwaltet, es gibt da aber offensichtlich einen fiesen Bug, weil es mir nicht gelungen ist eine DNS Auflösung aus dem Forgejo Container hinzubekommen. Somit wurd die DNS Auflösung ausgeschaltet und muss dann in jedem Container seperat eingestellt werden.
Issue Description When I use quatlet and define DNS either in network or pod or container (I testet IPv4 and IPv6) it is ignored. Steps to reproduce the issue Steps to reproduce the issue Set DNS=10.90.0.2 in pod or container service fil...
GitHub (github.com)
Der Rest kreiert ein internes Netzwerk, jetzt nichts besonderes.
Jetzt kommen wir zu den Containern
Hinweis zu den Environment Einträgen!
The Forgejo configuration is stored in the app.ini file as described in the Configuration Cheat Sheet. When using the Forgejo container image, this file is automatically created if it does not exist already. In addition it is possible to add settings using configuration variables. For instance:
FORGEJO__repository__ENABLE_PUSH_CREATE_USER=true
is the equivalent of adding the following to app.ini:
[repository] ENABLE_PUSH_CREATE_USER = true
NOTE: it is not possible to use environment variables to remove an existing value, it must be done by editing the app.ini file.
NOTE: in case you are in a SELinux environment check the audit logs if you are having issues with containers.
Quelle: https://forgejo.org/docs/latest/admin/installation-docker/
/etc/containers/systemd/forgejo.container
[Unit]
Description=Forgejo Container im Pod forgejo-pod
After=forgejo-pod.service
Requires=forgejo-pod.service
BindsTo=forgejo-pod.service
Restart=always
DNS=8.8.8.8
DNS=1.1.1.1
[Container]
Image=codeberg.org/forgejo/forgejo:11.0.1
AutoUpdate=registry
Label=PODMAN_SYSTEMD_UNIT=%n
PodmanArgs=--pod=forgejo-pod --name=forgejo
## User
Environment=USER_UID=1001
Environment=USER_GID=1001
## Mail
Environment=FORGEJO__MAILER
Environment=FORGEJO__MAILER__ENABLED=true
Environment=FORGEJO__MAILER__FROM=forgejo@example.com
Environment=FORGEJO__MAILER__PROTOCOL=smtps
Environment=FORGEJO__MAILER__SMTP_ADDR=smtps.example.com
Environment=FORGEJO__MAILER__SMTP_PORT=465
Environment=FORGEJO__MAILER__USER=<user>
Environment=FORGEJO__MAILER__PASSWD=<password>
## Registration
Environment=FORGEJO__SERVICE__REGISTER_EMAIL_CONFIRM=true
Environment=FORGEJO__SERVICE__ENABLE_NOTIFY_MAIL=true
Environment=FORGEJO__SERVICE__DISABLE_REGISTRATION=false
## Captcha
Environment=FORGEJO__SERVICE__ENABLE_CAPTCHA=true
Environment=FORGEJO__SERVICE__CAPTCHA_TYPE=cfturnstile
Environment=FORGEJO__SERVICE__CF_TURNSTILE_SECRET="<secret>"
Environment=FORGEJO__SERVICE__CF_TURNSTILE_SITEKEY="<sitekey>"
## Other
Environment=FORGEJO__SERVICE__DEFAULT_ALLOW_CREATE_ORGANIZATION=false
# Setting für Repositories
Environment=FORGEJO__repository__MAX_CREATION_LIMIT=0
## Log
Environment=FORGEJO__LOG__LEVEL=warn
Environment=FORGEJO__LOG__MODE=file
Environment=FORGEJO__LOG__ROOT_PATH=/data/forgejo/log
# Log-Rotation-Einstellungen
Environment=FORGEJO__LOG__FILE_NAME=forgejo.log
Environment=FORGEJO__LOG__ROTATE=true
Environment=FORGEJO__LOG__MAX_SIZE=256
Environment=FORGEJO__LOG__MAX_DAYS=7
Environment=FORGEJO__LOG__MAX_BACKUPS=5
Environment=FORGEJO__LOG__COMPRESS_BACKUPS=true
Environment=FORGEJO__LOG__COMPRESS_ARCHIVE=true
# Gleiche Einstellungen für Access- und Router-Logs
Environment=FORGEJO__LOG__ACCESS__LEVEL=warn
Environment=FORGEJO__LOG__ACCESS__MODE=file
Environment=FORGEJO__LOG__ACCESS__FILE_NAME=access.log
Environment=FORGEJO__LOG__ACCESS__ROTATE=true
Environment=FORGEJO__LOG__ACCESS__MAX_SIZE=256
Environment=FORGEJO__LOG__ACCESS__MAX_DAYS=7
Environment=FORGEJO__LOG__ACCESS__MAX_BACKUPS=5
Environment=FORGEJO__LOG__ROUTER__LEVEL=warn
Environment=FORGEJO__LOG__ROUTER__MODE=file
Environment=FORGEJO__LOG__ROUTER__FILE_NAME=router.log
Environment=FORGEJO__LOG__ROUTER__ROTATE=true
Environment=FORGEJO__LOG__ROUTER__MAX_SIZE=256
Environment=FORGEJO__LOG__ROUTER__MAX_DAYS=7
Environment=FORGEJO__LOG__ROUTER__MAX_BACKUPS=5
# Volumes
Volume=/home/forgejo:/data
Volume=/etc/timezone:/etc/timezone:ro
Volume=/etc/localtime:/etc/localtime:ro
[Install]
WantedBy=multi-user.target
WantedBy=forgejo-pod.service
Für NGINX brauchen wir folgende Files
/etc/nginx/default.conf
server {
listen 80;
server_name forgejo.example.org;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name forgejo.example.org.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.example.org/fullchain.pem;
ssl_certificate_key /etc/nginx/letsencrypt/live/forgejo.example.org/key.pem;
ssl_dhparam /etc/nginx/letsencrypt/live/forgejo.example.org.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://<IP-Adresse Server>: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
Dann das File für den Container
/etc/containers/systemd/nginx.container
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.
[Unit]
Description=NGINX Container im Pod forgejo-pod
After=forgejo-pod.service
Requires=forgejo-pod.service
BindsTo=forgejo-pod.service
Restart=always
[Container]
Image=docker.io/library/nginx:latest
AutoUpdate=registry
Label=io.containers.autoupdate=registry
Label=PODMAN_SYSTEMD_UNIT=%n
PodmanArgs=--pod=forgejo-pod --name=nginx --label=io.containers.autoupdate=registry --label=PODMAN_SYSTEMD_UNIT=%n
Volume=/etc/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
Volume=/etc/nginx/letsencrypt/live/forgejo.example.com/:/etc/nginx/letsencrypt/live/forgejo.example.com:ro
Volume=/etc/nginx/blocklists/nginx-block-ai-bots.conf:/etc/nginx/blocklists/nginx-block-ai-bots.conf:ro
Volume=/etc/nginx/blocklists/robots.txt:/var/www/html/robots.txt:ro
[Install]
WantedBy=multi-user.target
WantedBy=forgejo-pod.service
/etc/containers/systemd/postgres.container
[Unit]
Description=Postgres Container im Pod forgejo-pod
After=forgejo-pod.service
Requires=forgejo-pod.service
BindsTo=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
WantedBy=forgejo-pod.service
Nachdem alle Files erstellt wurden, lädt man mal den Daemon neu
systemctl daemon-reload
Jetzt sollten alle Dienste angelegt worden sein.
Das kann so kontrollieren. Netzwerkliste
root@forgejo:~# podman network list
NETWORK ID NAME DRIVER
2f259bab93aa podman bridge
1126fa6c1a9d systemd-podman-ipv4 bridge
Der Pod
root@forgejo:~# podman pod list
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
ed4aabd15fd7 forgejo-pod Running 6 hours ago 90dea473c3be 4
Die Container
root@debian-4gb-nbg1-2-forgejo:~# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
90dea473c3be localhost/podman-pause:5.4.2-1748111104 6 hours ago Up 6 hours 0.0.0.0:80->80/tcp, 0.0.0.0:222->22/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:3000->3000/tcp forgejo-pod-infra
bd58246de050 codeberg.org/forgejo/forgejo:11.0.1 /usr/bin/s6-svsca... 6 hours ago Up 6 hours 0.0.0.0:80->80/tcp, 0.0.0.0:222->22/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:3000->3000/tcp forgejo
4ad8f7e26210 docker.io/library/postgres:17 postgres 6 hours ago Up 6 hours 0.0.0.0:80->80/tcp, 0.0.0.0:222->22/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:3000->3000/tcp, 5432/tcp postgres
8173e49790fd docker.io/library/nginx:latest nginx -g daemon o... 43 minutes ago Up 44 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:222->22/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:3000->3000/tcp nginx
Wenn was nicht startet, kann man hiermit mal eben schnell reinschauen wo es klemmt.
systemctl status nginx.service
Die anderen Dienste analog.
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.
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.
Bei Gelegenheit ergänze ich noch die Installation von nftables & fail2ban.