Using Podman - dani-garcia/vaultwarden GitHub Wiki
Podman is a daemonless alternative to Docker, which is mostly compatible with Docker containers.
Creating a Quadlet (Podman 4.4+)
As of version 4.4, Podman uses quadlets and will show a warning if you use the previous generate systemd method.
Additional benefit is that this method will keep the container updated.
Configuration via environment file
Configuration may be easier in an environment file and less error-prone.
NOTE: this file contains secrets, make sure only root has access!
sudo install -o0 -g0 -m600 /dev/null /etc/vaultwarden.env
sudo vi /etc/vaultwarden.env
# Contents of /etc/vaultwarden.env
ROCKET_PORT=8080
# DISABLE_ADMIN_TOKEN=true
# ADMIN_TOKEN=$argon2id$...
# LOG_LEVEL=debug
Creating the podman quadlet
Configuration looks like systemd's but we configure a Container, not a Unit. See the documentation for all [Container] directives.
# Content of /usr/share/containers/systemd/vaultwarden.container
[Unit]
Description=Vaultwarden container
After=network-online.target
[Container]
AutoUpdate=registry
Image=ghcr.io/dani-garcia/vaultwarden:latest
Exec=/start.sh
EnvironmentFile=/etc/vaultwarden.env
Volume=/vw-data/:/data/
PublishPort=8080:8080
[Install]
WantedBy=default.target
After editing the quadlet, run systemctl daemon-reload to create or updates the systemd unit. You control this container using regular systemctl commands, e.g. systemctl start vaultwarden.service.
Auto update
auto-update automates the update process.
sudo podman auto-update
Or, you can enable the timer which invokes auto-update daily (by default, may be edited).
sudo systemctl enable podman-auto-update.timer
Creating a systemd service file (older Podman versions)
Podman is easier to run in systemd than Docker due to its daemonless architechture. It comes with a handy generate systemd command which can generate systemd files. Here is a good article that goes into more detail as well as this article detailing some more recent updates.
$ podman run -d --name vaultwarden -v /vw-data/:/data/:Z -e ROCKET_PORT=8080 -p 8080:8080 vaultwarden/server:latest
54502f309f3092d32b4c496ef3d099b270b2af7b5464e7cb4887bc16a4d38597
$ podman generate systemd --name vaultwarden
# container-vaultwarden.service
# autogenerated by Podman 1.6.2
# Tue Nov 19 15:49:15 CET 2019
[Unit]
Description=Podman container-vaultwarden.service
Documentation=man:podman-generate-systemd(1)
[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start vaultwarden
ExecStop=/usr/bin/podman stop -t 10 vaultwarden
KillMode=none
Type=forking
PIDFile=/run/user/1000/overlay-containers/54502f309f3092d32b4c496ef3d099b270b2af7b5464e7cb4887bc16a4d38597/userdata/conmon.pid
[Install]
WantedBy=multi-user.target default.target
You can provide a --files flag to tell podman to put the systemd service into a file or use podman generate systemd --name vaultwarden > /etc/systemd/system/container-vaultwarden.service. With this we can enable and start the container as any normal service file.
$ systemctl enable /etc/systemd/system/container-vaultwarden.service
$ systemctl start container-vaultwarden.service
New container every restart
If we want to create a new container every time the service starts we can use the podman generate systemd --new command to generate a service file that recreates containers
$ podman generate systemd --new --name vaultwarden
If you're using an older Podman, you can edit the service file to contain the following instead:
[Unit]
Description=Podman container-vaultwarden.service
[Service]
Restart=on-failure
ExecStartPre=/usr/bin/rm -f /%t/%n-pid /%t/%n-cid
ExecStart=/usr/bin/podman run --conmon-pidfile /%t/%n-pid --cidfile /%t/%n-cid --env-file=/home/spytec/Vaultwarden/vaultwarden.conf -d -p 8080:8080 -v /home/spytec/Vaultwarden/vw-data:/data/:Z vaultwarden/server:latest
ExecStop=/usr/bin/podman stop -t "15" --cidfile /%t/%n-cid
ExecStop=/usr/bin/podman rm -f --cidfile /%t/%n-cid
KillMode=none
Type=forking
PIDFile=/%t/%n-pid
[Install]
WantedBy=multi-user.target default.target
Where vaultwarden.conf environment file can contain all the container environment values you need
ROCKET_PORT=8080
If you want the container to have a specific name, you might need to add ExecStartPre=/usr/bin/podman rm -i -f vaultwarden if the process isn't cleaned up correctly. Note that this method currently doesn't work with the User= options users (see https://github.com/containers/podman/issues/5572).
Troubleshooting
Debugging systemd service file
If the host goes down or the container crashes, the systemd service file should automatically stop the existing container and spin it up again. We can find the error through journalctl -u container-vaultwarden -t 100.
Most of the time the errors we see can be fixed by simply upping the timeout in Podman command in the service file.
Full use of quadlet files for Vaultwarden and database
The application and the PostgreSQL database are containerised and placed in a pod. The application uses its own network via the Podman network functionality. Persistent volumes are used for database data and for Vaultwarden application data. Secrets used by the deployment containers are managed by the Podman secret functionality.
flowchart TD
A(vaultwarden.network) --- B(vaultwarden.pod)
B --- C(vaultwarden-app.container)
B --- D(vaultwarden-db.container)
C --- G[/env_file=/etc/vaultwarden/config/]
C --- E[(vaultwarden-app.volume)]
D --- F[(vaultwarden-db.volume)]
D --- H[/env_file=/home/vaultwarden/vaultwarden/vaultwarden-db.env/]
C --- I{{podman-secret: database_url, admin_token}}
D --- J{{podman-secret: postgres_password}}
style A fill:#ffec99
style B fill:#ffc9c9
style C fill:#b2f2bb
style D fill:#b2f2bb
style E fill:#a5d8ff
style F fill:#a5d8ff
style G fill:#f08c00
style H fill:#f08c00
style I fill:#d0bfff
style J fill:#d0bfff
This infrastructure is defined using these quadlet files:
- vaultwarden-app.container
- vaultwarden-app.volume
- vaultwarden-db.container
- vaultwarden-db.volume
- vaultwarden.network
- vaultwarden.pod
Definition of the Pod
Create the file `~/.config/containers/systemd/vaultwarden.pod:
[Pod]
PodName=vaultwarden
Network=vaultwarden.network
PublishPort=8080:8080
Definition of the network
Create the file `~/.config/containers/systemd/vaultwarden.network:
[Network]
NetworkName=vaultwarden
Gateway=192.168.220.1
Subnet=192.168.220.0/24
Definition of the persistent volumes
Create the file ~/.config/containers/systemd/vaultwarden-app.volume:
[Volume]
VolumeName=vaultwarden-app
and the file ~/.config/containers/systemd/vaultwarden-db.volume:
[Volume]
VolumeName=vaultwarden-db
Definition of the containers
Create the file ~/.config/containers/systemd/vaultwarden-app.container:
[Container]
ContainerName=vaultwarden-app
EnvironmentFile=/etc/vaultwarden/config
HealthCmd=/healthcheck.sh
HealthInterval=120s
HealthRetries=10
HealthTimeout=45s
Image=docker.io/vaultwarden/server:1.34.3
Pod=vaultwarden.pod
Secret=database_url,type=env,target=DATABASE_URL
Secret=admin_token,type=env,target=ADMIN_TOKEN
Volume=vaultwarden-app.volume:/data
[Unit]
Requires=vaultwarden-db.service
After=vaultwarden-db.service
[Install]
WantedBy=default.target
and the file ~/.config/containers/systemd/vaultwarden-db.container:
[Container]
ContainerName=vaultwarden-db
EnvironmentFile=/home/vaultwarden/vaultwarden/vaultwarden-db.env
HealthCmd=/usr/bin/pg_isready -q -d vaultwarden -U vaultwarden
HealthInterval=120s
HealthRetries=10
HealthTimeout=45s
Image=docker.io/library/postgres:17
Pod=vaultwarden.pod
Secret=postgres_password,type=env,target=POSTGRES_PASSWORD
Volume=vaultwarden-db.volume:/var/lib/postgresql/data
[Install]
WantedBy=default.target
Configuration
Configuration is done using the environment file /etc/vaultwarden/config and ~/vaultwarden/vaultwarden-db.env.
In the ~/vaultwarden/vaultwarden-db.env file set the vars POSTGRES_USER and POSTGRES_DB
Secrets
You need to define the secrets postgres_password, database_url and admin_token :
I assume that POSTGRES_USER=vaultwarden and POSTGRES_DB=vaultwarden
openssl rand -base64 32|podman secret create postgres_password -
echo "postgres://vaultwarden:$(podman secret inspect --showsecret --format '{{.SecretData}}' postgres_password)@vaultwarden-db/vaultwarden" | tr -d '\n' | podman secret create database_url -
echo -n "MySecretPassword" | argon2 "$(openssl rand -base64 32)" -e -id -k 65540 -t 3 -p 4| tr -d '\n' | podman secret create admin_token -
Deploy
systemctl --user daemon-reload
systemctl --user start vaultwarden-pod.service