Podman with Quadlet - Getting Started Guide

Podman with Quadlet - Getting Started Guide
You bending containers at your will

This guide will help you get started with Podman and Quadlet in a simple, non-technical way. Scroll down for templates for .container, .network, and .env files. ๐Ÿš€

Did you know? You can use Cockpit or Portainer with Podman for easier container management.


For real-life examples of containers I run, check out my GitHub. The configurations are tested and approved.

GitHub - fpatrick/podman-quadlet: Personal Podman Quadlet configurations for self-hosted services in a homelab environment
Personal Podman Quadlet configurations for self-hosted services in a homelab environment - fpatrick/podman-quadlet

What is Quadlet?

Quadlet is a way to manage containers in Podman using systemd. You write .container files, and systemd runs and manages the container for you. This makes it easier to start, stop, and update containers without needing complex scripts.

Rootless Setup

Rootless means you don't need admin (root) permissions to run containers. If something breaks out of the container, it won't cause too much damage.

Step-by-Step Guide

  1. Set up the directories ๐Ÿ“‚:

    mkdir -p ~/.config/containers/systemd/
    

    Later, put your .container, .network, and .env files in this directory.

  2. Create or modify a .container file ๐Ÿ› ๏ธ:

    nano ~/.config/containers/systemd/myapp.container
    

    This is where you define your container. Example template below.

  3. Reload systemd ๐Ÿ”„:

    systemctl --user daemon-reload
    
  4. Prepare persistent storage ๐Ÿ—‚๏ธ:
    Before starting the container, create the directories for persistent storage.

    mkdir -p /path/to/storage/containerfolder
    
  5. Start the container โ–ถ๏ธ:

    systemctl --user start myapp.service
    
  6. Troubleshooting โ—:
    If something goes wrong, check logs:

    journalctl --user -u myapp.service --no-pager -n 50
    

Rootful Setup (Admin Access)

In rootful mode, you need admin (root) permissions.

  1. Use sudo ๐Ÿ›‘: Prefix every command with sudo.
  2. Change directory for container files ๐Ÿ“: Put your .container files in /etc/containers/systemd/.
  3. Run commands:
    • Same as rootless, but without the --user flag:
      sudo systemctl start myapp.service
      

Updates

Auto-updating Containers ๐Ÿ”„

To automatically update your containers:

  1. Add AutoUpdate=registry in your .container file.
  2. Enable the Podman auto-update service:
    systemctl --user enable podman-auto-update
    

Manual Updates ๐Ÿ”ง

  1. Pull the latest image:
    podman pull docker.io/my-image:latest
    
  2. Restart the container:
    systemctl --user restart myapp.service
    

Example Templates

.container file template

[Unit]
# (Optional) A brief description of the service
Description=
# (Optional) Services you want to run with this one
Wants=
# (Optional) Services that need to start before this one
After=

[Container]
# (Mandatory) The container's name
ContainerName=
# (Mandatory) The container image to use (e.g., docker.io/library/alpine)
Image=
# (Optional) Path to an .env file
EnvironmentFile=
# (Optional) Key=value pairs for environment variables
Environment=
# (Optional) Persistent storage paths (host:container)
Volume=
# (Optional) Custom network for the container
Network=
# (Optional) Ports to expose (host:container)
PublishPort=
# (Optional) Custom command to run in the container
Exec=
# (Optional) Additional Podman arguments
PodmanArgs=
# (Optional) Extra capabilities to add to the container
AddCapability=
# (Optional) Add host devices to the container
AddDevice=
# (Optional) Disable SELinux labels
SecurityLabelDisable=
# (Optional) Run as a specific user inside the container
User=
# (Optional) Autoupdate (also needs to be enabled systemctl --user enable podman-auto-update)
AutoUpdate=registry
# (Optional) Add metadata labels to the container
Label=
# (Optional) User ID mapping. Example: 0:10000:10 (Inside:Outside:Range)
UIDMap=
# (Optional) Group ID mapping Example: 0:10000:10 (Inside:Outside:Range)
GIDMap=

[Service]
# (Optional) Set to 'always' or 'on-failure' to restart on failure
Restart=
# (Optional) Time to wait before considering a failure
TimeoutStartSec=

[Install]
# (Optional) Target to start with (default: multi-user.target)
WantedBy=

.network file template

The gateway and subnet cannot be the same as other containers or your home network. Make sure to check that if you have dependency errors and container not starting.

[Network]
# (Mandatory) Subnet for the network
Subnet=192.168.99.0/24  
# (Mandatory) Gateway IP address
Gateway=192.168.99.1    
# (Optional) Custom label for the network
Label=                  

.env file template

Define environment variables:

# Example: PGID=200
ENVIRONMENT_FIELD=your_secret_value 

That's it! You're ready to manage containers with Quadlet. ๐Ÿ˜Š