Si ya usas Podman, seguro que conoces el patrón: podman run con un montón de flags, y si el servidor reinicia, tienes que acordarte de arrancarlo todo a mano otra vez — o escribir un script que lo haga por ti. Quadlet resuelve esto de raíz: define tus contenedores como ficheros de unidad de systemd, y systemd se encarga de arrancarlos al boot, reiniciarlos si fallan, y gestionarlos con las mismas herramientas (systemctl, journalctl) que ya usas para cualquier otro servicio del sistema. Así es exactamente como tenemos desplegados El Rack y Predify en producción — nada de scripts caseros, todo gestionado por systemd de forma nativa.
Podman Quadlet paso a paso: de contenedor suelto a servicio systemd
Confirma que tienes Podman y systemd
Quadlet viene integrado en Podman desde la versión 4.4 en adelante, así que primero confirma qué versión tienes instalada. La mayoría de distros modernas (Fedora, RHEL, Debian 12+, Ubuntu 24.04+) ya traen una versión compatible.
podman --version
Si tu versión es anterior a la 4.4, actualiza Podman antes de continuar — Quadlet no funcionará en versiones más antiguas.
Crea la carpeta de unidades Quadlet
Si vas a correr el contenedor como tu usuario normal (rootless, la opción recomendada), Quadlet busca los ficheros de definición en una carpeta concreta dentro de tu directorio de usuario. Créala si no existe todavía.
mkdir -p ~/.config/containers/systemd/
Si en cambio necesitas que el contenedor corra como root (menos recomendable, solo si de verdad lo necesitas), la ruta equivalente es /etc/containers/systemd/.
Escribe el fichero .container
Aquí está la parte central: en vez de un comando podman run largo, defines el contenedor en un fichero con extensión .container, con sintaxis tipo INI. Este ejemplo levanta un contenedor simple de nginx — sustituye la imagen, puertos y volúmenes por los de tu propio servicio.
# ~/.config/containers/systemd/miapp.container [Unit] Description=Mi aplicación [Container] Image=docker.io/library/nginx:alpine PublishPort=8080:80 Volume=%h/miapp/html:/usr/share/nginx/html:Z [Service] Restart=always [Install] WantedBy=default.target
El %h se expande automáticamente a tu directorio home — no hace falta que pongas la ruta absoluta a mano. La :Z al final del volumen es importante si usas SELinux (Fedora, RHEL): indica que el contenedor puede acceder a esos ficheros sin bloqueos de contexto.
Recarga systemd para que detecte la unidad nueva
Quadlet genera el servicio systemd real a partir de tu fichero .container automáticamente, pero systemd necesita que le avises de que hay algo nuevo que leer.
systemctl --user daemon-reload
Si desplegaste el fichero en la ruta de sistema (/etc/containers/systemd/), usa el mismo comando sin --user.
Arranca y habilita el servicio
A partir de aquí, tu contenedor se gestiona exactamente igual que cualquier otro servicio systemd — mismo comando, mismo comportamiento.
systemctl --user enable --now miapp.service
El nombre del servicio (miapp.service) sale directamente del nombre que le diste al fichero (miapp.container) — Quadlet hace esa conversión automáticamente, no hace falta declararlo en ningún sitio.
Verifica que está corriendo
Comprueba el estado del servicio y, si algo no arranca como esperabas, revisa los logs — exactamente el mismo flujo que usarías para depurar cualquier otro servicio del sistema.
systemctl --user status miapp.service journalctl --user -u miapp.service -f
Si todo va bien, el estado debería mostrar "active (running)", y journalctl te irá mostrando los logs del contenedor en tiempo real con -f.
Prueba la persistencia reiniciando
La razón de todo esto es que el contenedor sobreviva a un reinicio del servidor sin que tengas que acordarte de arrancarlo a mano. Para comprobarlo sin reiniciar la máquina entera, puedes simplemente reiniciar el propio servicio y confirmar que vuelve a levantarse solo.
systemctl --user restart miapp.service systemctl --user is-enabled miapp.service
Si is-enabled responde enabled, el servicio arrancará automáticamente en cada reinicio del sistema, sin intervención manual.
Conclusión
A partir de aquí, cada servicio nuevo que despliegues es el mismo patrón: un fichero .container, un daemon-reload, y un enable --now. Es exactamente así como tenemos montados El Rack, Predify y el resto de servicios de este mismo VPS — nada de scripts de arranque caseros, todo gestionado por systemd de forma nativa, con los mismos comandos que ya conoces para cualquier otro servicio del sistema.
