Skip to content

Docker

PodVault ships as a single image, martitoci/podvault, for linux/amd64 and linux/arm64. There’s no Redis, Postgres or separate worker: one container runs the web interface, the background downloads and the scheduler, and keeps everything in one volume.

Terminal window
docker run -d --name podvault \
-p 8000:8000 \
-v ./data:/app/data \
-e PODVAULT_USERNAME=admin \
-e PODVAULT_PASSWORD=change-me \
--restart unless-stopped \
martitoci/podvault:latest

Open http://<server-address>:8000. Every setting is an optional PODVAULT_* environment variable; see Configuration.

Everything PodVault stores lives in /app/data. Mount it as a volume so your library survives restarts and updates:

Path in the container Contents
/app/data/podvault_data.db SQLite database: episodes, download state, settings, schedules
/app/data/downloads/ The downloaded episodes
/app/data/feeds.txt Your list of feed URLs
/app/data/backups/ Automatic database backups (the newest 7 are kept)

To store episodes on a different disk (a NAS share, an external drive), mount it over the downloads folder:

Terminal window
docker run -d --name podvault \
-p 8000:8000 \
-v ./data:/app/data \
-v /mnt/media/podcasts:/app/data/downloads \
-e PODVAULT_USERNAME=admin \
-e PODVAULT_PASSWORD=change-me \
--restart unless-stopped \
martitoci/podvault:latest

In Compose, add the line under volumes::

volumes:
- ./data:/app/data
- /mnt/media/podcasts:/app/data/downloads

The container listens on port 8000. To use another port on the host, change the left side of the mapping, for example -p 8080:8000.

The image has a built-in HEALTHCHECK that polls /healthz every 30 seconds. That endpoint needs no login, so the check keeps working when the login is on. docker ps shows the container as healthy once it’s up.

Terminal window
docker pull martitoci/podvault:latest
docker rm -f podvault
# then run the same docker run command as before

Updates don’t touch your data in /app/data, and the database is backed up automatically before feed syncs. To stay on a specific release, use a version tag instead of latest.

Tag Release
latest The most recent release
1.3.1 Newest-first episode order fixes, readable descriptions, full dates, podcast names on Schedule
1.3.0 Sign-in page with Sign out and “keep me signed in”, login lockout
1.2.0 OPML import/export, your own podcast feeds
1.1.0 Web login, non-MP3 audio, database backups
1.0.0 First release

Details in the release notes.

The full command line is available in the container:

Terminal window
docker exec podvault podvault --help
docker exec podvault podvault backup # back up the database now
docker exec podvault podvault opml-import /app/data/subs.opml # import subscriptions
docker exec podvault podvault verify # check every file is still on disk

Files you want the CLI to read, like an OPML file, need to be inside the volume (for example ./data/subs.opml on the host is /app/data/subs.opml in the container).

You don’t need a reverse proxy on a home network. If you put PodVault on a network you don’t fully trust anyway, run it behind an HTTPS reverse proxy (Caddy, Traefik, nginx…), because the password isn’t encrypted over plain HTTP. The session cookie is marked Secure automatically when the proxy reports HTTPS through X-Forwarded-Proto. Set PODVAULT_BASE_URL to the proxy’s address so links inside your podcast feeds use it.

A reverse proxy doesn’t make PodVault safe to expose to the internet. For access from outside, use a VPN. See Security.

The Dockerfile in the source repository builds from python:3.11-slim, installs the package and runs podvault serve --host 0.0.0.0 --port 8000. The repo’s docker-compose.yml builds from source:

Terminal window
git clone https://github.com/chmedinap/PodVault.git
cd PodVault
docker compose up -d --build

PodVault v1.3.1 · GitHub · Docker Hub ·Report an issue

Built for home networks · No trackers · MIT License · © Carlos Medina