Here's how to run podman containers as systemd units using "quadlets".
I was running my GoToSocial instance as a rootless container using podman-compose on a VPS with Debian Trixie. This was working fine, but when rebooting the server, I would have to manually log in, switch to the dedicated user account and start the container. Not starting this automatically is a real PITA, so I wanted to change this by using podman quadlets instead, which generate standard systemd unit files.
My starting point was a compose.yaml file:
services:
gotosocial:
image: docker.io/superseriousbusiness/gotosocial:0.19.2
container_name: gotosocial
user: 1004:1004
networks:
- gotosocial
environment:
GTS_HOST: fedi.4x31.dev
GTS_DB_TYPE: sqlite
GTS_DB_ADDRESS: /gotosocial/storage/sqlite.db
GTS_LETSENCRYPT_ENABLED: "false"
GTS_WAZERO_COMPILATION_CACHE: /gotosocial/.cache
GTS_TRUSTED_PROXIES: "192.168.0.1/16"
GTS_LOG_LEVEL: warn
TZ: Europe/Berlin
ports:
- "127.0.0.1:9000:8080"
volumes:
- ./data:/gotosocial/storage
- ./.gtscache:/gotosocial/.cache
restart: "always"
networks:
gotosocial:
ipam:
driver: default
config:
- subnet: "192.168.0.1/16"
gateway: "192.168.0.100"
First I defined the podman network:
# /etc/containers/system/gotosocial.network
[Network]
Subnet=192.168.0.1/16
Gateway=192.168.0.100
Then the container itself, which depends on this network:
# /etc/containers/system/gotosocial.container
[Unit]
Description=GoToSocial
Wants=network-online.target
After=network-online.target
Requires=gotosocial.network
After=gotosocial.network
[Container]
Image=docker.io/superseriousbusiness/gotosocial:0.19.2
# This is the UID:GID of the non-privileged user I was using with podman-compose
User=1004:1004
UserNS=keep-id
Environment=GTS_HOST=fedi.4x31.dev
Environment=GTS_DB_TYPE=sqlite
Environment=GTS_DB_ADDRESS=/gotosocial/storage/sqlite.db
Environment=GTS_LETSENCRYPT_ENABLED=false
Environment=GTS_WAZERO_COMPILATION_CACHE=/gotosocial/.cache
Environment=GTS_TRUSTED_PROXIES="192.168.0.1/16"
Environment=GTS_LOG_LEVEL=warn
Environment=TZ=Europe/Berlin
Volume=/home/gotosocial/data:/gotosocial/storage:rw,U,z
Volume=/home/gotosocial/.gtscache:/gotosocial/.cache:rw,U,z
PublishPort=127.0.0.1:9000:8080
Network=gotosocial.network
[Service]
TimeoutStartSec=900
Restart=always
[Install]
WantedBy=multi-user.target
I was able to test this configuration using the "dry-run mode" of the generator and review the output:
sudo /usr/lib/systemd/system-generators/podman-system-generator -dryrun
With all this set up, I was able to start the service and check the logs:
sudo systemctl daemon-reload
sudo systemctl start gotosocial
sudo journalctl -u gotosocial -f
Looking at the logs I noticed that ufw, my firewall, was blocking both DNS traffic from the podman network as well as outgoing traffic required to fetch media from other instances. So I allowed DNS and outgoing traffic for podman containers:
sudo ufw allow in on podman1 to any port 53
sudo ufw route allow in on podman1 out on ens3
sudo ufw status verbose
It was quite a journey figuring out all required steps. But I am very happy with the result, and I hope this little guide may help others. Thanks for reading! <3
#SelfHosting #FediVerse #GoToSocial #podman #containers #systemd #ufw #quadlet