Installation

Docker + Docker Compose · runs on any Linux, macOS, or Windows host

Requirements

Quick start

The fastest path to a running instance:

bash
# 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.

Default paths: the database is saved to ./data/ and downloaded audio files go into ./downloads/, both relative to the directory containing your docker-compose.yml.

First run

The wizard walks you through six short steps. You can change any of these later in Settings.

  1. Login — pick a username and password, or skip this step to leave your instance open.
  2. Theme — pick a colour scheme.
  3. Timezone — used for date-prefixed filenames and year-based folders.
  4. Downloads folder — where inside the container to save audio files. This maps to DOWNLOAD_PATH on the host.
  5. File options — filename format and folder organisation.
  6. External API — leave on if you plan to use the Android app or scripts; leave off if you'll only ever use the web interface.

Full docker-compose.yml

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.

docker-compose.yml
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

Environment variables

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.

Advanced options

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.

Running behind a reverse proxy

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.

Caddy example

Caddyfile
podcasts.example.com {
    reverse_proxy localhost:8000
}

nginx example

nginx.conf
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;
    }
}

External API access

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:

  1. Open Settings → External API in the web interface.
  2. Make sure Enable external API access is on.
  3. Click Generate new key and give it a name (e.g. "Phone" or "Backup script").
  4. Copy the key that appears — it's only shown once.

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.

Managing keys

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.

Interactive API docs

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 & backups

To restore: stop the container, replace the files, start again.

Build from source

If you prefer to build the image locally rather than pulling from the registry:

bash
git clone https://github.com/CastCharm/castcharm
cd castcharm
docker compose up -d --build

Updating

bash
# 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.