Skip to content

Official Docker image

Castopod publishes a single official Docker image to the Docker Hub as part of its automated build process:

Castopod requires a MySQL-compatible database to function. Optionally, a Redis service can be configured as the caching layer.

  • 1.x.x, specific version build (since 1.0.0)
  • 1, latest build for version 1
  • latest, latest version build
  • develop [unstable], latest development branch build

Other unstable channels (e.g., beta, next, 2-next) may be actively pushed during development phases. See all tags in the docker hub.

  1. Install docker and docker compose

  2. Create a compose.yml file with the following:

    services:
    castopod:
    image: castopod/castopod:1 # Pin to a specific version during production
    container_name: "castopod"
    volumes:
    - castopod-media:/app/public/media
    environment:
    MYSQL_DATABASE: castopod
    MYSQL_USER: castopod
    MYSQL_PASSWORD: changeme
    CP_BASEURL: "https://castopod.example.com"
    CP_ANALYTICS_SALT: changeme
    CP_CACHE_HANDLER: redis
    CP_REDIS_HOST: redis
    CP_REDIS_PASSWORD: changeme
    networks:
    - castopod-app
    - castopod-db
    ports:
    - "8080:8080" # HTTP
    - "8443:8443" # HTTPS
    - "8443:8443/udp" # HTTP/3
    restart: unless-stopped
    healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
    interval: 30s
    timeout: 10s
    retries: 3
    start_period: 30s # allows bootstrap/migrations time
    depends_on:
    mariadb:
    condition: service_healthy
    restart: true
    redis:
    condition: service_started
    mariadb:
    image: mariadb:12.1
    container_name: "castopod-mariadb"
    networks:
    - castopod-db
    volumes:
    - castopod-db:/var/lib/mysql
    environment:
    MYSQL_ROOT_PASSWORD: changeme
    MYSQL_DATABASE: castopod
    MYSQL_USER: castopod
    MYSQL_PASSWORD: changeme
    restart: unless-stopped
    healthcheck:
    test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
    start_period: 10s
    interval: 10s
    timeout: 5s
    retries: 3
    redis:
    image: redis:8.4-alpine
    container_name: "castopod-redis"
    command: --requirepass changeme
    volumes:
    - castopod-cache:/data
    networks:
    - castopod-app
    volumes:
    castopod-media:
    castopod-db:
    castopod-cache:
    networks:
    castopod-app:
    castopod-db:
    internal: true

    You have to adapt some variables to your needs (e.g. CP_BASEURL, MYSQL_ROOT_PASSWORD, MYSQL_PASSWORD and CP_ANALYTICS_SALT).

  3. Setup a reverse proxy for TLS (SSL/HTTPS)

    TLS is mandatory for ActivityPub to work. This job can easily be handled by a reverse proxy, for example with Caddy:

    #castopod
    castopod.example.com {
    reverse_proxy localhost:8080
    }
  4. Run docker compose up -d, wait for it to initialize and head on to https://castopod.example.com/cp-install to finish setting up Castopod!

  5. You’re all set, start podcasting! 🎙️🚀

Variable nameType (default)Default
CP_BASEURLstringundefined
CP_MEDIA_BASEURL?stringCP_BASEURL
CP_ADMIN_GATEWAY?string"cp-admin"
CP_AUTH_GATEWAY?string"cp-auth"
CP_ANALYTICS_SALTstringundefined
CP_DATABASE_HOSTNAME?string"mariadb"
CP_DATABASE_NAME?stringMYSQL_DATABASE
CP_DATABASE_USERNAME?stringMYSQL_USER
CP_DATABASE_PASSWORD?stringMYSQL_PASSWORD
CP_DATABASE_PREFIX?string"cp_"
CP_CACHE_HANDLER["file" or "redis"]"file"
CP_REDIS_HOST?string"localhost"
CP_REDIS_PASSWORD?stringnull
CP_REDIS_PORT?number6379
CP_REDIS_DATABASE?number0
CP_EMAIL_SMTP_HOST?stringundefined
CP_EMAIL_FROM?stringundefined
CP_EMAIL_SMTP_USERNAME?string"localhost"
CP_EMAIL_SMTP_PASSWORD?stringnull
CP_EMAIL_SMTP_PORT?number25
CP_EMAIL_SMTP_CRYPTO["tls" or "ssl"]"tls"
CP_ENABLE_2FA?booleanundefined
CP_MEDIA_FILE_MANAGER?stringundefined
CP_MEDIA_S3_ENDPOINT?stringundefined
CP_MEDIA_S3_KEY?stringundefined
CP_MEDIA_S3_SECRET?stringundefined
CP_MEDIA_S3_REGION?stringundefined
CP_MEDIA_S3_BUCKET?stringundefined
CP_MEDIA_S3_PROTOCOL?numberundefined
CP_MEDIA_S3_PATH_STYLE_ENDPOINT?booleanundefined
CP_MEDIA_S3_KEY_PREFIX?stringundefined
CP_DISABLE_HTTPS?[0 or 1]undefined
PHP_MEMORY_LIMIT?number (with suffix)512M
PHP_UPLOAD_MAX_FILE_SIZE?number (with suffix)512M
PHP_POST_MAX_SIZE?number (with suffix)512M
PHP_MAX_EXECUTION_TIME?number300
PHP_OPCACHE_ENABLE?[0 or 1]1