770 - ¡Deja de usar contraseñas en tus Docker Compose! Descubre Podman Secrets
Aprende a proteger tus contraseñas en Podman. Descubre cómo usar Secrets, drivers personalizados y la herramienta Crypta (Rust) para máxima seguridad.
Algo que me molesta sobremanera es el hecho de tener todos la configuración, claves, contraseñas, token, etcétera, en archivos de texto plano. Esto es algo que no me gusta nada de nada. Esta es precisamente una de las razones para el episodio 765 en el que te hablé de SOPS y Age para cifrar.
Después de tanto tiempo, utilizando Docker, sin hacer nada con los secretos, y ahora que con SOPS y Age tenía una buena solución, voy y doy el salto a Podman. Es lo que tiene.
Cierto es que podía haber activado Swarm en Docker y haber utilizado los secretos de Docker, pero la verdad es que no me apetecía nada. Pero es que en Podman, no tengo que hacer nada, ya viene habilitado por defecto, con lo que si no lo utilizo ya es desidia.

¡Deja de usar contraseñas en tus Docker Compose! Descubre Podman Secrets
¿Que es un Secret en Podman?
Un secreto es un objeto que almacena datos sensibles (passwords, claves SSH, certificados API) fuera de la imagen del contenedor y de las variables de entorno.
- Seguridad. No se quedan grabados en el historial de docker inspect o en el bash_history.
- Almacenamiento. Por defecto, Podman los guarda encriptados en el host en
~/.local/share/containers/storage/secrets/para modo rootless.
El ciclo de vida de un secreto
El ciclo de vida de un secreto en Podman es muy similar al de cualquier otro elemento del mundo de los contenedores. Básicamente consta de tres fases, creación, uso y eliminación.
Creación de un secreto
Para crear un secreto tienes dos opciones, o bien desde un archivo,
podman secret create mi_secreto archivo_con_datos_sensibles.txt
O bien directamente desde la terminal, pero evitando que se guarde en el historial. Para que no se guarde en el historial simplemente precede el primer comando con un espacio en blanco.
echo "mi_dato_sensible" | podman secret create mi_secreto -
Listar y gestionar
Aquí podemos hacer tres operaciones básicas,
podman exists <secreto>: Comprobar si un secreto existe. Esto nos devolverá un0si existe o un1si no existe. Recuerda que lo devuelve en el código de salida.podman secret ls. Lista todos los secretos disponibles.podman secret inspect <secreto>. Muestra información detallada sobre un secreto específico. Como por ejemplo,
podman secret inspect 696
[
{
"ID": "696d1faa0f6c32ee7b1ecea63",
"CreatedAt": "2026-01-28T13:27:39.25075274+01:00",
"UpdatedAt": "2026-01-28T13:27:39.25075274+01:00",
"Spec": {
"Name": "clave",
"Driver": {
"Name": "file",
"Options": {
"path": "/data/containers/secrets/filedriver"
}
},
"Labels": {}
}
}
]
Fin de vida de un secreto
Como ya te puedes imaginar, el fin de vida de un secreto llega cuando lo eliminamos. Para eliminar un secreto utilizamos el siguiente comando,
podman secret rm mi_secreto
Como utilizar un secreto en un contenedor
Evidentemente, el objetivo de los secretos es utilizarlos en los contenedores. Para ello, simplemente tenemos que indicarle a Podman que queremos utilizar un secreto determinado en el momento de crear el contenedor.
podman run --detach \
--name wp-mariadb \
--network wp-network.network \
--secret wp_db_root_pass,type=env,target=MYSQL_ROOT_PASSWORD \
--secret wp_db_user_pass,type=env,target=MYSQL_PASSWORD \
--env MYSQL_USER=lorenzo \
--env MYSQL_DATABASE=wordpress \
docker.io/library/mariadb:10.11
O la otra opción es montarlo como un archivo dentro del contenedor,
podman run --detach \
--name wp-mariadb \
--secret wp_db_root_pass \
--secret wp_db_user_pass \
-e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/wp_db_root_pass \
-e MYSQL_PASSWORD_FILE=/run/secrets/wp_db_user_pass \
-e MYSQL_USER=lorenzo \
-e MYSQL_DATABASE=wordpress \
docker.io/library/mariadb:10.11
Para verificar que nuestro secreto está donde está y tiene lo que tiene que tener,
podman run --rm --secret wp_db_user_pass alpine cat /run/secrets/wp_db_user_pass
Y los qualets respectivos utilizando las dos opciones serían los siguientes,
[Unit]
Description=Base de Datos MariaDB (Secreto como Entorno)
[Container]
Image=docker.io/library/mariadb:10.11
ContainerName=wp-mariadb
# Mapeo directo: Secreto -> Variable de Entorno
Secret=wp_db_root_pass,type=env,target=MYSQL_ROOT_PASSWORD
Secret=wp_db_user_pass,type=env,target=MYSQL_PASSWORD
# Variables no sensibles
Environment=MYSQL_USER=lorenzo
Environment=MYSQL_DATABASE=wordpress
Network=wp-network.network
Volume=wp-db-data.volume:/var/lib/mysql:Z
[Service]
Restart=always
[Install]
WantedBy=default.target
Y para el caso de montarlo como archivo,
[Unit]
Description=Base de Datos MariaDB (Secreto como Archivo)
[Container]
Image=docker.io/library/mariadb:10.11
ContainerName=wp-mariadb
# Montaje implícito (comportamiento por defecto)
Secret=wp_db_root_pass
Secret=wp_db_user_pass
# Configuramos MariaDB para que lea desde el archivo montado
Environment=MYSQL_ROOT_PASSWORD_FILE=/run/secrets/wp_db_root_pass
Environment=MYSQL_PASSWORD_FILE=/run/secrets/wp_db_user_pass
# Variables no sensibles
Environment=MYSQL_USER=lorenzo
Environment=MYSQL_DATABASE=wordpress
Network=wp-network.network
Volume=wp-db-data.volume:/var/lib/mysql:Z
[Service]
Restart=always
[Install]
WantedBy=default.target
Indicar que la opción _FILE no es una característica de Podman, sino que es una convención utilizada por muchas aplicaciones para leer secretos desde archivos. Pero es una característica que tiene que implementar la propia aplicación.
Por supuesto, esto de los secretos, también se puede utilizar con Podman Compose. Por ejemplo,
services:
db:
image: mariadb
secrets:
- mi_db_password
environment:
- MARIADB_PASSWORD_FILE=/run/secrets/mi_db_password
secrets:
mi_db_password:
external: true
Drivers externos
Además del driver por defecto file, el ecosistema de Podman está diseñado para ser extensible. La arquitectura de secretos de Podman utiliza internamente un modelo de plugins que permite conectar casi cualquier sistema de gestión de clave.
fileel secreto se encuentra en un archivo de solo lecturapassel secreto está en un archivo cifrado con GPGshellen este caso el secreto se gestiona por scripts personalizados. Después de mucho probar, conseguí integrarcryptacon los secretos de Podman. Pero no ha sido nada fácil
Un ejemplo de su uso con pass sería el siguiente,
podman secret create --driver=pass mi_screto ./mi_secreto_cifrado.txt.gpg
crypta
Si lo quieres utilizar con crypta, tienes que añadir en ~/.config/containers/containers.conf lo siguiente,
[secrets]
driver = "shell"
[secrets.opts]
store = "/home/lorenzo/.local/bin/crypta store"
lookup = "/home/lorenzo/.local/bin/crypta lookup"
delete = "/home/lorenzo/.local/bin/crypta delete"
list = "/home/lorenzo/.local/bin/crypta list"
He tenido que hacer varias modificaciones a crypta para que funcione correctamente como driver de secretos en Podman. Y es que el nombre del parámetro se pasa en la variable SECRET_ID, y no había leído la documentación con suficiente atención.
Así ahora si quieres crear un secreto con crypta, simplemente tienes que hacer,
echo "secreto" | podman secret create --driver shell mi_secreto -
Si listas los secretos obtendrás lo siguiente,
ID NAME DRIVER CREATED UPDATED
f7eb919d48f45cebeede11ab6 mi_secreto shell 27 seconds ago 27 seconds ago
Y en crypta, verás que se ha creado el secreto,
f7eb919d48f45cebeede11ab6
Para que todo funcione como toca, cuando lo quieras borrar lo tienes que hacer desde Podman, no con crypta.
Ventajas de los secretos
- Rootless por defecto. Los secretos funcionan perfectamente en modo rootless, manteniendo la coherencia con la filosofía de seguridad de Podman que sueles promulgar.
- Integración con Systemd. Si generas unidades de systemd con podman generate systemd, los secretos se mantienen vinculados al ciclo de vida del servicio.
- Drivers externos. Podman permite usar drivers como pass para gestionar los secretos, lo cual escala muy bien si ya usas herramientas de cifrado en tu escritorio Linux.
Más información,