Rootless podman installation

Published

This is a guide on how to install cradle-cms as a rootless podman systemd service on a DietPI distro. DietPI is a bare minimal debian installation mainly targeted for SBC:s but it works on PC:s and laptops as well.

We also show how to setup automatic software updates.

Install latest podman and required dependencies

The curse of many debian based distros is that they are far behind the latest software versions. In this case we need podman v5.8+ but it’s not available in the package sources. To overcome that we install podman from debian unstable.

Add debian unstable and set it as a low priority source.

echo "deb https://deb.debian.org/debian unstable main contrib" >> /etc/apt/sources.list
cat << EOF >> /etc/apt/preferences
Package: *
Pin: release o=debian, a=unstable
Pin-Priority: 300
EOF
apt update

Now you can install podman from unstable along with the dependencies we need.

apt install podman -t unstable dbus-user-session passt polkitd uidmap slirp4netns

Setup so that non-root users can bind to http and https ports and reboot the system.

echo "net.ipv4.ip_unprivileged_port_start=80" > /etc/sysctl.d/unprivileged.conf
reboot

Create a non root user

We want a rootless podman that runs as a non root cradle user.

adduser --comment "Cradle Podman" cradle
# give user access to journalctl
usermod -a -G systemd-journal cradle
# setup podman user runtime directory
mkdir -p /run/user/$(id -u cradle)
chown -R cradle:cradle /run/user/$(id -u cradle)
echo '[ -z "${XDG_RUNTIME_DIR}" ] && export XDG_RUNTIME_DIR=/run/user/$(id -ru)' >> /home/cradle/.profile
chown -R cradle:cradle /home/cradle/.profile
# allow cradle user to have lingering processes
systemctl unmask systemd-logind.service
systemctl start systemd-logind.service
loginctl enable-linger cradle

Instead of password login you should use ssh authorized_keys

Login as the cradle user and setup podman environment

Login to your server as the cradle user ssh cradle@your.server.ip

# check that you have a working podman and that the version is `v5.8+`
podman -v
# login to the registry using your licensekey and account password
# we store the authentication in `auth.json` as it's needed for automatic updates 
mkdir -p /home/cradle/.config/containers
podman login --authfile /home/cradle/.config/containers/auth.json registry.cradlecms.com/cradle-cms
# test that pulling from the registry using the `auth.json` actually works
podman pull --authfile /home/cradle/.config/containers/auth.json registry.cradlecms.com/cradle-cms:latest

Create container configuration

This is a basic configuration which uses a self signed certificate for https. If you need a letsencrypt certificate for your own domain name then change Environment=ACME=false to Environment=DOMAIN_NAME=your.domain.name.

Create the following podman quadlet file ~/.config/cradle-cms.quadlets

# FileName=cradle-cms
[Unit]
Description=Cradle CMS

[Container]
Image=cms-latest.image
ContainerName=cradle-cms
Environment=ACME=false
PublishPort=443:4040
PublishPort=80:8080
Volume=storage:/storage
AutoUpdate=registry

[Service]
Restart=always
RestartSec=10

[Install]
WantedBy=default.target
---
# FileName=cms-latest
[Image]
Image=registry.cradlecms.com/cradle-cms:latest
AuthFile=/home/cradle/.config/containers/auth.json

After that install the podman quadlets file.

podman quadlets install -r ~/.config/cradle-cms.quadlets

In production we recommend that you pin the version number instead of using :latest so set it to a feature release number like :0.14.

For tests or if you want early access to new features you may use the :test tag.

Start the cradle-cms service

systemctl --user daemon-reload
# check that the cradle-cms.service has been generated
systemctl --user cat cradle-cms
# start the container
systemctl --user start cradle-cms
# check the service status
systemctl --user status cradle-cms
# start the auto update timer
systemctl --user enable --now podman-auto-update.timer

The auto update timer is by default set to daily updates. If you want to schedule the updates more specifically i.e when you have least traffic, you can override the timer configuration.

# override the auto update OnCalendar timer
systemctl --user edit podman-auto-update.timer
# Insert the following lines so that podman auto update runs daily at 4am.
[Timer]
OnCalendar=
OnCalendar=*-*-* 04:00:00

And finally, reboot the server to ensure the service starts up automatically as expected.

That’s it, the only real hassle was that debian “stable” sources didn’t contain the podman version we wanted.

Troubleshooting

Since there are many linux distributions and they work a bit differently, you likely need to adjust this setup a bit. The most common problems are missing or conflicting dependencies and various permission errors.

If you get service not found when starting the service it’s most likely caused by errors in the podman quadlet config. You can validate the service file generation using /usr/lib/systemd/system-generators/podman-system-generator --user --dryrun and correct any reported issues. Then run systemctl --user daemon-reload which should produce a cradle-cms service file, verify with systemctl --user cat cradle-cms.

You can also inspect the service logs using journalctl --user -u cradle-cms.