docker compose plugin, not the legacy docker-compose)The fastest path to a running instance:
# Download the compose file curl -O https://raw.githubusercontent.com/CastCharm/castcharm/main/docker-compose.yml # Start in the background docker compose up -d
Then open http://localhost:8000 in your browser. A setup wizard will run on the first visit.
./data/ and downloaded audio files go into ./downloads/, both relative to the directory containing your docker-compose.yml.
The wizard walks you through six short steps. You can change any of these later in Settings.
DOWNLOAD_PATH on the host.Below is the complete file for reference. You can customise paths and the port via environment variables or a .env file placed in the same directory.
services: castcharm: image: ghcr.io/castcharm/castcharm:latest container_name: castcharm ports: - "${PORT:-8000}:8000" volumes: # database and app state - ${DATA_PATH:-./data}:/data # downloaded audio files - ${DOWNLOAD_PATH:-./downloads}:/downloads environment: - DATABASE_URL=sqlite:////data/castcharm.db - DEFAULT_DOWNLOAD_PATH=/downloads - CLEAN_RSS_PATH=/downloads/clean-rss restart: unless-stopped security_opt: - no-new-privileges:true healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/api/status"] interval: 30s timeout: 10s retries: 3 start_period: 20s
Set these in a .env file in the same folder as your docker-compose.yml, or pass them directly to the container.
Most people only need these three:
| Variable | Default | Description |
|---|---|---|
| PORT | 8000 | Host port the app is exposed on. |
| DATA_PATH | ./data | Host path for the SQLite database and application state. Back this up to preserve all feeds, settings, and playback history. |
| DOWNLOAD_PATH | ./downloads | Host path where audio files are saved. Point this at an existing media directory if you want CastCharm to manage files you already have. |
You can safely skip this section unless you're running CastCharm behind a reverse proxy in another container, or building your own image.
| Variable | Default | Description |
|---|---|---|
| CASTCHARM_TRUSTED_PROXIES | (empty) | Comma-separated list of IP addresses that are allowed to tell CastCharm the "real" client IP via the X-Forwarded-For header. The loopback address (127.0.0.1) is trusted by default, so a proxy on the same host needs no change. If your proxy runs in its own container (Traefik, nginx in Docker), add its container IP here — otherwise the login rate-limit will lump every failed attempt together under the proxy's address. |
| APP_VERSION | dev | Version string reported by /api/status and shown in the API docs. Set automatically by official container images; only useful when building your own. |
The login cookie's Secure flag is set automatically based on whether the current request came in over HTTPS, so no configuration is needed for either plain-HTTP or HTTPS deployments.
The DATABASE_URL, DEFAULT_DOWNLOAD_PATH, and CLEAN_RSS_PATH variables inside the container are set automatically by the compose file and do not normally need to be changed.
CastCharm works behind nginx, Caddy, Traefik, or any other reverse proxy. If your proxy runs on the same host as CastCharm (the usual setup), no configuration is needed — just point it at the container and go.
If your proxy runs in a separate container and you want the login rate-limit to see the real client IP instead of the proxy's, set CASTCHARM_TRUSTED_PROXIES to the proxy's container IP. See the Advanced options above.
podcasts.example.com { reverse_proxy localhost:8000 }
server { listen 443 ssl; server_name podcasts.example.com; location / { proxy_pass http://localhost:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
Everything the web interface can do is also available as a REST API. This is what the Android app uses to talk to your server, and it's how scripts and home-automation tools can reach your library.
To let an outside app or script in:
The Android app handles all of this for you: log in once with your username and password, and the app generates and stores its own key automatically.
The keys list in Settings shows when each key was last used. You can:
CastCharm also runs a small daily cleanup that removes keys never used within a week of being created — usually the fingerprint of a failed enrolment.
Full API reference with an interactive "try it out" panel is at /api/docs on your instance (e.g. http://localhost:8000/api/docs). Use the Authorize button to paste an API key for testing.
DATA_PATH/castcharm.db. This single file contains all feeds, episode records, settings, and playback history. Copy it to back everything up.DOWNLOAD_PATH/, organised as Podcast Name/YYYY/filename.mp3 by default.To restore: stop the container, replace the files, start again.
If you prefer to build the image locally rather than pulling from the registry:
git clone https://github.com/CastCharm/castcharm cd castcharm docker compose up -d --build
# Pull the latest image and restart docker compose pull docker compose up -d
Database migrations run automatically on startup. No manual steps are required when upgrading.