惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 热门话题
Stack Overflow Blog
Stack Overflow Blog
B
Blog
WordPress大学
WordPress大学
Project Zero
Project Zero
P
Palo Alto Networks Blog
阮一峰的网络日志
阮一峰的网络日志
博客园 - 司徒正美
有赞技术团队
有赞技术团队
S
SegmentFault 最新的问题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
小众软件
小众软件
T
Tailwind CSS Blog
Forbes - Security
Forbes - Security
F
Full Disclosure
SecWiki News
SecWiki News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hacker News: Ask HN
Hacker News: Ask HN
C
Check Point Blog
Microsoft Security Blog
Microsoft Security Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
F
Fortinet All Blogs
Cisco Talos Blog
Cisco Talos Blog
G
Google Developers Blog
J
Java Code Geeks
Google DeepMind News
Google DeepMind News
人人都是产品经理
人人都是产品经理
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recorded Future
Recorded Future
O
OpenAI News
Spread Privacy
Spread Privacy
MongoDB | Blog
MongoDB | Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
Cybersecurity and Infrastructure Security Agency CISA
S
Securelist
V
Vulnerabilities – Threatpost
Y
Y Combinator Blog
IT之家
IT之家
U
Unit 42
腾讯CDC
S
Security Affairs
C
Cisco Blogs
Schneier on Security
Schneier on Security
The Last Watchdog
The Last Watchdog
B
Blog RSS Feed
宝玉的分享
宝玉的分享
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Security @ Cisco Blogs
Cyberwarzone
Cyberwarzone
T
The Blog of Author Tim Ferriss

Solene'%

Solene'% : Software to keep photos organized Solene'% : Make your own container base images from trusted sources Solene'% : File transfer made easier with Tailscale Solene'% : Comparison of cloud storage encryption software Solene'% : Revert fish shell deleting shortcuts behavior Solene'% : Hardware review: ergonomic mouse Logitech Lift Solene'% : URL filtering HTTP(S) proxy on Qubes OS Solene'% : Introduction to Qubes OS when you do not know what it is Solene'% : How to trigger a command on a running Linux laptop when disconnected from power
Solene'% : Declaratively manage containers on Linux
2026-02-10 · via Solene'%

Written by Solène, on 10 February 2026.
Tags: #systemd #linux #containers

Table of contents

  • 1. Introduction
  • 2. Setup (simple service)
  • 3. Setup (advanced service)
  • 4. Ops
    • 4. 1. Getting into a user shell
    • 4. 2. Disabling a user
    • 4. 3. Automatic updates
  • 5. Conclusion
  • 6. Going further

1. Introduction §

When you have to deal with containers on Linux, there are often two things making you wonder how to deal with effectively: how to keep your containers up to date, and how to easily maintain the configuration of everything running.

It turns out podman is offering systemd unit templates to declaratively manage containers, this comes with the fact that podman can run in user mode. This combination gives the opportunity to create files, maintain them in git or deploy them with a configuration management tool like ansible, and keep things separated per user.

It is also very convenient when you want to run a program shipped as a container on your desktop.

For some reason, this is called "quadlets".

podman-systemd.unit man page

In this guide, I will create a kanboard service (a PHP software to run a kanban) under the kanban user.

2. Setup (simple service) §

You need to create files that will declare containers and/or networks, this can be done in various places depending on how you want to manage the files, the man page gives all the details, but basically you want to stick with the two following options:

  • system-wide configuration: /etc/containers/systemd/users/$(UID)
  • user configuration: ~/.config/containers/systemd/

Both will run rootless containers under the user UID, but one keep the files in /etc/ which may be more suitable for central management.

As systemd is used to run the containers, if you want to run a container for a user that is not one where you are logged, you need to always enable it so its related systemd processes / services are running, including the containers, this is done by enabling "linger".

useradd -m kanban
loginctl enable-linger kanban

This will immediately create a session for that user and pop all related services.

Now, create a file /etc/containers/systemd/users/1001/ (1001 being the uid of kanban user) with this content:

[Container]
Image=docker.io/kanboard/kanboard:latest
Network=podman
PublishPort=10080:80
Volume=kanboard_data:/var/www/app/data
Volume=kanboard_plugins:/var/www/app/plugins
Volume=kanboard_ssl:/etc/nginx/ssl

[Service]
Restart=always

[Install]
WantedBy=default.target

This can exactly map to a very long podman command line that would use the image docker.io/kanboard/kanboard:latest in network podman and declaring three different container volumes and associated mount points. This generator even allows you to add command line arguments in case an option is not available with systemd format.

Because the user already runs, the container will not start yet except if you use disable-linger and then enable-linger the kanban user, and that would not be ideal to be honest. There is a better way to proceed: systemctl --user --machine kanban@ daemon-reload which basically runs systemctl --user daemon-reload by the user kanban except we do it as root user which is more convenient for automation.

Running the container this way will trigger exactly the same processes as if you started it manually with podman run -v kanboard_data:/var/www/app/data/ [...] docker.io/kanboard/kanboard:latest.

Note that you can skip the [Install] section if you do not want to automatically start the container, and prefer to manually start/stop it with "systemctl", this is actually useful if you have the container under your regular user and do not always need it.

3. Setup (advanced service) §

If you want to run a more complicated service that need a couple of containers to talk together like a web server, a backend runner and a database, you only need to configure them in the same network.

If you need them to start the containers of a group in a specific order, you can add use systemd dependency declaration in [Install] section.

Podman will run a local DNS resolver that translates the container name into a working hostname, this mean if you have a postgresql container called "db", then you can refer to the postgresql host as "db" from another container within the same network. This works the same way as docker-compose.

4. Ops §

4.1. Getting into a user shell §

To have a working environment for journalctl or systemctl commands to work requires to use machinectl shell kanban@, otherwise the dbus environment variables will not be initialized. Note that it works too when connecting with ssh, but it is not always ideal if you use it locally.

From this shell, you can run commands like systemctl --user status kanboard.container for our example or journalctl --user -f -u kanboard.container, or run a shell in a container, inspect a volume etc...

Using sudo -u user or su - user will not work.

4.2. Disabling a user §

If you want to disable the services associated with an user, use this command:

loginctl disable-linger username

This will immediately close all its sessions and stop services running under that user.

4.3. Automatic updates §

This is the very first reason I went into using quadlets for local services using containers, I did not want to have to manually run some podman pull commands over a list then restart related containers that were running.

Podman gives you a systemd services doing all of this for you, this works for containers with the parameter AutoUpdate=registry within the section [Container].

Enable the timer of this service with: systemctl --user enable --now podman-auto-update.timer then you can follow the timer information with systemctl --user status podman-auto-update.timer or logs from the update service with journalctl --user -u podman-auto-update.service.

Make sure to pin your container image to a branch like "stable" or "lts" or "latest" if you want a development version, the update mechanism will obviously do nothing if you pin the image to a specific version or checksum.

5. Conclusion §

Quadlets made me switch to podman as it allowed me to deploy and maintain containers with ansible super easily, and also enabled me to separate each services into different users.

Prior to this, handling containers on a simple server or desktop was an annoying task to figure what should be running, how to start them and retrieving command lines from the shell history or use a docker/podman compose file. This also comes with all the power from systemd like querying a service status or querying logs with journalctl.

6. Going further §

There is a program named "podlet" that allow you to convert some file format into quadlets files, most notably it is useful when getting a docker-compose.yml file and transforming it into quadlet files.

podlet GitHub page