Quadlets are a native Podman feature that allow users to manage containers as systemd services without manually writing complex unit files.
They function by using declarative configuration files (ending in .container, .pod, etc.)
The podman-system-generator automatically converts these high-level declarative files into standard systemd .service files during boot or when systemctl daemon-reload is executed.
Because Quadlets integrate directly with the systemd init system, they eliminate the need for Docker’s daemon or wrapper tools like podman-compose.
This allows management of container lifecycles (auto-start on boot, restart on failure, logging) using native Linux service management commands like systemctl,
making Docker a completely optional dependency.
/home/containers: containers’s home directory; dedicated to user/local container filesservice.container files, container-config directories, etc)/home/containers/ # constant write config data on ssd or nvme
├── .config/
│ └── containers/
│ └── systemd/ # symbolically link the unit files directory
│ ├── immich -> ../../../immich/quadlets
│ ├── jellyfin -> ../../../jellyfin/quadlets
│ └── transmission -> ../../../transmission/quadlets
│
├── immich/
│ ├── backups/
│ ├── postgres/
│ ├── model-cache/
│ └── quadlets/
│ ├── immich.pod
│ ├── immich-server.container
│ ├── immich-machine-learning.container
│ ├── immich-database.container
│ ├── immich-valkey.container
│ └── immich.env
│
├── jellyfin/
│ ├── backups/
│ ├── cache/
│ ├── config/
│ └── quadlets/
│ └── jellyfin.container
│
└── transmission/
├── backups/
├── config/
└── quadlets/
└── transmission.container
/srv/media/ # for storage data on spinning platter disks
├── pictures/ existing photo collection
└── immich/ media uploaded and managed by Immich
service.container files MUST contain:
[Install]
# Start by default on boot
WantedBy=default.target
service.container files get symlinked to:/home/containers/.config/containers/systemdloginctl enable-linger containerssystemctl --user daemon-reloadsystemctl --user start {serviceName}.servicesystemctl --user enable --now podman-auto-update.timerSome services need a password, and instead of typing the password into one of the quadlet INI’s, we will store it as a “podman secret”
printf 'password' | podman secret create immich_db_pass -
Then add a line in the particular service that needs the password (ex:)
Secret=immich_db_pass,type=env,target=POSTGRES_PASSWORD
printf 'password' | podman secret create immich_db_pass -
Config straight from Bazzite! (but looks to be missing some bits)
https://docs.bazzite.gg/Installing_and_Managing_Software/Quadlet/?h=samba#samba-server
[Container]
ContainerName=samba
Environment=ACCOUNT_username=password
Environment=UID_username=1011
#Environment=GROUPS_username=users
# Protected share with write access
Environment="SAMBA_VOLUME_CONFIG_dublife=[DubLife]; path=/srv; valid users = username; guest ok = no; read only = no; browseable = yes"
# Open share with readonly access
Environment="SAMBA_VOLUME_CONFIG_media=[Media Share]; path=/srv/media; guest ok = yes; read only = no; browseable = yes"
Image=ghcr.io/servercontainers/samba:smbd-only-latest
AutoUpdate=registry
Network=host
Volume=/path/to/protected:/shares/dublife:z
Volume=/path/to/guest:/shares/media:z
# Remove if you don't want autostart
[Install]
WantedBy=default.target
https://hub.docker.com/r/servercontainers/samba #for info only, use below to actually pull image
docker pull ghcr.io/servercontainers/samba:latest
samba:
image: docker.io/servercontainers/samba:latest
container_name: samba
restart: unless-stopped
# user: samba
# network_mode: host
# hostname: smb-server
environment:
ACCOUNT_samba: test
UID_samba: 1000
SAMBA_GLOBAL_STANZA: vfs objects = catia fruit streams_xattr
SAMBA_VOLUME_CONFIG_shared_home: |
[home];
path=/shares/home
valid users = samba
browsable = yes
writeable = yes
dockurr is recently updated & well regarded
https://hub.docker.com/r/dockurr/samba
search.brave.com:dockur samba example
Quadlet:
docker pull dockurr/samba:latest
# ~/.config/containers/systemd/samba.container
#https://hub.docker.com/r/dockurr/samba
[Unit]
Description=Samba SMB Server
[Container]
ContainerName=samba
Image=docker.io/dockurr/samba
PublishPort=445:445
Volume=/path/to/local/data:/storage
Environment=USER=samba
Environment=PASS=secret
Environment=NAME=Media
Network=host
# Note: If using default bridge network, ensure port mapping is correct
# and no conflicting services are on port 445.
[Install]
WantedBy=default.target
docker-compose:
services:
samba:
image: dockurr/samba
container_name: samba
environment:
NAME: "Data"
USER: "samba"
PASS: "secret"
RW: true
UID: 1000
GID: 1000
ports:
- 445:445
volumes:
- ./samba:/storage
restart: always