Skip to content

App configuration

PodVault is configured in two places:

  • Environment variables (PODVAULT_*) for deployment settings: paths, the login, backups, timeouts and logging. All of them are optional.
  • The database for settings you change while it runs: the naming templates and per-podcast schedules. Change these from the web interface or with podvault config and podvault schedule.

Set them with -e on docker run, under environment: in Compose, or in your shell before podvault serve. The Settings page shows the values in effect.

Variable Default Purpose
PODVAULT_USERNAME unset (no login) Username for the web interface. Set together with PODVAULT_PASSWORD.
PODVAULT_PASSWORD unset (no login) Password for the web interface. Set both if port 8000 is reachable from other machines.
PODVAULT_FEED_TOKEN derived from the password Fixed access token for podcast app feed URLs when the login is on. Without it, changing the password revokes old feed URLs.
PODVAULT_BASE_URL taken from each request Address used in links inside your podcast feeds, e.g. https://podvault.example.com behind a reverse proxy.

Setting only one of PODVAULT_USERNAME and PODVAULT_PASSWORD is treated as a mistake: every request is refused until both are set (or neither), podvault serve names the missing one when it starts, and the sign-in page explains the problem. See Security for how the login works.

Variable Default (from source) Default in Docker Purpose
PODVAULT_DB_PATH podvault_data.db /app/data/podvault_data.db SQLite database file
PODVAULT_DOWNLOADS_FOLDER downloads /app/data/downloads Where episodes are saved
PODVAULT_FEEDS_FILE feeds.txt /app/data/feeds.txt Your list of feed URLs
PODVAULT_DB_TIMEOUT 30.0 30.0 Database timeout, in seconds

Relative paths are relative to the directory you run podvault from. In Docker, the image sets these three to paths under /app/data, so keep them there or make sure the new location is on a mounted volume.

Variable Default Purpose
PODVAULT_DEFAULT_DELAY_SECONDS 5 Pause between episode downloads, to go easy on publishers’ servers
PODVAULT_DOWNLOAD_TIMEOUT 30 Download timeout, in seconds
Variable Default Purpose
PODVAULT_SCHEDULER_POLL_INTERVAL_SECONDS 300 How often the scheduler checks for podcasts that are due for a refresh

The refresh interval itself (6h, 12h, 24h, 7d) is set per podcast, in the web interface or with podvault schedule.

Variable Default Purpose
PODVAULT_BACKUP_ENABLED true Automatic database backups on or off
PODVAULT_BACKUP_KEEP 7 How many backups to keep
PODVAULT_BACKUP_INTERVAL_HOURS 24 Minimum time between automatic backups
PODVAULT_BACKUP_DIR backups/ next to the database (/app/data/backups in Docker) Where backups are written

See Archive safety for how backups work and how to restore one.

Variable Default Purpose
PODVAULT_LOG_LEVEL INFO DEBUG, INFO, WARNING, ERROR or CRITICAL
PODVAULT_LOG_FILE unset (console only) Also write the log to this file
docker-compose.yml
services:
podvault:
image: martitoci/podvault:latest
ports:
- "8000:8000"
volumes:
- ./data:/app/data
environment:
PODVAULT_USERNAME: admin
PODVAULT_PASSWORD: a-long-password
PODVAULT_BACKUP_KEEP: "14"
PODVAULT_LOG_LEVEL: WARNING
restart: unless-stopped

PodVault decides where each episode goes with two templates: one for the folder and one for the file name. The defaults are:

Template Default
Folder {podcast_name}/{year}/{month}/{episode_label} - {episode_title}
File name {episode_title} - {podcast_name}

That produces a tree like this:

downloads/
└── podcast_name/
└── 2024/
└── 01/
└── 003 - Episode Title/
├── Episode Title - podcast_name.mp3
├── episode_image.jpg (if available)
└── episode_metadata.xml (original RSS entry)

Each episode gets its own folder. The audio keeps its real extension (.mp3, .m4a, .ogg…), and the folder also holds the cover image and the original RSS entry as XML. Your files stay organized and usable without PodVault.

Variable Value
{podcast_name} The podcast’s name
{episode_title} The episode title, or your custom name if you renamed it
{episode_number} Episode number from the feed
{season_number} Season number from the feed
{year}, {month}, {day} Parts of the publication date
{date} The publication date
{episode_label} The episode number zero-padded to 3 digits (003), or the publication date if the feed doesn’t number its episodes

{episode_label} is a ready-made fallback, so you don’t have to handle unnumbered shows yourself.

  • Templates are plain str.format-style strings. A / in the folder template starts a new folder.
  • Each folder segment is cleaned up for the file system on its own, and . and .. segments are dropped, so a template can’t write outside the downloads folder.
  • Templates are checked against two sample episodes before saving, one with numbers and one without. A template that only works when a number is present (like {episode_number:03d} with no fallback) is rejected right away instead of failing later on a real episode.

Use the Settings page, which has clickable variables and a live preview, or the CLI:

Terminal window
podvault config
podvault config --folder-template "{podcast_name}/{year}/{episode_label} - {episode_title}"
podvault config --filename-template "{episode_number} - {episode_title}"

PodVault writes tags to MP3 files (ID3) and M4A/M4B/MP4 files (MP4 tags). Other formats (Ogg/Opus, FLAC, WAV…) are downloaded and archived, but their tags are left as the publisher made them.

Each tagged file gets:

Tag Value
Title Episode title (or your custom name)
Artist, Album Podcast name
Year Publication year
Track Episode number, if any
Disc Season number, if any
Comment Episode description
Genre Podcast
Cover art The episode’s image, or the podcast’s cover

A few settings aren’t environment variables. They’re constants in podvault/config.py in the source code:

MAX_RETRIES = 3 # Retry attempts for failed downloads
RETRY_DELAY_BASE = 1 # Base delay for exponential backoff
RETRY_DELAY_MAX = 60 # Maximum delay for exponential backoff
RSS_CACHE_TTL_HOURS = 1 # How long fetched feeds are cached
MAX_FILENAME_LENGTH = 200

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

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