podman-systemd.unit(5)
π podman-systemd.unit(5) β File Formats Manual π
okay so you're reading podman-systemd.unit(5), from the File Formats Manual, and it's literally the glow-up guide for Podman Quadlet systemd units. π«Ά
πΈ NAME πΈ
podman-systemd.unit β systemd units using Podman Quadlet.
β¨ SYNOPSIS β¨
Quadlet unit filenames are giving this exact shape, bestie:
name.artifact, name.build, name.container, name.image, name.kube,
name.network, name.pod, name.volume
and the file types are:
.buildβ Builds a container image from aContainerfile. Seepodman-build.unit(5)..containerβ Defines and manages a single container. Seepodman-container.unit(5)..imageβ Pulls and caches a container image. Seepodman-image.unit(5)..kubeβ Deploys containers from Kubernetes YAML usingpodman-kube.unit(5)..networkβ Creates a Podman network for containers and pods. Seepodman-network.unit(5)..podβ Creates a Podman pod that containers can join. Seepodman-pod.unit(5)..volumeβ Ensures a named Podman volume exists. Seepodman-volume.unit(5).
ποΈ Podman rootful unit search path
Quadlet files for the root user can be placed in these directories, ordered in precedence. Meaning duplicate named quadlets found under /run take precedence over ones in /etc, as well as those in /usr:
Temporary quadlets, usually used for testing:
/run/containers/systemd/
System administrator's defined quadlets:
/etc/containers/systemd/
Distribution defined quadlets:
/usr/share/containers/systemd/
π Podman rootless unit search path
Quadlet files for non-root users can be placed in the following directories:
$XDG_RUNTIME_DIR/containers/systemd/$XDG_CONFIG_HOME/containers/systemd/or~/.config/containers/systemd//etc/containers/systemd/users/${UID}/etc/containers/systemd/users//usr/share/containers/systemd/users/${UID}/usr/share/containers/systemd/users/
π Using symbolic links
Quadlet supports using symbolic links for the base of the search paths and inside them. slay. π
π DESCRIPTION π
Podman supports building and starting containers (and creating volumes) via systemd by using a systemd generator. These files are read during boot (and when systemctl daemon-reload is run) and generate corresponding regular systemd service unit files. Both system and user systemd units are supported. All options and tables available in standard systemd unit files are supported. For example, options defined in the [Service] table and [Install] tables pass directly to systemd and are handled by it. See systemd.unit(5) man page for more information.
The Podman generator reads the search paths above and reads files with the extensions .container .volume, .network, .build, .pod, .kube, and .artifact, and for each file generates a similarly named .service file. Be aware that existing vendor services (i.e., in /usr/) are replaced if they have the same name. The generated unit files can be started and managed with systemctl like any other systemd service. systemctl {--user} list-unit-files lists existing unit files on the system. To list unit files of a user who has /sbin/nologin as a login shell, run sudo systemctl --machine username@ --user list-unit-files.
The Podman files use the same format as regular systemd unit files. Each file type has a custom section (for example, [Container]) that is handled by Podman, and all other sections are passed on untouched, allowing the use of any normal systemd configuration options like dependencies or cgroup limits.
The source files also support drop-ins in the same way systemd does. For a given source file (foo.container), the corresponding .d directory (foo.container.d) will be scanned for files with a .conf extension, which are then merged into the base file in alphabetical order. Top-level type drop-ins (container.d) will also be included. If the unit contains dashes (-) in the name (foo-bar-baz.container), then the drop-in directories generated by truncating the name after the dash are searched as well (foo-.container.d and foo-bar-.container.d). Drop-in files with the same name further down the hierarchy override those further up (foo-bar-baz.container.d/10-override.conf overrides foo-bar-.container.d/10-override.conf, which overrides foo-.service.d/10-override.conf, which overrides container.d/10-override.conf). The format of these drop-in files is the same as the base file. This is useful to alter or add configuration settings for a unit, without having to modify unit files.
For rootless containers, when administrators place Quadlet files in the /etc/containers/systemd/users or /usr/share/containers/users directories, all users' sessions execute the Quadlet when the login session begins. If the administrator places a Quadlet file in the /etc/containers/systemd/users/${UID}/ or /usr/share/containers/users/${UID} directory, then only the user with the matching UID executes the Quadlet when the login session gets started. For unit files placed in subdirectories within /etc/containers/systemd/users/${UID}/, /usr/share/containers/users/${UID} and the other user unit search paths, Quadlet will recursively search and run the unit files present in these subdirectories.
Note that Quadlet units do not support running as a non-root user by defining the User, Group, or DynamicUser systemd options. If you want to run a rootless Quadlet, you will need to create the user and add the unit file to one of the above rootless unit search paths.
When a Quadlet unit starts, Podman may need to pull or build container images, which can take significantly longer than systemd's default 90-second service startup limit. If this causes the unit to fail, you can either pre-pull the required images or increase the service's startup timeout using the TimeoutStartSec option. Keep in mind, however, that for units that specify Type=oneshot, the startup timeout is disabled by default (set to infinity), so TimeoutStartSec must be explicitly configured if a timeout is desired. For further details on TimeoutStartSec, see systemd.service(5).
Adding the following snippet to a Quadlet file extends the startup timeout to 15 minutes.
[Service]
TimeoutStartSec=900
Quadlet requires the use of cgroup v2, use podman info --format {{.Host.CgroupsVersion}} to check on the system.
βοΈ Service Type
By default, the Type field of the Service section of the Quadlet file does not need to be set. Quadlet will set it to notify for .container and .kube files, forking for .pod files, and oneshot for .volume, .network, .build, .image, and .artifact files.
However, Type may be explicitly set to oneshot for .container and .kube files when no containers are expected to run once podman exits.
When setting Type=oneshot, it is recommended to also set RemainAfterExit=yes to prevent the service state from becoming inactive (dead). However, when activating a service via a timer unit, having RemainAfterExit=yes leaves the job in a "started" state which prevents subsequent activations by the timer. For more information, see the systemd.service(5) man page.
Examples for such cases:
.containerfile with an image that exits after their entrypoint has finished.kubefile pointing to a Kubernetes Yaml file that does not define any containers. E.g. PVCs only
π Enabling unit files
The services created by Podman are considered transient by systemd, which means they don't have the same persistence rules as regular units. In particular, it is not possible to systemctl enable them in order for them to become automatically enabled on the next boot.
To compensate for this, the generator manually applies the [Install] section of the container definition unit files during generation, in the same way systemctl enable does when run later.
For example, to start a container on boot, add something like this to the file:
[Install]
WantedBy=default.target
Currently, only the Alias, WantedBy, RequiredBy, and UpheldBy keys are supported.
The Install section can be part of the main file, or it can be in a separate drop-in file as described above. The latter allows you to install a non-enabled unit and then later enabling it by installing the drop-in.
𧬠Template files
Systemd supports a concept of template files. They are units with names of the form basename@instancename.service when they are running, but that can be instantiated multiple times from a single basename@.service file. The individual instances can also be different by using drop-in files with the full instance name.
Quadlets support these in two ways. First of all, a quadlet unit with a template form will generate a systemd service with a template form, and the template systemd service can be used as a regular template. For example, foo@.container will generate foo@.service and you can then systemctl start foo@bar.service.
Secondly, if you make a symlink like foo@instance.container, that will generate an instantiated template file. When generating this file quadlet will read drop-in files both from the instanced directory (foo@instance.container.d) and the template directory (foo@.container.d). This allows customization of individual instances.
Instanced template files (like foo@bar.container) can be enabled just like non-templated ones. However, templated ones (foo@.container) are different, because they need to be instantiated. If the [Install] section contains a DefaultInstance= key, then that instance will be enabled, but if not, nothing will happen and the options will only be used as the default for units that are instantiated using symlinks.
An example template file sleep@.container might look like this:
[Unit]
Description=A templated sleepy container
[Container]
Image=quay.io/fedora/fedora
Exec=sleep %i
[Service]
# Restart service when sleep finishes
Restart=always
[Install]
WantedBy=multi-user.target
DefaultInstance=100
If this is installed, then on boot there will be a sleep@100.service running that sleeps for 100 seconds. You can then do something like systemctl start sleep@50.service to start another instance that sleeps 50 seconds, or alternatively another service can start it via a dependency like Wants=sleep@50.service.
In addition, if you do ln -s sleep@.container sleep@10.container you will also have a 10 second sleep running at boot. And, if you want that particular instance to be running with another image, you can create a drop-in file like sleep@10.container.d/10-image.conf:
[Container]
Image=quay.io/centos/centos
π Referencing other template Quadlets
It often occurs that you may want to reference another template Quadlet from your Quadlet. For example, you may want each instance of foo@.container to mount a distinct volume. In this case you can create a template Quadlet foo-data@.volume (the name is arbitrary) and reference it in foo@.container:
foo-data@.volume:
okay so hereβs the example in action, bestie:
[Volume]
# Optional: without an explicit VolumeName, Quadlet auto-generates one with a
# "systemd-" prefix (e.g. systemd-foo-data-%i for foo-data@.volume).
# This does not affect how you reference this Quadlet from other Quadlets.
VolumeName=my-name-%i
foo@.container:
[Container]
Volume=foo-data@.volume:/mnt/path
Note that we reference the template name foo-data@.volume instead of the instance name foo-data@%i.volume. Quadlet will read the template file and determine the correct volume name (with the systemd specifier) for the podman run command in the generated .service file. In this example, the ExecStart generated by Quadlet would look something like this:
ExecStart=/usr/bin/podman run ... -v my-name-%i:/mnt/path ...
π€οΈ Relative paths π€οΈ
In order to support systemd specifiers, Quadlet does not resolve relative paths that start with %. To resolve such a path, prepend it with ./.
For example, instead of EnvironmentFile=%n/env use EnvironmentFile=./%n/env.
π Debugging unit files π
After placing the unit file in one of the unit search paths (mentioned above), you can start it with systemctl start {--user}. If it fails with "Failed to start example.service: Unit example.service not found.", then it is possible that you used incorrect syntax or you used an option from a newer version of Podman Quadlet and the generator failed to create a service file.
View the generated files and/or error messages with:
/usr/lib/systemd/system-generators/podman-system-generator {--user} --dryrun
Alternatively, show only the errors with:
systemd-analyze {--user} --generators=true verify example.service
That command also performs additional checks on the generated service unit. For details, see systemd-analyze(1) man page.
π Debugging a limited set of unit files π
If you would like to debug a limited set of unit files, you can copy them to a separate directory and set the QUADLET_UNIT_DIRS environment variable to this directory when running the command below:
QUADLET_UNIT_DIRS=<Directory> /usr/lib/systemd/system-generators/podman-system-generator {--user} --dryrun
This will instruct Quadlet to look for units in this directory instead of the common ones and by that limit the output to only the units you are debugging.
π Implicit network dependencies π
Quadlet will add dependencies on network-online.target (as root) or podman-user-wait-network-online.service (as user) by adding After= and Wants= properties to the unit. This is to ensure that the network is reachable if an image needs to be pulled and by the time the container is started.
The special case podman-user-wait-network-online.service unit is needed as user because user units are unable to wait for system (root) units so network-online.target doesn't do anything there and is instead ignored. As this caused a significant amount of issues we decided to work around this with our own special purpose unit that simply checks if the network-online.target unit is active with systemctl is-active network-online.target.
This behavior can be disabled by adding DefaultDependencies=false in the Quadlet section.
β οΈ Note: the systemd [Unit] section has an option with the same name but a different meaning.
π Dependency between Quadlet units π
Quadlet will automatically translate dependencies, specified in the keys Wants, Requires, Requisite, BindsTo, PartOf, Upholds, Conflicts, Before and After of the [Unit] section, between different Quadlet units.
For example the fedora.container unit below specifies a dependency on the basic.container unit.
[Unit]
After=basic.container
Requires=basic.container
[Container]
Image=registry.fedoraproject.org/fedora:41
π·οΈ Setting resource names π·οΈ
Quadlet units allow setting the names of the created resources (e.g. VolumeName for .volume units or PodName for .pod units).
Note that using systemd specifiers that reference the generated service unit (e.g. $N) breaks Quadlet's ability to link between resources as they are translated differently in each service.
π³ Container units [Container] π³
Container units are named with a .container extension and contain a [Container] section describing the container that is run as a service. The resulting service file contains a line like ExecStart=podman run β¦ image-name, and most of the keys in this section control the command-line options passed to Podman. However, some options also affect the details of how systemd is set up to run and interact with the container.
By default, the Podman container has the same name as the unit, but with a systemd- prefix, i.e. a $name.container file creates a $name.service unit and a systemd-$name Podman container. The ContainerName option allows for overriding this default name with a user-provided one.
There is only one required key, Image, which defines the container image the service runs.
Valid options for [Container] are listed below:
Okay bestie, picking right back up with the cheat sheet β left column is what you write in the unit file, right column is the podman run flag it turns into. No cap, they line up almost one-to-one π«Ά
AddCapability=CAPβ this is--cap-add CAP, easy peasyAddDevice=/dev/fooβ becomes--device /dev/foo, so your container can actually touch the thingAddHost=example.com:192.168.10.11β turns into--add-host example.com:192.168.10.11Annotation="XYZ"β same as--annotation "XYZ"(quotes and all, don't lose 'em π )AppArmor="alternate-profile"β maps to--security-opt apparmor=alternate-profileAutoUpdate=registryβ lowkey just a label wearing a costume:--label "io.containers.autoupdate=registry"CgroupsMode=no-conmonβ that's--cgroups=no-conmonContainerName=nameβ the classic,--name nameContainersConfModule=/etc/nvd.confβ lines up with--module=/etc/nvd.confDNS=192.168.55.1β same as--dns=192.168.55.1DNSOption=ndots:1β same as--dns-option=ndots:1DNSSearch=example.comβ same as--dns-search example.comDropCapability=CAPβ the flip side,--cap-drop=CAPEntrypoint=/foo.shβ same as--entrypoint=/foo.shEnvironment=foo=barβ this one's--env foo=barEnvironmentFile=/tmp/envβ this one's--env-file /tmp/envEnvironmentHost=trueβ this one's--env-hostExec=/usr/bin/commandβ special case alert π¨ this isn't a flag at all, it's the command that goes after the image name, like/usr/bin/commandExposeHostPort=50-59β same as--expose 50-59GIDMap=0:10000:10β same as--gidmap=0:10000:10GlobalArgs=--log-level=debugβ same as--log-level=debugGroup=1234β quirky one: this is--user UID:1234(yes, literally the stringUIDin there β don't @ me, that's what it says π)GroupAdd=keep-groupsβ same as--group-add=keep-groupsHealthCmd=/usr/bin/commandβ same as--health-cmd=/usr/bin/commandHealthInterval=2mβ same as--health-interval=2mHealthLogDestination=/foo/logβ same as--health-log-destination=/foo/logHealthMaxLogCount=5β same as--health-max-log-count=5HealthMaxLogSize=500β same as--health-max-log-size=500HealthOnFailure=killβ same as--health-on-failure=killHealthRetries=5β same as--health-retries=5HealthStartPeriod=1mβ same as--health-start-period=1mHealthStartupCmd=commandβ same as--health-startup-cmd=commandHealthStartupInterval=1mβ same as--health-startup-interval=1mHealthStartupRetries=8β same as--health-startup-retries=8
β¦and the list keeps going, don't you worry π§
π key β flag, the saga continues π
okay so the chart keeps going, bestie β left side is what you type in the unit file, right side is the podman run flag it lowkey turns into. no cap, it's giving "translator app" energy π
HealthStartupSuccess=2β--health-startup-success=2π«HealthStartupTimeout=1m33sβ--health-startup-timeout=1m33sβ±οΈHealthTimeout=20sβ--health-timeout=20sβHostName=example.comβ--hostname example.comβ yes she gets a name, main character energy β¨HttpProxy=trueβ--http-proxy=trueπImage=ubi8β the image specification itself, so that's imageubi8πΌοΈImageVolume=tmpfsβ--image-volume tmpfsπ¦IP=192.5.0.1β--ip 192.5.0.1IP6=2001:db8::1β--ip6 2001:db8::1β v6 girlies rise πΈLabel="XYZ"β--label "XYZ"π·οΈLogDriver=journaldβ--log-driver journaldLogOpt=path=/var/log/mykube.jsonβ--log-opt path=/var/log/mykube.jsonπMask=/proc/sys/foo:/proc/sys/barβ--security-opt mask=/proc/sys/foo:/proc/sys/barβ those paths simply do not exist to the container, periodt πMemory=20gβ--memory 20gπΎMount=type=...β--mount type=...Network=hostβ--network hostπΈοΈNetworkAlias=nameβ--network-alias nameNoNewPrivileges=trueβ--security-opt no-new-privilegesπNotify=trueβ--sdnotify containerβ that's the sdnotify vibe, iykyk πPidsLimit=10000β--pids-limit 10000Pod=pod-nameβ--pod=pod-nameπ«PodmanArgs=--publish 8080:80β--publish 8080:80β the sneaky backdoor for extra flags πͺPublishPort=8080:80β--publish 8080:80πPull=neverβ--pull neverReadOnly=trueβ--read-onlyβ she's frozen, do not touch π§ReadOnlyTmpfs=trueβ--read-only-tmpfsReloadCmd=/usr/bin/commandβ addsExecReloadand runsexecwith the value πReloadSignal=SIGHUPβ addsExecReloadand runskillwith the signal πΆRetry=5β--retry=5πRetryDelay=5sβ--retry-delay=5sβ³Rootfs=/var/lib/rootfsβ--rootfs /var/lib/rootfsπ³RunInit=trueβ--initπ£SeccompProfile=/tmp/s.jsonβ--security-opt seccomp=/tmp/s.jsonπ‘οΈSecret=secretβ--secret=secret[,opt=opt ...]π€« (yes, the[,opt=opt ...]part is literally there, copy it exactly bestie)SecurityLabelDisable=trueβ--security-opt label=disableπ·οΈSecurityLabelDisable=true...
wait, hold on β the last one is where our part ends π more coming, don't go anywhere π
SecurityLabelFileType=usr_tβ maps to--security-opt label=filetype:usr_tSecurityLabelLevel=s0:c1,c2β maps to--security-opt label=level:s0:c1,c2SecurityLabelNested=trueβ maps to--security-opt label=nestedSecurityLabelType=spc_tβ maps to--security-opt label=type:spc_tServiceName=nameβ names the systemd unitname.serviceShmSize=100mβ maps to--shm-size=100mStartWithPod=trueβ ifPod=is defined, the container gets started by the podStopSignal=SIGINTβ maps to--stop-signal=SIGINTStopTimeout=20β maps to--stop-timeout=20SubGIDMap=gtestβ maps to--subgidname=gtestSubUIDMap=utestβ maps to--subuidname=utestSysctl=name=valueβ maps to--sysctl=name=valueTimezone=localβ maps to--tz localTmpfs=/workβ maps to--tmpfs /workUIDMap=0:10000:10β maps to--uidmap=0:10000:10Ulimit=nofile=1000:10000β maps to--ulimit nofile=1000:10000Unmask=ALLβ maps to--security-opt unmask=ALLUser=binβ maps to--user binUserNS=keep-id:uid=200,gid=210β maps to--userns keep-id:uid=200,gid=210Volume=/source:/destβ maps to--volume /source:/destWorkingDir=$HOMEβ maps to--workdir $HOME
π Description of [Container] section π
okay bestie, this is the main character section, so pay attention π here's every single key you can put in there:
AddCapability=
Adds these capabilities on top of the default Podman capability set that the container already gets. π«Ά
It's a space-separated list of capabilities, and you can list this key as many times as you want.
Like, for example:
AddCapability=CAP_DAC_OVERRIDE CAP_IPC_OWNER
AddDevice=
Pulls a device node from the host into the container. The format is HOST-DEVICE[:CONTAINER-DEVICE][:PERMISSIONS], where HOST-DEVICE is the path of the device node on the host, CONTAINER-DEVICE is the path of the device node in the container, and PERMISSIONS is a list of permissions combining r for read, w for write, and m for mknod(2).
And a - prefix? That tells Quadlet to add the device only if it actually exists on the host β¨
This key can be listed multiple times.
AddHost=
Drops a host-to-IP mapping into /etc/hosts. Format is hostname:ip.
Same energy as the Podman --add-host option. This key can be listed multiple times, no cap.
Annotation=
Sets one or more OCI annotations on the container. The format is a list of key=value items β think of it like Environment's cousin.
This key can be listed multiple times.
AppArmor=
Sets the AppArmor confinement profile for the container. And if you set it to unconfined, it literally turns AppArmor confinement off. π«’
AutoUpdate=
Tells you whether the container gets auto-updated (that's podman-auto-update(1), iykyk). These are the values it understands:
registryβ needs a fully-qualified image reference (like, e.g.,quay.io/podman/stable:latest) to create the container. This enforcement is genuinely necessary so Podman knows which image to actually check and pull. If you used an image ID instead? Podman has no idea which image to check/pull anymore, so like... yeah. πlocalβ tells Podman to compare the image a container is using to the image with its raw name in local storage. If an image got updated locally, Podman just restarts the systemd unit that runs the container. easy.
CgroupsMode=
The cgroups mode of the Podman container. Same thing as Podman's --cgroups option.
Important tho: by default, the cgroups mode of a container made by Quadlet is split, which is different from the default (enabled) that the Podman CLI uses. π
And if the container joins a pod (as in, Pod= is specified), you might wanna change this to no-conmon or enabled so that pod-level cgroup resource limits can actually take effect.
ContainerName=
The (optional) name of the Podman container. If you don't say anything, the default value systemd-%N is used β that's the same as the service name but with a systemd- prefix, so it doesn't beef with user-managed containers. π«Ά
ContainersConfModule=
Loads the containers.conf(5) module you point at. Equivalent to the Podman --module option.
This key can be listed multiple times.
DNS=
Sets a network-scoped DNS resolver/nameserver for containers in this network.
This key can be listed multiple times.
DNSOption=
Sets custom DNS options.
This key can be listed multiple times.
DNSSearch=
Sets custom DNS search domains. And if you want to remove the search domain? Use DNSSearch=. β iconic little trick. β¨
This key can be listed multiple times.
DropCapability=
Drops these capabilities from the default podman capability set β or all to drop literally every single capability.
Space-separated list of capabilities, and the key can be listed multiple times.
Like for example:
DropCapability=CAP_DAC_OVERRIDE CAP_IPC_OWNER
Entrypoint=
Overrides the default ENTRYPOINT from the image. Equivalent to the Podman --entrypoint option. If you've got multi-option commands, write them as a JSON string. π
Environment=
Sets an environment variable in the container. Uses the exact same format as services in systemd, and you can list it multiple times.
EnvironmentFile=
Uses a line-delimited file to set environment variables in the container. The path can be absolute or relative to wherever the unit file lives. This key can be used multiple times, and the order persists when it gets passed to podman run. π
EnvironmentHost=
Uses the host environment inside of the container.
Exec=
Extra arguments for the container β this has exactly the same effect as passing more arguments after a podman run <image> <arguments> invocation.
The format is the same as for systemd command lines. But heads up: unlike the usage scenario for the similarly-named systemd ExecStart= verb, which operates on the ambient root filesystem, container images very commonly have their own ENTRYPOINT or CMD metadata, and this is what Exec= interacts with. π¦
So like, most images ship with an ENTRYPOINT that already points at a default binary, and this field just sprinkles extra args on top of that. π«
Honestly? It's the same energy as the args field in a Kubernetes pod. If you know, you know. β¨
ExposeHostPort=β exposes a port β or a whole range of ports, like50-59β from the host into the container. Same thing as Podman's--expose. π«Ά You can list this key more than once, bestie.GIDMap=β runs the container in a brand new user namespace using the GID mapping you hand it. Equivalent to Podman's--gidmap. This key can be listed multiple times, no cap.GlobalArgs=β this one holds a list of arguments passed directly betweenpodmanandrunin the generated file. It's your escape hatch for Podman features the generator doesn't otherwise support. β οΈ But listen: since the generator has no idea what cursed interactions these args might cause, it is not recommended to use this option. Consider yourself warned, babe.
The format is a space-separated list of arguments, which you can optionally escape individually so you can sneak whitespace and other control characters in there. π
This key can be listed multiple times.
Group=β the (numeric) GID to run as inside the container. It doesn't have to match the GID on the host β that's whatUserNSis for β but if you don't specifyUserNS, then this GID gets used on the host too.
π Note: when you specify bothUser=andGroup=, they get smooshed into one single--user USER:GROUPargument handed to Podman. And usingGroup=withoutUser=? That's an error, periodt. π
GroupAdd=β assigns extra groups to the primary user running inside the container process. It also supports the specialkeep-groupsflag. Equivalent to Podman's--group-add.HealthCmd=β sets or alters the healthcheck command for a container. A value ofnonedisables any existing healthchecks. Equivalent to Podman's--health-cmd. π©ΊHealthInterval=β sets the interval for the healthchecks. An interval ofdisablemeans no automatic timer gets set up at all. Equivalent to Podman's--health-interval.HealthLogDestination=β sets the destination of the HealthCheck log. It takes a directory path,local, orevents_logger(localuses the container state file). Default islocal. Equivalent to Podman's--health-log-destination. πlocal: (default) HealthCheck logs are stored in overlay containers. (For example:$runroot/healthcheck.log)directory: creates a log file named<container-ID>-healthcheck.logwith HealthCheck logs in the directory you specify.events_logger: the log gets written with the logging mechanism set byevents_logger. It also saves the log to a default directory β which is a whole vibe on performance if you've got a system with a huge number of logs.
HealthMaxLogCount=β sets the maximum number of attempts in the HealthCheck log file. (a'0'value means an infinite number of attempts in the log file) (Default:5attempts) Equivalent to Podman's--Health-max-log-count.HealthMaxLogSize=β sets the maximum length in characters of the stored HealthCheck log. (a"0"value means an infinite log length) (Default:500characters) Equivalent to Podman's--Health-max-log-size.HealthOnFailure=β the action to take once the container transitions to an unhealthy state. The"kill"action in combination integrates best with systemd: once the container turns unhealthy it gets killed, and systemd restarts the service. Iconic teamwork honestly. π₯ Equivalent to Podman's--health-on-failure.HealthRetries=β the number of retries allowed before a healthcheck is considered unhealthy. Equivalent to Podman's--health-retries.HealthStartPeriod=β the initialization time a container needs to bootstrap itself. Equivalent to Podman's--health-start-period.HealthStartupCmd=β sets a startup healthcheck command for a container. Equivalent to Podman's--health-startup-cmd.HealthStartupInterval=β sets an interval for the startup healthcheck. An interval ofdisableresults in no automatic timer setup. Equivalent to Podman's--health-startup-interval.HealthStartupRetries=β the number of attempts allowed before the startup healthcheck restarts the container. Equivalent to Podman's--health-startup-retries.HealthStartupSuccess=β the number of successful runs required before the startup healthcheck succeeds and the regular healthcheck kicks in. Equivalent to Podman's--health-startup-success.HealthStartupTimeout=β the maximum time a startup healthcheck command has to complete before it's marked as failed. Equivalent to Podman's--health-startup-timeout.HealthTimeout=β the maximum time allowed to complete the healthcheck before an interval is considered failed. Equivalent to Podman's--health-timeout.HostName=β sets the host name that's available inside the container. Equivalent to Podman's--hostname. π·οΈHttpProxy=β controls whether proxy environment variables (http_proxy,https_proxy,ftp_proxy,no_proxy) get passed from the Podman process into the container during image pulls and builds.
Set it to true to enable proxy inheritance (that's the default Podman behavior) or false to disable it. This one is especially useful on systems that need proxy config to reach the internet but don't want those proxy settings leaking into the container runtime. Equivalent to Podman's --http-proxy. π
Image=β the image to run in the container. Highly recommend using a fully qualified image name instead of a short name β both for performance and for robustness reasons. Trust. π
The format of the name is the same as when you pass it to podman pull, so it supports :tag or digests to guarantee that specific image version. π
Special cases, bestie:
- If the name of the image ends with
.image, Quadlet uses the image pulled by the corresponding.imagefile, and the generated systemd service contains a dependency on the$name-image.service(or whatever service name is set in the.imagefile). Note that the corresponding.imagefile must exist. π«‘ - If the name of the image ends with
.build, Quadlet uses the image built by the corresponding.buildfile, and the generated systemd service contains a dependency on the$name-build.service. Note: the corresponding.buildfile must exist.
ImageVolume=β tells Podman how to handle the builtin image volumes. Default isbind. Equivalent to Podman's--image-volume.IP=β specify a static IPv4 address for the container, for example10.88.64.128. Equivalent to Podman's--ip.IP6=β specify a static IPv6 address for the container, for examplefd46:db93:aa76:ac37::10. Equivalent to Podman's--ip6. β¨Label=β sets one or more OCI labels on the container. The format is a list ofkey=valueitems, similar toEnvironment. π·οΈ
This key can be listed multiple times.
LogDriver=β sets the log-driver Podman uses when running the container. Equivalent to Podman's--log-driver.LogOpt=β sets the log-opt (logging options) Podman uses when running the container. Equivalent to Podman's--log-opt. This key can be listed multiple times.Mask=β specify the paths to mask, separated by a colon:Mask=/path/1:/path/2. A masked path cannot be accessed inside the container. πMemory=β specify the amount of memory for the container.Mount=β attaches a filesystem mount to the container. This is equivalent to Podman's--mountoption, and generally has the formtype=TYPE,TYPE-SPECIFIC-OPTION[,...].
Special cases:
- For
type=volume, ifsourceends with.volume, the Podman named volume generated by the corresponding.volumefile is used. - For
type=image, ifsourceends with.image, the image generated by the corresponding.imagefile is used.
In both those cases, the generated systemd service will contain a dependency on the service generated for the corresponding unit. Note: the corresponding .volume or .image file must exist. π«Ά
This key can be listed multiple times.
Network=β specify a custom network for the container. Same format as the--networkoption topodman run. For example, usehostto use the host network in the container, ornoneto not set up networking in the container at all. π
Special cases:
- If the name of the network ends with
.network, a Podman network calledsystemd-$nameis used, and the generated systemd service contains a dependency on the$name-network.service. A network like that can be automatically created by using a$name.networkQuadlet file. Note: the corresponding.networkfile must exist. - If the name ends with
.container, the container will reuse the network stack of another container created by$name.container. The generated systemd service contains a dependency on$name.service. Note: the corresponding.containerfile must exist.
This key can be listed multiple times.
NetworkAlias=β adds a network-scoped alias for the container. Same format as the--network-aliasoption topodman run. Aliases can group containers together in DNS resolution: for example, settingNetworkAlias=webon multiple containers makes a DNS query forwebresolve to all the containers rockin' that alias. πΈοΈ
This key can be listed multiple times.
NoNewPrivileges=(defaults tofalse) β if enabled, this disables container processes from gaining additional privileges via things like setuid and file capabilities. πNotify=(defaults tofalse) β by default, Podman is run in such a way that the systemd startup notify command is handled by the container runtime. In other words, the service is deemed started when the container runtime starts the child in the container. But! If the container application supportssd_notify, then settingNotifytotruepasses the notification details to the container, letting it notify of startup all on its own. main character energy, honestly. π
Also, setting Notify to healthy will postpone startup notifications until such time as the container is marked healthy, as determined by Podman healthchecks. Note that this requires setting up a container healthcheck β see the HealthCmd option for more. π©Ί
PidsLimit=β tunes the container's pids limit. This is equivalent to Podman's--pids-limit.Pod=β specify a Quadlet.podunit to link the container to. The value must take the form of<name>.podand the.podunit must exist. π«
Quadlet will add all the necessary parameters to link between the container and the pod, and between their corresponding services.
PodmanArgs=β a list of arguments that get passed straight to the end of thepodman runcommand in the generated file (right before the image name in the command line). It's your little backdoor into Podman features the generator doesn't support yet. But bestie, the generator has no idea what unexpected interactions your args might cause, so this one is not recommended π«£. Format: a space separated list of arguments, and you can optionally escape each one individually so you can sneak in whitespace and other control characters. Can be listed multiple times.PublishPort=β exposes a port, or a range of ports (e.g.50-59), from the container to the host. Equivalent to the Podman--publishoption. Format is similar to the Podman options, which goes likeip:hostPort:containerPort,ip::containerPort,hostPort:containerPortorcontainerPort, and the number of host and container ports must match (in the case of a range). You can slap the protocol on the end, e.g.hostPort:containerPort/tcp. Valid protocols aretcpandudp; thesctpprotocol is supported only for rootful containers. If the IP is set to0.0.0.0or not set at all, the port is bound on all IPv4 addresses on the host β use[::]for IPv6 π .
Heads up: not listing a host port means Podman automatically selects one, and it may be different for each invocation of the service. That makes it a less useful option, ngl. The allocated port can be found with the podman port command.
This key can be listed multiple times.
Pull=β sets the image pull policy. Equivalent to the Podman--pulloption β¨.ReadOnly=(defaults tofalse) β if enabled, makes the image read-only.ReadOnlyTmpfs=(defaults totrue) β ifReadOnlyis set totrue, mounts a read-writetmpfson/dev,/dev/shm,/run,/tmp, and/var/tmp.ReloadCmd=β adds anExecReloadline to theServicethat runspodman execwith this command in this container. To actually execute the reload, runsystemctl reload <Service>. Mutually exclusive withReloadSignalπ«.ReloadSignal=β adds anExecReloadline to theServicethat runspodman killwith this signal, which sends the signal to the main container process. To actually execute the reload, runsystemctl reload <Service>. Mutually exclusive withReloadCmdπ«.Retry=β number of times to retry the image pull when a HTTP error occurs. Equivalent to the Podman--retryoption.RetryDelay=β delay between retries. Equivalent to the Podman--retry-delayoption.Rootfs=β the rootfs to use for the container. Rootfs points to a directory on the system that contains the content to be run within the container. This option conflicts with theImageoption π¬.
The format of the rootfs is the same as when passed to podman run --rootfs, so it supports overlay mounts as well.
Note: on SELinux systems, the rootfs needs the correct label, which is by default unconfined_u:object_r:container_file_t:s0.
RunInit=(defaults tofalse) β if enabled, the container has a minimal init process inside the container that forwards signals and reaps processes. Cleanup crew energy π§Ή.SeccompProfile=β set the seccomp profile to use in the container. If unset, the default podman profile is used. Set it to either the pathname of a JSON file, orunconfinedto disable the seccomp filters.Secret=β use a Podman secret in the container either as a file or an environment variable. Equivalent to the Podman--secretoption and generally has the formsecret[,opt=opt ...].SecurityLabelDisable=β turn off label separation for the container.SecurityLabelFileType=β set the label file type for the container files.SecurityLabelLevel=β set the label process level for the container processes.SecurityLabelNested=β allowSecurityLabelsto function within the container. This allows separation of containers created within the container πͺ.SecurityLabelType=β set the label process type for the container processes.ServiceName=β by default, Quadlet names the systemd service unit using the name of the Quadlet. Setting this key overrides that behavior by instructing Quadlet to use the provided name instead.
Note: the name should not include the .service file extension.
ShmSize=β size of/dev/shm. Equivalent to the Podman--shm-sizeoption and generally has the formnumber[unit].StartWithPod=β start the container after the associated pod is created. Defaults totrue.
If true, the container will be started/stopped/restarted alongside the pod.
If false, the container will not be started when the pod starts. The container will be stopped with the pod. Restarting the pod will also restart the container as long as the container was also running before.
Note: the container can still be started manually or through a target by configuring the [Install] section. The pod will be started as needed in any case.
StopSignal=β signal to stop a container. Default isSIGTERM. Equivalent to the Podman--stop-signaloption.StopTimeout=β seconds to wait before forcibly stopping the container.
Note: this value should be lower than the actual systemd unit timeout to make sure the podman rm command is not killed by systemd π.
Equivalent to the Podman --stop-timeout option.
SubGIDMap=β run the container in a new user namespace using the map with name in the/etc/subgidfile. Equivalent to the Podman--subgidnameoption.SubUIDMap=β run the container in a new user namespace using the map with name in the/etc/subuidfile. Equivalent to the Podman--subuidnameoption.Sysctl=β configures namespaced kernel parameters for the container. The format isSysctl=name=value. This is a space separated list of kernel parameters. This key can be listed multiple times. For example:
Sysctl=net.ipv6.conf.all.disable_ipv6=1 net.ipv6.conf.all.use_tempaddr=1
Timezone=(if unset uses system-configured default) β the timezone to run the container in π°οΈ.Tmpfs=β mount atmpfsin the container. Equivalent to the Podman--tmpfsoption, and generally has the formCONTAINER-DIR[:OPTIONS]. This key can be listed multiple times.UIDMap=β run the container in a new user namespace using the supplied UID mapping. Equivalent to the Podman--uidmapoption. This key can be listed multiple times.Ulimit=β Ulimit options. Sets the ulimits values inside the container. This key can be listed multiple times.Unmask=β specify the paths to unmask, separated by a colon:unmask=ALLor/path/1:/path/2, or shell expanded paths (/proc/*). If set toALL, Podman will unmask all the paths that are masked or made read-only by default.
The default masked paths are /proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.
The default paths that are read-only are /proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup.
User=β the (numeric) UID to run as inside the container. This does not need to match the UID on the host, which can be modified withUserNS, but if that is not specified, this UID is also used on the host.
Note: when bothUser=andGroup=are specified, they are combined into a single--user USER:GROUPargument passed to Podman.
UserNS=β set the user namespace mode for the container. Equivalent to the Podman--usernsoption and generally has the formMODE[:OPTIONS,...].Volume=β mount a volume in the container. Equivalent to the Podman--volumeoption, and generally has the form[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]].
If SOURCE-VOLUME starts with ., Quadlet resolves the path relative to the location of the unit file π―.
Special case:
- If
SOURCE-VOLUMEends with.volume, a Podman named volume calledsystemd-$nameis used as the source, and the generated systemd service contains a dependency on the$name-volume.service. Note that the corresponding.volumefile must exist.
This key can be listed multiple times.
WorkingDir=β working directory inside the container. The default working directory for running binaries within a container is the root directory (/). The image developer can set a different default with theWORKDIRinstruction. This option overrides the working directory by using the-woption.
π« Pod units [Pod] π«
Pod units are named with a .pod extension and contain a [Pod] section describing the pod that is created and run as a service. The resulting service file contains a line like ExecStartPre=podman pod create β¦, and most of the keys in this section control the command-line options passed to Podman.
By default, the Podman pod has the same name as the unit, but with a systemd- prefix, i.e. a $name.pod file creates a $name-pod.service unit and a systemd-$name Podman pod. The PodName option allows for overriding this default name with a user-provided one β¨.
The generated service defaults to Restart=on-failure. Note that with ExitPolicy=stop (the default for Quadlet pods), the pod exits cleanly (exit code 0) when all its containers stop, so on-failure will not trigger a restart in that case. To have the pod automatically restart when containers exit, set Restart=always in the [Service] section of the .pod file π
.
Valid options for [Pod] are listed below:
Ok so here's the cheat sheet for how every [Pod] key lines up with the real podman pod create flag π
(left side = what you write in the unit, right side = what Quadlet turns it into, iykyk):
AddHost=example.com:192.168.10.11β--add-host example.com:192.168.10.11ContainersConfModule=/etc/nvd.confβ--module=/etc/nvd.confDNS=192.168.55.1β--dns=192.168.55.1DNSOption=ndots:1β--dns-option=ndots:1DNSSearch=example.comβ--dns-search example.comExitPolicy=stopβ--exit-policy stopGIDMap=0:10000:10β--gidmap=0:10000:10GlobalArgs=--log-level=debugβ--log-level=debugHostName=nameβ--hostname=nameIP=192.5.0.1β--ip 192.5.0.1IP6=2001:db8::1β--ip6 2001:db8::1Label="XYZ"β--label "XYZ"Network=hostβ--network hostNetworkAlias=nameβ--network-alias namePodmanArgs=--cpus=2β--cpus=2PodName=nameβ--name=namePublishPort=8080:80β--publish 8080:80ServiceName=nameβ Name the systemd unitname.serviceShmSize=100mβ--shm-size=100mStopTimeout=20β--time=20SubGIDMap=gtestβ--subgidname=gtestSubUIDMap=utestβ--subuidname=utestUIDMap=0:10000:10β--uidmap=0:10000:10UserNS=keep-id:uid=200,gid=210β--userns keep-id:uid=200,gid=210Volume=/source:/destβ--volume /source:/dest
π«Ά Supported keys in the [Pod] section
Ok bestie, here's every single key, what it does, and whether you can stack it. Let's go π
AddHost=
Adds a host-to-IP mapping into /etc/hosts. Format is hostname:ip. No cap, this is literally the same as the Podman --add-host option.
You can list this key multiple times π
ContainersConfModule=
Loads the containers.conf(5) module you point at. Same energy as the Podman --module option.
Also stackable β this key can be listed multiple times β¨
DNS=
Sets a network-scoped DNS resolver/nameserver for the containers inside this pod.
You guessed it: this key can be listed multiple times π¦
DNSOption=
Sets custom DNS options.
Multiple times, bestie π
DNSSearch=
Sets custom DNS search domains. Wanna nuke the search domain? Set DNSSearch=. and it's gone, iconic.
Can be listed multiple times πΈ
ExitPolicy=
Sets the exit policy of the pod for when the last container dips out. Default for quadlets is stop.
Want the pod to stay alive instead? Set ExitPolicy=continue. That's the whole vibe π
GIDMap=
Creates the pod inside a shiny new user namespace using the GID mapping you supply. Equivalent to the Podman --gidmap option.
Listable multiple times, fr fr β
GlobalArgs=
This one holds a list of arguments that get passed directly between podman and pod in the generated file. It's the escape hatch for reaching Podman features the generator otherwise doesn't support.
β οΈ Okay so real talk: since the generator has zero clue what kind of unhinged interactions these arguments might cause, using this option is not recommended. You've been warned π
The format is a space-separated list of arguments, and each one can optionally be individually escaped so you can sneak whitespace and other control characters in there.
This key can be listed multiple times π§
HostName=
Sets the pod's hostname inside all the containers. Cute, right?
That hostname also gets added to /etc/hosts using the container's primary IP address (peep the --add-host option too π).
Equivalent to the Podman --hostname option.
IP=
Pins a static IPv4 address for the pod, like 10.88.64.128. Equivalent to the Podman --ip option.
IP6=
Pins a static IPv6 address for the pod, like fd46:db93:aa76:ac37::10. Equivalent to the Podman --ip6 option.
Label=
Slaps one or more OCI labels on the pod. Format is a list of key=value items, same style as Environment.
Multiple times, always π
Network=
Points the pod at a custom network. Same format as the --network option to podman pod create. So like, use host to give the pod the host network, or none to not set up networking in the pod at all.
Special case, pay attention bestie:
- If the network name ends with
.network, Quadlet goes looking for the matching.networkQuadlet unit. If it finds one, Quadlet uses the name of theNetworkset in theUnitβ and if there isn't one, it falls back tosystemd-$name.
The generated systemd service gets a dependency on the service unit generated for that .network unit.
π Note: the corresponding .network file must exist.
This key can be listed multiple times π¦
NetworkAlias=β gives your pod a network-scoped alias, bestie. Same format as the--network-aliasoption topodman pod create. The whole point of aliases is grouping stuff together in DNS resolution β so like, if you setNetworkAlias=webon multiple containers, a DNS query forwebresolves to all the containers with that alias. iconic group-chat behavior tbh π
This key can be listed multiple times.
PodmanArgs=β this one is just a big list of arguments shoved directly onto the end of thepodman pod createcommand in the generated file. It's your backstage pass to Podman features the generator otherwise doesn't support. BUT β and I cannot stress this enough β the generator has zero clue what chaotic unexpected interactions these arguments might cause, so using this option is not recommended. π«£
The format is a space separated list of arguments, and you can optionally escape them individually so you can sneak in whitespace and other control characters.
This key can be listed multiple times.
PodName=β the (optional) name of the Podman pod. If you don't specify it, the default value is the same name as the unit, but with asystemd-prefix β so a$name.podfile creates asystemd-$namePodman pod, specifically to avoid conflicts with user-managed pods. β¨
Heads up though: pods and containers cannot have the same name. So if PodName is set, it must not conflict with any container. no cap.
PublishPort=β exposes a port, or a range of ports (e.g.50-59), from the pod to the host. Equivalent to the Podman--publishoption. The format is similar to the Podman options, which is of the formip:hostPort:containerPort,ip::containerPort,hostPort:containerPortorcontainerPortβ and the number of host and container ports must be the same (in the case of a range). You can slap the protocol at the end, e.g.,hostPort:containerPort/tcp. Valid protocols aretcpandudp; thesctpprotocol is supported only for rootful containers. π§
If the IP is set to 0.0.0.0 or not set at all, the port is bound on all IPv4 addresses on the host; use [::] for IPv6.
Note that not listing a host port means that Podman automatically selects one, and it may be different for each invocation of service. That makes it a less useful option, ngl. The allocated port can be found with the podman port command.
When using host networking via Network=host, the PublishPort= option cannot be used.
This key can be listed multiple times.
ServiceName=β by default, Quadlet will name the systemd service unit by appending-podto the name of the Quadlet. Setting this key overrides that behavior by instructing Quadlet to use the provided name instead. π
Note, the name should not include the .service file extension.
ShmSize=β size of/dev/shm. Equivalent to the Podman--shm-sizeoption and generally has the formnumber[unit].StopTimeout=β sets the time in seconds to wait for the pod to gracefully stop. This value is equivalent to the--timeargument in thepodman pod stopcommand when the service is stopped. After this period expires, any running containers in the pod are forcibly killed. π dramatic but necessary.SubGIDMap=β creates the pod in a new user namespace using the map with name in the/etc/subgidfile. Equivalent to the Podman--subgidnameoption.SubUIDMap=β creates the pod in a new user namespace using the map with name in the/etc/subuidfile. Equivalent to the Podman--subuidnameoption.UIDMap=β creates the pod in a new user namespace using the supplied UID mapping. Equivalent to the Podman--uidmapoption.
This key can be listed multiple times.
UserNS=β sets the user namespace mode for the pod. Equivalent to the Podman--usernsoption and generally has the formMODE[:OPTIONS,...].Volume=β mounts a volume in the pod. Equivalent to the Podman--volumeoption, and generally has the form[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]]. π
If SOURCE-VOLUME starts with ., Quadlet resolves the path relative to the location of the unit file.
Special case:
- If SOURCE-VOLUME ends with
.volume, Quadlet will look for the corresponding.volumeQuadlet unit. If found, Quadlet will use the name of the Volume set in the Unit, otherwise,systemd-$nameis used. Note: the corresponding.volumefile must exist.
The generated systemd service contains a dependency on the service unit generated for that .volume unit, or on $name-volume.service if the .volume unit is not found.
This key can be listed multiple times.
π Kube units [Kube]
Kube units are named with a .kube extension and contain a [Kube] section describing how podman kube play runs as a service. The resulting service file contains a line like ExecStart=podman kube play β¦ file.yml, and most of the keys in this section control the command-line options passed to Podman. However, some options also affect the details of how systemd is set up to run and interact with the container. it's giving very hands-on, love that for us. π
There is only one required key, Yaml, which defines the path to the Kubernetes YAML file. everything else is optional bestie, breathe.
Valid options for [Kube] are listed below:
Okay bestie, so before we get into the keys one by one β here's the cheat sheet of how every [Kube] key lines up with its podman kube play equivalent, because seeing them side by side is so much easier to remember π
AutoUpdate=registryβ--annotation "io.containers.autoupdate=registry"ConfigMap=/tmp/config.mapβ--config-map /tmp/config.mapContainersConfModule=/etc/nvd.confβ--module=/etc/nvd.confExitCodePropagation=howβ How to propagate container error statusGlobalArgs=--log-level=debugβ--log-level=debugKubeDownForce=trueβ--force(for podman kube down)LogDriver=journaldβ--log-driver journaldNetwork=hostβ--network hostPodmanArgs=--annotation=key=valueβ--annotation=key=valuePublishPort=8080:80β--publish 8080:80ServiceName=nameβ Name the systemd unitname.serviceSetWorkingDirectory=yamlβ SetWorkingDirectoryof unit file to location of the YAML fileUserNS=keep-id:uid=200,gid=210β--userns keep-id:uid=200,gid=210Yaml=/tmp/kube.yamlβpodman kube play /tmp/kube.yaml
Now the actual tea β β the supported keys in the [Kube] section are:
π AutoUpdate=
Tells you whether the containers get auto-updated (that's podman-auto-update(1) doing its thing β¨). And yup, you can drop AutoUpdate in there multiple times, she's flexible. Accepted values, bestie:
registryβ needs a fully-qualified image reference (likequay.io/podman/stable:latest) to create the container. This is literally required so Podman knows which images to actually check and pull. If you used an image ID instead, Podman has no idea which image to check/pull anymore. Sorry, them's the rules πlocalβ tells Podman to compare the image a container is using against the image with its raw name in local storage. If an image got updated locally, Podman just restarts the systemd unit running the Kubernetes Quadlet. Slay πname/(local|registry)β tells Podman to do thelocalorregistryautoupdate on the container name you specified.
π¦ ConfigMap=
Passes the Kubernetes ConfigMap YAML path over to podman kube play via the --configmap argument. Small plot twist though: unlike the configmap argument, this value can only hold one path β but that path can be absolute or relative to the location of the unit file. No cap π
This key may be used multiple times.
π§ ContainersConfModule=
Loads the containers.conf(5) module you point at. Equivalent to the Podman --module option. Iconic load order behaviour, honestly.
This key can be listed multiple times.
π ExitCodePropagation=
Controls how the main PID of the systemd service should exit. Values that get the green light:
allβ exits non-zero if all containers have failed (i.e., exited non-zero)anyβ exits non-zero if any container has failednoneβ exits zero and ignores failed containers
The current default value is none. That's the vibe rn π
π«Ά GlobalArgs=
This key holds a list of arguments that get passed directly between podman and kube in the generated file. It's your back door to Podman features the generator otherwise doesn't support. But real talk: since the generator has zero clue what unhinged interactions these arguments might cause, it is not recommended to use this option. You've been warned, bestie π
The format is a space separated list of arguments, which can optionally be individually escaped so you can sneak in whitespace and other control characters.
This key can be listed multiple times.
π KubeDownForce=
Removes all resources, including volumes, when you call podman kube down. Equivalent to the Podman --force option. Like, it's giving "burn it all down" energy β make sure that's what you actually want π₯
β LogDriver=
Sets the log-driver Podman uses when running the container. Equivalent to the Podman --log-driver option. Simple, clean, does what it says π
πΈ Network=
Specifies a custom network for the container. Same format as the --network option to podman kube play. For example, use host to use the host network in the container, or none to not set up networking in the container at all. Hermit mode π
Special case, pay attention:
- If the name of the network ends with
.network, a Podman network calledsystemd-$namegets used, and the generated systemd service contains a dependency on$name-network.service. You can get such a network auto-created by using a$name.networkQuadlet file. Note: the corresponding.networkfile must exist. No file, no network, no mercy π
This key can be listed multiple times.
π PodmanArgs=
This key holds a list of arguments passed directly to the end of the podman kube play command in the generated file (right before the path to the yaml file in the command line). It's how you reach Podman features the generator doesn't support on its own. But again β since the generator is unaware of what unexpected interactions these arguments can cause, it is not recommended to use this option. Same warning, same energy π
The format is a space separated list of arguments, which can optionally be individually escaped to allow inclusion of whitespace and other control characters.
This key can be listed multiple times.
π PublishPort=
Exposes a port β or a whole range of ports (e.g. 50-59) β from the container to the host. Equivalent to podman kube play's --publish option. The format is similar to the Podman options, which is of the form ip:hostPort:containerPort, ip::containerPort, hostPort:containerPort or containerPort, where the number of host and container ports must be the same (in the case of a range). You can tack the protocol on at the end, e.g. hostPort:containerPort/tcp. Valid protocols are tcp and udp; the sctp protocol is supported only for rootful containers. Rootful girlies only for that one π«Ά
If the IP is set to 0.0.0.0 or not set at all, the port is bound on all IPv4 addresses on the host; use [::] for IPv6.
The list of published ports specified in the unit file is merged with the list of ports specified in the Kubernetes YAML file. If the same container port and protocol shows up in both, the entry from the unit file takes precedence. Unit file stays winning π
This key can be listed multiple times.
ServiceName=β lowkey one of the handiest keys ever π by default Quadlet names the systemd service unit after the Quadlet itself, but set this and you get to choose the name instead. Main character behavior, honestly.
Heads up bestie: the name should not include the .service file extension, ok?
SetWorkingDirectory=β this sets theWorkingDirectoryfield of theServicegroup in the systemd service unit file. Why do you care? Because it letspodman kube playactually resolve relative paths correctly π Supported values areyamlandunit, which set the working directory to that of the YAML file or the Quadlet unit file respectively.
Alternatively, you can just explicitly set the WorkingDirectory field of the Service group in the .kube file yourself, no cap. But like β please note that if the WorkingDirectory field of the Service group is set, Quadlet will not set it, even if SetWorkingDirectory is set. It respects your choices, periodt.
Special case: if multiple YAML paths are provided, only unit is supported. π
UserNS=β sets the user namespace mode for the container. This is equivalent to the Podman--usernsoption and generally has the formMODE[:OPTIONS,...].Yaml=β the path to the Kubernetes YAML file to use. Can be absolute, or relative to the location of the unit file.
This key can be listed multiple times. β¨
πΈοΈ Network units [Network] πΈοΈ
Network files are named with a .network extension and contain a section [Network] describing the named Podman network. The generated service is a one-time command that makes sure the network exists on the host, creating it if needed. It's giving "set it and forget it" energy, fr fr.
By default, the Podman network has the same name as the unit, but with a systemd- prefix β so for a network file named $NAME.network, the generated Podman network is called systemd-$NAME, and the generated service file is $NAME-network.service. The NetworkName option lets you override this default name with one you provide yourself π
So here's the thing about updating network parameters: you will first need to manually remove the podman network and then restart the service. Set NetworkDeleteOnStop=true to override that behavior and delete the network when the device is stopped. Obsessed with a clean exit tbh.
Using network units lets containers depend on networks being automatically pre-created. This is particularly interesting when you're using special options to control network creation, because Podman otherwise creates networks with the default options. iykyk.
Valid options for [Network] are listed below β here's the whole glow-up chart of "[Network] option β‘οΈ podman network create equivalent":
ContainersConfModule=/etc/nvd.confβ‘οΈ--module=/etc/nvd.confDisableDNS=trueβ‘οΈ--disable-dnsDNS=192.168.55.1β‘οΈ--dns=192.168.55.1Driver=bridgeβ‘οΈ--driver bridgeGateway=192.168.55.3β‘οΈ--gateway 192.168.55.3GlobalArgs=--log-level=debugβ‘οΈ--log-level=debugInterfaceName=enp1β‘οΈ--interface-name enp1Internal=trueβ‘οΈ--internalIPAMDriver=dhcpβ‘οΈ--ipam-driver dhcpIPRange=192.168.55.128/25β‘οΈ--ip-range 192.168.55.128/25IPv6=trueβ‘οΈ--ipv6Label="XYZ"β‘οΈ--label "XYZ"NetworkDeleteOnStop=trueβ‘οΈ AddExecStopPostto delete the network when the unit is stoppedNetworkName=fooβ‘οΈpodman network create fooOptions=isolate=trueβ‘οΈ--opt isolate=truePodmanArgs=--dns=192.168.55.1β‘οΈ--dns=192.168.55.1ServiceName=nameβ‘οΈ Name the systemd unitname.serviceSubnet=192.5.0.0/16β‘οΈ--subnet 192.5.0.0/16
Supported keys in the [Network] section are:
π« ContainersConfModule=
Load the specified containers.conf(5) module. Equivalent to the Podman --module option.
This key can be listed multiple times. π
π« DisableDNS= (defaults to false)
If enabled, disables the DNS plugin for this network.
This is equivalent to the Podman --disable-dns option.
π« DNS=
Set network-scoped DNS resolver/nameserver for containers in this network.
This key can be listed multiple times.
π« Driver= (defaults to bridge)
Driver to manage the network. Currently bridge, macvlan and ipvlan are supported.
This is equivalent to the Podman --driver option.
π« Gateway=
Define a gateway for the subnet. If you want to provide a gateway address, you must also provide a subnet option β they're a package deal, bestie π«Ά
This is equivalent to the Podman --gateway option.
This key can be listed multiple times.
π« GlobalArgs=
This key contains a list of arguments passed directly between podman and network in the generated file. It can be used to access Podman features otherwise unsupported by the generator. But β since the generator is completely unaware of what unexpected interactions these arguments can cause, it is not recommended to use this option. π It's giving "do it if you must, but don't come crying to me."
The format of this is a space separated list of arguments, which can optionally be individually escaped to allow inclusion of whitespace and other control characters.
This key can be listed multiple times.
π« InterfaceName=
This option maps the network_interface option in the network config, see podman network inspect. Depending on the driver, this can have different effects: for bridge, it uses the bridge interface name. For macvlan and ipvlan, it is the parent device on the host. It is the same as --opt parent=....
This is equivalent to the Podman --interface-name option.
π« Internal= (defaults to false)
Restrict external access of this network. β¨
This is equivalent to the Podman --internal option.
π« IPAMDriver=
Set the ipam driver (IP Address Management Driver) for the network. Currently host-local, dhcp and none are supported.
This is equivalent to the Podman --ipam-driver option.
π« IPRange=
Allocate container IP from a range. The range must be either a complete subnet in CIDR notation, or be in the <startIP>-<endIP> syntax, which allows for a more flexible range compared to the CIDR subnet. The ip-range option must be used with a subnet option.
This is equivalent to the Podman --ip-range option.
This key can be listed multiple times.
π« IPv6=
Enable IPv6 (Dual Stack) networking.
This is equivalent to the Podman --ipv6 option.
π·οΈ Label=
Sets one or more OCI labels on the network, bestie. The format is a list of key=value items β similar to Environment, iykyk. π
This key can be listed multiple times. β¨
π NetworkDeleteOnStop= (defaults to false)
Set it to true and the network gets deleted when the service is stopped. That's literally it. Poof. Gone. No cap. π
π NetworkName=
The (optional) name of the Podman network. If you don't specify it, the default is the same name as the unit β but with a systemd- prefix π«Ά. So like, a $name.network file creates a systemd-$name Podman network, and the whole reason is to avoid conflicts with user-managed network. Iconic behaviour, honestly. π
πΈ Options=
Set driver specific options.
This is equivalent to the Podman --opt option.
π PodmanArgs=
This key contains a list of arguments passed directly to the end of the podman network create command in the generated file (right before the name of the network in the command line). It can be used to access Podman features otherwise unsupported by the generator.
ok so listen β since the generator is unaware of what unexpected interactions can be caused by these arguments, it is not recommended to use this option. fr fr, be careful. π¨
The format of this is a space separated list of arguments, which can optionally be individually escaped to allow inclusion of whitespace and other control characters.
This key can be listed multiple times. β
π¦ ServiceName=
By default, Quadlet will name the systemd service unit by appending -network to the name of the Quadlet. Setting this key overrides this behavior by instructing Quadlet to use the provided name you gave it. π
Note, the name should not include the .service file extension.
π Subnet=
The subnet in CIDR notation. That's the vibe check. β¨
This is equivalent to the Podman --subnet option.
This key can be listed multiple times. π₯
πΎ Volume units [Volume] πΎ
Volume files are named with the .volume extension and contain a section [Volume] that describes the named Podman volume. The generated service is a one-time command that makes sure the volume exists on the host, creating it if needed. π
By default, the Podman volume has the same name as the unit, but with a systemd- prefix. So for a volume file named $NAME.volume, the generated Podman volume is called systemd-$NAME, and the generated service file is $NAME-volume.service. The VolumeName option lets you override this default name with a user-provided one. β¨
Using volume units lets containers depend on volumes being automatically pre-created. This is especially interesting when youβre using special options to control volume creation, because Podman otherwise creates volumes with the default options. π«Ά
Valid options for [Volume] are listed below. Mapping time, bestie β hereβs the [Volume] option to podman volume create equivalent glow-up: π
ContainersConfModule=/etc/nvd.confβ--module=/etc/nvd.confCopy=trueβ--opt copyDevice=tmpfsβ--opt device=tmpfsDriver=imageβ--driver=imageGID=5678β--gid 5678GlobalArgs=--log-level=debugβ--log-level=debugGroup=192β--opt "o=group=192"Image=quay.io/centos/centos:latestβ--opt image=quay.io/centos/centos:latestLabel="foo=bar"β--label "foo=bar"Options=XYZβ--opt "o=XYZ"PodmanArgs=--driver=imageβ--driver=imageServiceName=nameβ Name the systemd unitname.serviceType=typeβ Filesystem type ofDeviceUID=1234β--uid 1234User=123β--opt "o=uid=123"VolumeName=fooβpodman volume create foo
Supported keys in the [Volume] section are: πΈ
ContainersConfModule= π§
Load the specified containers.conf(5) module. Equivalent to the Podman --module option.
This key can be listed multiple times.
Copy= (default to true) π
If enabled, the content of the image located at the mountpoint of the volume is copied into the volume on the first run.
Device= π
The path of a device which is mounted for the volume.
Driver= π₯
Specify the volume driver name. When set to image, the Image key must also be set.
This is equivalent to the Podman --driver option.
GID= π
The GID that the volume will be created as. Differently than Group=, the specified value is not passed to the mount operation. The specified GID will own the volume's mount point directory and affects the volume chown operation.
GlobalArgs= π
This key contains a list of arguments passed directly between podman and volume in the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware of what unexpected interactions can be caused by these arguments, it is not recommended to use this option.
The format of this is a space separated list of arguments, which can optionally be individually escaped to allow inclusion of whitespace and other control characters.
This key can be listed multiple times.
Group= πΈ
The host (numeric) GID, or group name to use as the group for the volume. Differently than GID, the specified value is passed to the mount operation.
Image= π¦
Specifies the image the volume is based on when Driver is set to the image. It is recommended to use a fully qualified image name rather than a short name, both for performance and robustness reasons.
The format of the name is the same as when passed to podman pull. So, it supports using :tag or digests to guarantee the specific image version.
Special case:
- If the name of the image ends with
.image, Quadlet will use the image pulled by the corresponding.imagefile, and the generated systemd service contains a dependency on the$name-image.service(or the service name set in the.imagefile). Note: the corresponding.imagefile must exist.
Label= π·οΈ
Set one or more OCI labels on the volume. The format is a list of key=value items, similar to Environment.
This key can be listed multiple times.
Options= βοΈ
The mount options to use for a filesystem as used by the mount(8) command -o option.
PodmanArgs= π
This key contains a list of arguments passed directly to the end of the podman volume create command in the generated file (right before the name of the volume in the command line). It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware of what unexpected interactions can be caused by these arguments, it is not recommended to use this option.
The format of this is a space separated list of arguments, which can optionally be individually escaped to allow inclusion of whitespace and other control characters.
This key can be listed multiple times.
ServiceName= β¨
By default, Quadlet will name the systemd service unit by appending -volume to the name of the Quadlet. Setting this key overrides this behavior by instructing Quadlet to use the provided name.
Note, the name should not include the .service file extension.
Type= π§
The filesystem type of Device as used by the mount(8) commands -t option.
UID= π
The UID that the volume will be created as. Differently than User, the specified value is not passed to the mount operation. The specified UID will own the volume's mount point directory and affects the volume chown operation.
User= π
The host (numeric) UID, or user name to use as the owner for the volume. Differently than UID, the specified value is passed to the mount operation.
VolumeName= π
The (optional) name of the Podman volume. If this is not specified, the default value is the same name as the unit, but with a systemd- prefix, i.e. a $name.volume file creates a systemd-$name Podman volume to avoid conflicts with user-managed volumes.
π οΈ Build units [Build] π οΈ
Build files are named with a .build extension and contain a section [Build] describing the image build command. The generated service is a one-time command that ensures that the image is built on the host from a supplied Containerfile and context directory. Subsequent (re-)starts of the generated built service will usually finish quickly, as image layer caching will skip unchanged build steps. π₯
A minimal .build unit needs at least the ImageTag= key, and either of File= or SetWorkingDirectory= keys. π
These build units are how you make containers and volumes depend on images that get built locally β which is so useful when you want to create container images that aren't up on any container registry, or when you're just doing local testing and development. Main character behavior, honestly. π
Valid options for [Build] are listed below β every single one, mapped to its podman build equivalent, no cap:
Annotation=annotation=valueβ becomes--annotation=annotation=valueArch=aarch64β becomes--arch=aarch64AuthFile=/etc/registry/auth.jsonβ becomes--authfile=/etc/registry/auth.jsonBuildArg=foo=barβ becomes--build-arg foo=barContainersConfModule=/etc/nvd.confβ becomes--module=/etc/nvd.confDNS=192.168.55.1β becomes--dns=192.168.55.1DNSOption=ndots:1β becomes--dns-option=ndots:1DNSSearch=example.comβ becomes--dns-search example.comEnvironment=foo=barβ becomes--env foo=barFile=/path/to/Containerfileβ becomes--file=/path/to/ContainerfileForceRM=falseβ becomes--force-rm=falseGlobalArgs=--log-level=debugβ becomes--log-level=debugGroupAdd=keep-groupsβ becomes--group-add=keep-groupsIgnoreFile=/path/to/.customignoreβ becomes--ignorefile=/path/to/.customignoreImageTag=localhost/imagenameβ becomes--tag=localhost/imagenameLabel=labelβ becomes--label=labelNetwork=hostβ becomes--network=hostPodmanArgs=--pull neverβ becomes--pull neverPull=neverβ becomes--pull neverRetry=5β becomes--retry=5RetryDelay=10sβ becomes--retry-delay=10sSecret=secretβ becomes--secret=id=mysecret,src=pathServiceName=nameβ names the systemd unitname.serviceSetWorkingDirectory=unitβ sets theWorkingDirectoryof the systemd unit fileTarget=my-appβ becomes--target=my-appTLSVerify=falseβ becomes--tls-verify=falseVariant=arm/v7β becomes--variant=arm/v7Volume=/source:/destβ becomes--volume /source:/dest
Annotation=
Adds an image annotation (like annotation=value) to the image metadata. You can use it as many times as you want, bestie β stack 'em up. β¨
This is equivalent to the --annotation option of podman build.
Arch=
Overrides the architecture of the image you're building. Defaults to the host's architecture, iykyk.
This is equivalent to the --arch option of podman build.
AuthFile=
Path of the authentication file. That's it, that's the vibe. π
This is equivalent to the --authfile option of podman build.
BuildArg=
Specifies a build argument and its value in the same way environment variables are written (e.g., env=value), but heads up β it is not added to the environment variable list in the resulting image's configuration. Can be listed multiple times, so go off. π
This is equivalent to the --build-arg option of podman build.
ContainersConfModule=
Loads the specified containers.conf(5) module. Equivalent to the Podman --module option.
This key can be listed multiple times.
DNS=
Sets a network-scoped DNS resolver/nameserver for the build container. Literally telling your build where to look stuff up. π
This key can be listed multiple times.
This is equivalent to the --dns option of podman build.
DNSOption=
Sets custom DNS options. Fancy.
This key can be listed multiple times.
This is equivalent to the --dns-option option of podman build.
DNSSearch=β Set custom DNS search domains. UseDNSSearch=.to remove the search domain. This key can be listed multiple times. This is equivalent to the--dns-searchoption ofpodman build.Environment=β Add a value (e.g.env=value) to the built image. This uses the same format as services in systemd β the docs are athttps://www.freedesktop.org/software/systemd/man/systemd.exec.html#Environment=β and can be listed multiple times.File=β Specifies aContainerfilewhich contains instructions for building the image. A URL starting withhttp(s)://allows you to specify a remoteContainerfileto be downloaded. Note that for a given relative path to aContainerfile, or when using ahttp(s)://URL, you also must setSetWorkingDirectory=in order forpodman buildto find a valid context directory for the resources specified in theContainerfile. Note that setting aFile=field is mandatory for a.buildfile, unlessSetWorkingDirectory(or aWorkingDirectoryin theServicegroup) has also been set. This is equivalent to the--fileoption ofpodman build.ForceRM=β Always remove intermediate containers after a build, even if the build fails (defaulttrue). This is equivalent to the--force-rmoption ofpodman build.GlobalArgs=β This key contains a list of arguments passed directly betweenpodmanandbuildin the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware of what unexpected interactions can be caused by these arguments, it is not recommended to use this option. The format of this is a space separated list of arguments, which can optionally be individually escaped to allow inclusion of whitespace and other control characters. This key can be listed multiple times.GroupAdd=β Assign additional groups to the primary user running within the container process. Also supports thekeep-groupsspecial flag. This is equivalent to the--group-addoption ofpodman build.IgnoreFile=β Path to an alternate.containerignorefile to use when building the image. Note that when using a relative path you should also setSetWorkingDirectory=. This is equivalent to the--ignorefileoption ofpodman build.ImageTag=β Specifies the name which is assigned to the resulting image if the build process completes successfully. This is equivalent to the--tagoption ofpodman build. This key can be listed multiple times. The first instance will be used as the name of the created artifact when the.buildfile is referenced by another Quadlet unit.Label=β Add an image label (e.g.label=value) to the image metadata. Can be used multiple times. This is equivalent to the--labeloption ofpodman build.Network=β Sets the configuration for network namespaces when handlingRUNinstructions. This has the same format as the--networkoption topodman build. For example, usehostto use the host network, ornoneto not set up networking.
Special case:
- If the name of the network ends with
.network, Quadlet will look for the corresponding.networkQuadlet unit. If found, Quadlet will use the name of the Network set in theUnit, otherwise,systemd-$nameis used. The generated systemd service contains a dependency on the service unit generated for that.networkunit, or on$name-network.serviceif the.networkunit is not found. Note: the corresponding.networkfile must exist.
This key can be listed multiple times.
PodmanArgs=β This key contains a list of arguments passed directly to the end of thepodman buildcommand in the generated file (right before the image name in the command line). It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware of what unexpected interactions can be caused by these arguments, it is not recommended to use this option. The format of this is a space separated list of arguments, which can optionally be individually escaped to allow inclusion of whitespace and other control characters. This key can be listed multiple times.Pull=β Set the image pull policy. This is equivalent to the--pulloption ofpodman build.Retry=β Number of times to retry the image pull when a HTTP error occurs. Equivalent to the Podman--retryoption.RetryDelay=β Delay between retries. Equivalent to the Podman--retry-delayoption.Secret=β Pass secret information used inContainerfilebuild stages in a safe way. This is equivalent to the--secretoption ofpodman buildand generally has the formsecret[,opt=opt ...].ServiceName=β By default, Quadlet will name the systemd service unit by appending-buildto the name of the Quadlet. Setting this key overrides this behavior by instructing Quadlet to use the provided name. Note, the name should not include the.servicefile extension.SetWorkingDirectory=β Provide context (a working directory) topodman build. Supported values are a path, a URL, or the special keysfileorunitto set the context directory to the parent directory of the file from theFile=key or to that of the Quadlet.buildunit file, respectively. This allows Quadlet to resolve relative paths. When using one of the special keys (fileorunit), theWorkingDirectoryfield of theServicegroup of the Systemd service unit will also be set accordingly. Alternatively, users can explicitly set theWorkingDirectoryfield of theServicegroup in the.buildfile. Please note that if theWorkingDirectoryfield of theServicegroup is set by the user, Quadlet will not overwrite it even ifSetWorkingDirectoryis set tofileorunit. By providing a URL toSetWorkingDirectory=you can instructpodman buildto clone a Git repository or download an archive file extracted to a temporary location bypodman buildas build context. Note that in this case, theWorkingDirectoryof the Systemd service unit is left untouched by Quadlet. Note that providing context directory is mandatory for a.buildfile, unless aFile=key has also been provided.Target=β Set the target build stage to build. Commands in theContainerfileafter the target stage are skipped. This is equivalent to the--targetoption ofpodman build.TLSVerify=β Require HTTPS and verification of certificates when contacting registries. This is equivalent to the--tls-verifyoption ofpodman build.Variant=β Override the default architecture variant of the container image to be built. This is equivalent to the--variantoption ofpodman build.Volume=β Mount a volume to containers when executingRUNinstructions during the build. This is equivalent to the--volumeoption ofpodman build, and generally has the form[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]]. IfSOURCE-VOLUMEstarts with., Quadlet resolves the path relative to the location of the unit file.
Special case:
- If
SOURCE-VOLUMEends with.volume, Quadlet will look for the corresponding.volumeQuadlet unit. If found, Quadlet will use the name of the Volume set in theUnit, otherwise,systemd-$nameis used. The generated systemd service contains a dependency on the service unit generated for that.volumeunit, or on$name-volume.serviceif the.volumeunit is not found. Note: the corresponding.volumefile must exist.
This key can be listed multiple times.
π¦ Image units [Image] π¦
Image files are named with a .image extension and contain a section [Image] describing the container image pull command. The generated service is a one-time command that ensures that the image exists on the host, pulling it if needed.
Using image units allows containers and volumes to depend on images being automatically pulled. This is particularly interesting when using special options to control image pulls.
Valid options for [Image] are listed below:
π [Image] options β podman image pull mapping
okay bestie, hereβs the [Image] key-to-podman image pull pipeline, no cap: left side is the Quadlet key, right side is what it maps to. β¨
AllTags=trueβ--all-tagsArch=aarch64β--arch=aarch64AuthFile=/etc/registry/auth.jsonβ--authfile=/etc/registry/auth.jsonCertDir=/etc/registry/certsβ--cert-dir=/etc/registry/certsContainersConfModule=/etc/nvd.confβ--module=/etc/nvd.confCreds=myname:mypasswordβ--creds=myname:mypasswordDecryptionKey=/etc/registry.keyβ--decryption-key=/etc/registry.keyGlobalArgs=--log-level=debugβ--log-level=debugImage=quay.io/centos/centos:latestβpodman image pull quay.io/centos/centos:latestImageTag=quay.io/centos/centos:latestβ use this name when resolving.imagereferencesOS=windowsβ--os=windowsPodmanArgs=--os=linuxβ--os=linuxPolicy=alwaysβ--policy=alwaysRetry=5β--retry=5RetryDelay=10sβ--retry-delay=10sServiceName=nameβ names the systemd unitname.serviceTLSVerify=falseβ--tls-verify=falseVariant=arm/v7β--variant=arm/v7
πΈ AllTags=
Every tagged image in the repository gets pulled. This is equivalent to Podmanβs --all-tags option. π·οΈ
π¦ Arch=
Override the architecture of the image to be pulled; if you donβt, it defaults to the hostβs architecture. This is equivalent to Podmanβs --arch option. ποΈ
π AuthFile=
Path of the authentication file. This is equivalent to Podmanβs --authfile option. π
β¨ CertDir=
Use certificates at the given path β (*.crt, *.cert, *.key) β to connect to the registry. This is equivalent to Podmanβs --cert-dir option. π§
π ContainersConfModule=
Load the containers.conf(5) module you specify. This is equivalent to Podmanβs --module option.
This key can be listed multiple times. π«Ά
π Creds=
The [username[:password]] to use when authenticating with the registry, if required. This is equivalent to Podmanβs --creds option. π
π DecryptionKey=
The [key[:passphrase]] to be used for decryption of images. This is equivalent to Podmanβs --decryption-key option. π
π GlobalArgs=
This key contains a list of arguments passed directly between podman and image in the generated file. It can be used to access Podman features that the generator otherwise doesnβt support.
Since the generator is unaware of what unexpected interactions these arguments can cause, it is not recommended to use this option.
The format is a space separated list of arguments, which can optionally be individually escaped to allow inclusion of whitespace and other control characters.
This key can be listed multiple times. π
πΌοΈ Image=
The image to pull. It is recommended to use a fully qualified image name rather than a short name β both for performance and robustness reasons.
The format of the name is the same as when passed to podman pull. So it supports using :tag or digests to guarantee the specific image version. π
π§ ImageTag=
The actual FQIN of the referenced Image. Only meaningful when the source is a file or directory archive.
For example, an image saved into a docker-archive with the following Podman command:
podman image save --format docker-archive --output /tmp/archive-file.tar quay.io/podman/stable:latest
requires setting:
Image=docker-archive:/tmp/archive-file.tarImageTag=quay.io/podman/stable:latest
π OS=
Override the OS of the image to be pulled; if you donβt, it defaults to the hostβs OS. This is equivalent to Podmanβs --os option. πΊοΈ
π PodmanArgs=
This key contains a list of arguments passed directly to the end of the podman image pull command in the generated file β right before the image name in the command line. It can be used to access Podman features that the generator otherwise doesnβt support.
Since the generator is unaware of what unexpected interactions these arguments can cause, it is not recommended to use this option.
The format is a space separated list of arguments, which can optionally be individually escaped to allow inclusion of whitespace and other control characters.
This key can be listed multiple times. π
π Policy=
The pull policy to use when pulling the image. This is equivalent to Podmanβs --policy option. π―
π Retry=
Number of times to retry the image pull when an HTTP error occurs. This is equivalent to Podmanβs --retry option. β°
β³ RetryDelay=
Delay between retries. This is equivalent to Podmanβs --retry-delay option. π°οΈ
π·οΈ ServiceName=
By default, Quadlet will name the systemd service unit by appending -image to the name of the Quadlet. Setting this key overrides this behavior by instructing Quadlet to use the provided name.
Note: the name should not include the .service file extension. π
π TLSVerify=
Require HTTPS and verification of certificates when contacting registries. This is equivalent to Podmanβs --tls-verify option. π‘οΈ
𧬠Variant=
Override the default architecture variant of the container image. This is equivalent to Podmanβs --variant option. π±
π§Έ Artifact units [Artifact]
β οΈ WARNING: Experimental Unit β οΈ
bestie, this unit is considered experimental and still in development. Inputs, options, and outputs are all subject to change. no cap, tread carefully π
Artifact units are named with a .artifact extension and contain a [Artifact] section describing the container artifact pull command. The generated service is a one-time command that ensures that the artifact exists on the host, pulling it if needed.
Using artifact units allows containers to depend on artifacts being automatically pulled. This is particularly useful for managing artifacts that containers need to mount or access. The Artifact key is mandatory inside of the [Artifact] unit.
Valid options for [Artifact] are listed below β here's the cheat-sheet mapping, because we love a clear vibe check π«Ά
Artifact=quay.io/foobar/artifact:specialβpodman artifact pull quay.io/foobar/artifact:specialAuthFile=/etc/registry/auth.jsonβ--authfile=/etc/registry/auth.jsonCertDir=/etc/registry/certsβ--cert-dir=/etc/registry/certsContainersConfModule=/etc/nvd.confβ--module=/etc/nvd.confCreds=username:passwordβ--creds=username:passwordDecryptionKey=/etc/registry.keyβ--decryption-key=/etc/registry.keyGlobalArgs=--log-level=debugβ--log-level=debugPodmanArgs=--pull neverβ--pull neverQuiet=trueβ--quietRetry=5β--retry=5RetryDelay=10sβ--retry-delay=10sServiceName=my-artifactβ Set the systemd service name tomy-artifact.serviceTLSVerify=falseβ--tls-verify=false
π Artifact=
The artifact to pull from a registry onto the local machine. This is the only required key for artifact units.
It is required to use a fully qualified artifact name rather than a short name, both for performance and robustness reasons. periodt, use the whole name β¨
π AuthFile=
Path of the authentication file.
This is equivalent to the Podman --authfile option.
π CertDir=
Use certificates at path (*.crt, *.cert, *.key) to connect to the registry.
This is equivalent to the Podman --cert-dir option.
π ContainersConfModule=
Load the specified containers.conf(5) module. Equivalent to the Podman --module option.
This key can be listed multiple times. yes bestie, stack 'em πΈ
π Creds=
The credentials to use when contacting the registry in the format [username[:password]].
This is equivalent to the Podman --creds option.
π DecryptionKey=
The [key[:passphrase]] to be used for decryption of artifacts.
This is equivalent to the Podman --decryption-key option.
π GlobalArgs=
This key contains a list of arguments passed directly between podman and artifact in the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware of what unexpected interactions can be caused by these arguments, it is not recommended to use this option.
The format of this is a space separated list of arguments, which can optionally be individually escaped to allow inclusion of whitespace and other control characters.
This key can be listed multiple times.
ngl, this one is giving βI know what I'm doingβ energy β but the manpage literally says it's not recommended, so don't come for me if it gets weird π
π PodmanArgs=
This key contains a list of arguments passed directly to the end of the podman artifact pull command in the generated file (right before the artifact name in the command line). It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware of what unexpected interactions can be caused by these arguments, it is not recommended to use this option.
The format of this is a space separated list of arguments, which can optionally be individually escaped to allow inclusion of whitespace and other control characters.
This key can be listed multiple times.
π Quiet=
Suppress output information when pulling artifacts.
This is equivalent to the Podman --quiet option.
π Retry=
Number of times to retry the artifact pull when a HTTP error occurs. Equivalent to the Podman --retry option.
π RetryDelay=
Delay between retries. Equivalent to the Podman --retry-delay option.
π ServiceName=
The (optional) name of the systemd service. If this is not specified, the default value is the same name as the unit, but with a -artifact suffix, i.e. a $name.artifact file creates a $name-artifact.service systemd service.
π TLSVerify=
Require HTTPS and verification of certificates when contacting registries.
This is equivalent to the Podman --tls-verify option.
πͺ Quadlet section [Quadlet]
Some quadlet specific configuration is shared between different unit types. Those settings can be configured in the [Quadlet] section.
Valid options for [Quadlet] are listed below:
DefaultDependencies=falseβ Disable implicit network dependencies to the unit
π DefaultDependencies=
Add Quadlet's default network dependencies to the unit (default is true).
When set to false, Quadlet will not add a dependency (After=, Wants=) to network-online.target/podman-user-wait-network-online.service to the generated unit.
Note, this option is set in the [Quadlet] section. The systemd [Unit] section has an option with the same name but a different meaning. iykyk, don't mix them up π
π EXAMPLES π
Okay bestie, this is the part you actually came for β the examples. Grab a snack π, we're going shopping.
π Example test.container
The classic. A minimal container unit, serving looks:
[Unit]
Description=A minimal container
[Container]
# Use the centos image
Image=quay.io/centos/centos:latest
# Use volume and network defined below
Volume=test.volume:/data
Network=test.network
# In the container we just run sleep
Exec=sleep 60
[Service]
# Restart service when sleep finishes
Restart=always
# Extend Timeout to allow time to pull the image
TimeoutStartSec=900
# ExecStartPre flag and other systemd commands can go here, see systemd.unit(5) man page.
ExecStartPre=/usr/share/mincontainer/setup.sh
[Install]
# Start by default on boot
WantedBy=multi-user.target default.target
Notice the [Container] section pulling the quay.io/centos/centos:latest image, wiring up the test.volume volume and the test.network network from the examples lower down π
, and then just vibing with Exec=sleep 60. Then [Service] does its systemd thing β Restart=always, TimeoutStartSec=900 so the image pull has room to breathe, and an ExecStartPre=/usr/share/mincontainer/setup.sh hook. [Install] gets it starting on boot via WantedBy=multi-user.target default.target. Iconic.
πΈ Example test.kube
Kubernetes yaml, but make it a unit file:
[Unit]
Description=A kubernetes yaml based service
Before=local-fs.target
[Kube]
Yaml=/opt/k8s/deployment.yml
[Install]
# Start by default on boot
WantedBy=multi-user.target default.target
Before=local-fs.target in [Unit], the yaml living at /opt/k8s/deployment.yml, and boom β WantedBy=multi-user.target default.target for that boot-time slay β¨.
π¦ Example for a locally built image used in a container, with build-specific arguments
Two files, one cute little build pipeline. First, test.build:
[Build]
# Tag the image to be built
ImageTag=localhost/imagename
# Set the working directory to the path of the unit file,
# expecting to find a Containerfile/Dockerfile
# + other files needed to build the image
SetWorkingDirectory=unit
# Set build arguments VERSION and DEBUG
BuildArg=VERSION=1.0
DEBUG=false
Then test.container:
[Container]
Image=test.build
The ImageTag=localhost/imagename names what you're building, SetWorkingDirectory=unit points the working dir at the unit file's path (where your Containerfile/Dockerfile and other build files live π«Ά), and the BuildArg=VERSION=1.0 / DEBUG=false pair sets those two build args. Then the container just says Image=test.build and it's giving "I built this myself" main character energy π.
π Example test.volume
[Volume]
User=root
Group=root
Label=org.test.Key=value
User=root, Group=root, and a Label=org.test.Key=value. Short, sweet, perfect.
π§ Example test.network
[Network]
Subnet=172.16.0.0/24
Gateway=172.16.0.1
IPRange=172.16.0.0/28
Label=org.test.Key=value
Subnet 172.16.0.0/24, gateway 172.16.0.1, IP range 172.16.0.0/28, plus that same Label=org.test.Key=value. Networking but make it adorable π.
π₯ Example test.artifact β pulling with a single auth file
[Artifact]
Artifact=quay.io/example/my-artifact:latest
AuthFile=/etc/registry/auth.json
TLSVerify=false
Just the artifact, one auth file at /etc/registry/auth.json, and TLSVerify=false. Look at you being efficient π
.
β Example where a container depends on an artifact
Okay this one's a two-parter. my-artifact.artifact:
[Artifact]
Artifact=quay.io/example/my-config:latest
And my-app.container:
[Container]
Image=quay.io/example/my-app:latest
Mount=type=artifact,source=my-artifact.artifact,destination=/etc/config
The container mounts the artifact at /etc/config via Mount=type=artifact,source=my-artifact.artifact,destination=/etc/config. The way that dependency just works ππ.
π Example for a container in a Pod
test.pod:
[Pod]
PodName=test
centos.container:
[Container]
Image=quay.io/centos/centos:latest
Exec=sh -c "sleep inf"
Pod=test.pod
The pod's named test via PodName=test, and the container joins it with Pod=test.pod while running sh -c "sleep inf" forever. No notes, flawless β¨.
π Example for a Pod with a one-shot startup task
Three files. test.pod:
[Pod]
PodName=test
ExitPolicy=continue
startup-task.container:
[Service]
Type=oneshot
RemainAfterExit=yes
[Container]
Pod=test.pod
Image=quay.io/centos/centos:latest
Exec=sh -c "echo 'setup starting'; sleep 2; echo 'setup complete'"
app.container:
[Unit]
Requires=startup-task.container
After=startup-task.container
[Container]
Pod=test.pod
Image=quay.io/centos/centos:latest
Exec=sh -c "echo 'app running.'; sleep 30"
The pod uses ExitPolicy=continue so it keeps going even when a member exits, the startup task is Type=oneshot with RemainAfterExit=yes, and the app Requires= and After= the startup task. It's giving "ordered, responsible, hydrated" π.
π Example s3fs.volume
For further details, please see the s3fs-fuse project. Remember to read the FAQ.
β οΈ NOTE: Enabling the cache massively speeds up access and write times on static files/objects. However, use_cache is UNBOUNDED! Be careful, it will fill up with any files accessed on the s3 bucket through the file system.
Please remember to set S3_BUCKET, PATH, AWS_REGION. CACHE_DIRECTORY should be set up by systemd.
[Service]
CacheDirectory=s3fs
ExecStartPre=/usr/local/bin/aws s3api put-object --bucket ${S3_BUCKET} --key ${PATH}/
[Volume]
Device=${S3_BUCKET}:/${PATH}
Type=fuse.s3fs
VolumeName=s3fs-volume
Options=iam_role,endpoint=${AWS_REGION},use_xattr,listobjectsv2,del_cache,use_cache=${CACHE_DIRECTORY}
# `iam_role` assumes inside EC2, if not, Use `profile=` instead
CacheDirectory=s3fs in [Service], a put-object ExecStartPre, and then the volume itself: Type=fuse.s3fs, VolumeName=s3fs-volume, and that long Options= line. And peep the comment β # `iam_role` assumes inside EC2, if not, Use `profile=` instead π.
For more examples, please see the podman-quadlet-basic-usage.7.
π SEE ALSO π
Go read these next, bestie, they're all linked in the group chat:
podman-auto-update(1)podman-build.unit(5),podman-container.unit(5),podman-image.unit(5),podman-kube.unit(5),podman-network-create(1),podman-network.unit(5),podman-pod.unit(5),podman-quadlet-basic-usage.7,podman-run(1),podman-volume.unit(5),systemd-analyze(1),systemd.service(5),systemd.unit(5)
And that's the whole page, babe π«Ά β you made it to the end of podman-systemd.unit(5) (that's section 5 of the manual, mwah). Go forth, write your units, and remember: use_cache is unbounded. Stay hydrated, stay caffeinated, and don't let your s3 bucket eat your disk πβ¨π
π¦ where this page comes from
- arch rolling: podman 6.1.4-1 Β· Apache-2.0
- centos-stream 10: podman 7:6.1.0-2.el10 Β· Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND ISC AND MIT AND MPL-2.0
- nixpkgs unstable: podman 6.1.4
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms