/herz-quadlet

A repository where I store my podman quadlets.

GNU General Public License v3.0GPL-3.0

herz-quadlet

A repository where I store my podman quadlets.

What are Quadlets?

Quadlets are a new way to manage containers. They consist of .container files.

They were originally a separate project which has now been merged into Podman.

By writing an INI file with the .container extension (as well as .network, .volume and .kube if needed) and storing it in a certain directory, systemd is able to automatically generate a systemd service using systemd-generate. Once the service is started, it will pull all required images and run a podman container.

It deprecates, but is not a direct alternative to, podman-generate-systemd. It is more of an alternative to docker-compose.yml or compose.yml files. So instead of writing compose files following the Compose Specification, and instead of using something like docker compose or podman compose, you write files in INI format, similarly to a systemd unit.

It is not a direct alternative to podman-generate-systemd because it does not generate the new format using your existing compose files. You need to manually create new files based on them. Thankfully, there is a tool called Podlet that is able to generate container files for you based on podman run, podman compose or a {docker-}compose.yml.

Where are Quadlets stored?

Podman unit search path:

  • /etc/containers/systemd/
  • /usr/share/containers/systemd/

Podman user unit search path:

  • ~/.config/containers/systemd/ <---- Only for your user
  • /etc/containers/systemd/users/$(UID) <---- Only for a specific user
  • /etc/containers/systemd/users/ <---- For all users

If you have no idea how to get started or you are using rootless Podman, store your container files in ~/.config/containers/systemd/ and run them as a user.

Quickstart

  1. Create the folder ~/.config/containers/systemd/.
  2. Copy the owncast.container file to ~/.config/containers/systemd/.
  3. Run systemctl daemon-reload --user.
  4. Run systemctl start --user owncast.

Done, you now have your own selfhosted Owncast instance! You can visit it under localhost:8080 and configure it under localhost:8080/admin.

Additionally, the following commands might be useful to you:

  • systemctl status --user owncast: check the Owncast service status.
  • systemctl list-unit-files --user --all --state generated: list all generated services.
  • journalctl --user-unit owncast: see the logs for your Owncast container.
  • podman stats owncast: monitor the status of your Owncast container.
  • journalctl enable-linger youruser: let systemd services run while your user is not logged in.

What do you need to use Quadlets?

Learn more about Quadlets

The real source-of-truth documentation is podman-systemd.unit. You might also want to look at systemd.unit and systemd.service to learn more about how to manage systemd services.

Current caveats

  • The current documentation is scarce, and the only true documentation is a manpage, namely podman-systemd.unit, which is far from ideal. There is the docs folder of the original project, and while useful, it is severely outdated.

  • If your podman container setup relies on Kubernetes Pods / Podman Pods instead of Docker Networks, you are either forced to write your own Kubernetes Deployment files, generate Kubernetes Deployment files with podman-kube-generate, or rewrite your setup to use Docker Networks instead (the easiest option).

  • Depending on your Podman version, not all entries in podman-systemd.unit might be supported. In that case, use the respective Podman command line flags under the entry PodmanArgs=.

  • Unlike compose files which have built-in dependency management, this is not present within the [Container] section of container files, and together with certain policies, such as Restart= or modifications to the container command like Exec=, such features will have to be adapted to systemd unit style. You might want to use WantedBy=default.target in the [Install] section to start a service on boot. The following is a good read on how unit dependencies behave in systemd: Difference between PartOf and BindsTo in a systemd unit.

Advantages of Quadlets

  • Podman Pods require you to define ports and whatnot at Pod creation time, which can be unpractical if you need to change your setup in the future. With Quadlets, you alter the container file, reload the daemon and restart the service.

  • Using podman-generate-systemd always generates complex and hard-to-read systemd service files. Quadlets do not have this issue.

  • Using podman-generate-systemd together with podman-compose is not very robust: after making drastic changes to a compose file and recreating the containers/ pods, the generated services will lose their ability to manage those containers. With Quadlets, container files have an inherent connection to their respective systemd services.

  • Extending a service is as simple as adding or removing a few lines and restarting the daemon and service.

  • Systemd features are available to container files. Things like OnFailure= to trigger another service if the current one fails, ExecStopPost= to run an arbitrary command if the current service fails, container logs are stored in journald and are accessible via journalctl, containers can be managed together with systemd timers, etc. This allows for capabilities that are not possible or are difficult to do with compose files.

  • Because all processes related to the container are under the same service cgroup, systemd is able to manage it entirely, and changing the respective cgroup affects the entire container.

  • Because the containers are internally run with podman, you can still manage them with podman as you wish. This is useful, for instance, if the container requires a restart after some internal modification to the container (like MediaWiki), or if it needs changes to its matching database (like WriteFreely).