Self-Hosting Castopod with Docker Compose

What Is Castopod?

Castopod is an open-source podcast hosting platform with a unique twist: it’s ActivityPub-native, meaning your podcast becomes a federated social account. Followers on Mastodon, Pleroma, or any Fediverse platform can interact with your episodes directly. Beyond federation, it covers everything a podcast host needs — RSS feed generation, episode management, analytics, and multi-podcast support. It replaces Anchor, Buzzsprout, and Podbean. Official site

Why Self-Host Your Podcast?

Commercial podcast hosts charge $12-24/month, limit storage or bandwidth, and own the relationship with podcast directories. Self-hosting means:

  • Unlimited episodes and storage (your hardware)
  • Full analytics without platform gatekeeping
  • Your own RSS feed URL that never changes (even if you switch hosts)
  • ActivityPub integration for direct audience engagement
  • No platform taking a cut of your sponsorship revenue

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 1 GB of free RAM
  • Storage for audio files (plan 100 MB per episode hour at 128 kbps)
  • A domain name (required for RSS feeds and ActivityPub)

Docker Compose Configuration

services:
  castopod-db:
    image: mariadb:11.4
    container_name: castopod-db
    environment:
      MYSQL_ROOT_PASSWORD: change-this-root-password
      MYSQL_DATABASE: castopod
      MYSQL_USER: castopod
      MYSQL_PASSWORD: change-this-db-password
    volumes:
      - castopod-db:/var/lib/mysql
    networks:
      - castopod
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 5

  castopod-redis:
    image: redis:7.4-alpine
    container_name: castopod-redis
    volumes:
      - castopod-redis:/data
    networks:
      - castopod
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  castopod:
    image: castopod/castopod:1.15.5
    container_name: castopod
    ports:
      - "8080:8080"
    environment:
      CP_BASEURL: https://podcast.example.com
      CP_MEDIA_BASEURL: https://podcast.example.com
      CP_ADMIN_GATEWAY: cp-admin           # Admin panel URL path
      CP_AUTH_GATEWAY: cp-auth             # Authentication URL path
      CP_DATABASE_HOSTNAME: castopod-db
      CP_DATABASE_NAME: castopod
      CP_DATABASE_USERNAME: castopod
      CP_DATABASE_PASSWORD: change-this-db-password
      CP_CACHE_HANDLER: redis
      CP_REDIS_HOST: castopod-redis
      CP_REDIS_PORT: 6379
    volumes:
      - castopod-media:/var/www/castopod/public/media
    networks:
      - castopod
    depends_on:
      castopod-db:
        condition: service_healthy
      castopod-redis:
        condition: service_healthy
    restart: unless-stopped

networks:
  castopod:

volumes:
  castopod-db:
  castopod-redis:
  castopod-media:

Start Castopod:

docker compose up -d

Initial Setup

  1. Navigate to http://your-server:8080/cp-install
  2. Complete the installation wizard:
    • Set your instance name
    • Create the super admin account
    • Configure your podcast metadata
  3. After install, the admin panel is at /cp-admin
  4. Create your first podcast: fill in title, description, cover art, and category
  5. Upload your first episode with title, description, and audio file

Key Features

FeatureDetails
Multi-podcastHost multiple shows from one instance
RSS feedAuto-generated, compliant with Apple/Spotify/Google specs
ActivityPubYour podcast is a Fediverse account — followers interact directly
AnalyticsDownload stats, geographic data, listening apps, episode trends
ChaptersPodcast 2.0 chapter markers with images and links
TranscriptsUpload SRT/VTT transcripts for accessibility
SoundbitesHighlight clips for social sharing
Video podcastsUpload video episodes alongside audio
MonetizationPodcast Value (Value4Value), funding links
Multi-userContributors, editors, admin roles per podcast
Embeddable playerEmbed episodes on any website

ActivityPub Integration

Castopod’s ActivityPub support means:

  • Each podcast gets a Fediverse handle (e.g., @[email protected])
  • New episodes appear as posts in followers’ timelines
  • Followers can comment, boost, and interact from Mastodon or any ActivityPub platform
  • Comments from the Fediverse appear on your episode page
  • No separate social media management needed — your podcast IS your social presence

This is unique to Castopod. No other podcast host integrates with the Fediverse natively. For more on ActivityPub, see The Fediverse Explained.

Podcast Directory Submission

After creating your podcast and publishing at least one episode, submit your RSS feed to directories:

DirectorySubmission URLTurnaround
Apple Podcastspodcasters.apple.com1-5 days
Spotifypodcasters.spotify.com1-3 days
Google Podcastspodcastsmanager.google.com2-5 days
Pocket Castspocketcasts.com/submitAutomatic
Podcast Indexpodcastindex.org/addAutomatic

Your RSS feed URL: https://podcast.example.com/@yourshow/feed.xml

Reverse Proxy

Behind Nginx Proxy Manager:

Proxy Host: podcast.example.com → http://castopod:8080
Enable: WebSocket Support, Force SSL

Set CP_BASEURL to your public URL including https://. This is critical — the RSS feed and ActivityPub federation use this URL.

Backup

VolumeContainsPriority
castopod-dbEpisodes, analytics, user accounts, settingsCritical
castopod-mediaAudio files, cover art, transcriptsCritical
castopod-redisCache (regenerated automatically)Low

The media volume is your most space-intensive backup target. Each episode hour at 128 kbps ≈ 60 MB.

# Database backup
docker exec castopod-db mariadb-dump -u castopod -p'change-this-db-password' castopod > castopod-backup-$(date +%Y%m%d).sql

# Media backup (rsync to backup location)
rsync -av /var/lib/docker/volumes/castopod-media/_data/ /backup/castopod-media/

See Backup Strategy for automated approaches.

Troubleshooting

Install wizard shows 500 error

Symptom: /cp-install returns a server error. Fix: Check that MariaDB is healthy (docker logs castopod-db). Ensure CP_DATABASE_PASSWORD matches in both containers. Check Castopod logs: docker logs castopod.

ActivityPub federation not working

Symptom: Podcast has a Fediverse handle but nobody can find or follow it. Fix: CP_BASEURL must match your actual public URL exactly (including https://). ActivityPub requires HTTPS. Verify .well-known/webfinger is accessible: curl https://podcast.example.com/.well-known/webfinger?resource=acct:[email protected].

Audio files won’t upload

Symptom: Episode upload fails or times out. Fix: Check the castopod-media volume has sufficient space. For large files, increase your reverse proxy upload limit (Nginx: client_max_body_size 500M). PHP max upload size inside the container defaults to 150 MB.

RSS feed not validating

Symptom: Apple Podcasts or Spotify rejects your feed. Fix: Ensure cover art is at least 1400×1400 pixels (Apple requirement). Check your podcast has a valid category set. Test your feed at https://podba.se/validate/.

Resource Requirements

  • RAM: ~250 MB idle (Castopod + MariaDB + Redis), ~500 MB during file processing
  • CPU: Low — audio transcoding is not done server-side (upload pre-encoded files)
  • Disk: 500 MB for application, plus ~60 MB per episode hour of audio

Verdict

Castopod is the best self-hosted podcast platform, and the ActivityPub integration is genuinely compelling. Your podcast becomes a first-class Fediverse citizen — no separate social media strategy needed. For podcasters who just need RSS hosting without the social features, AzuraCast covers radio streaming with podcast RSS as a secondary feature. But if you’re starting a podcast in 2026, Castopod’s Fediverse-native approach is the most forward-looking option.

Frequently Asked Questions

What does ActivityPub integration mean for my podcast?

Your Castopod podcast becomes a Fediverse account that Mastodon, Pleroma, and Pixelfed users can follow. When you publish a new episode, it appears in their feeds as a post. Followers can comment, boost, and interact directly — your podcast has built-in social engagement without needing separate social media accounts.

Can I import my podcast from Anchor or another host?

Yes. Castopod supports importing podcasts via RSS feed URL. Enter your existing podcast’s RSS feed during setup, and Castopod downloads all episode metadata and audio files. After import, update your podcast directories (Apple, Spotify, etc.) to point to Castopod’s RSS feed URL for a seamless migration.

Does Castopod submit my podcast to Apple Podcasts and Spotify?

No. Castopod generates a standard RSS feed that you manually submit to podcast directories. Go to Apple Podcasts Connect, Spotify for Podcasters, and other platforms, and submit your Castopod RSS URL. Once accepted, new episodes automatically appear on those platforms through the feed.

Can Castopod host multiple podcasts?

Yes. A single Castopod instance can host multiple podcasts, each with its own RSS feed, analytics, and Fediverse presence. This is useful if you run multiple shows — manage them all from one dashboard without separate installations.

Does Castopod include analytics?

Yes. Castopod has built-in analytics that track downloads, listening duration, geographic distribution, and user agents — all without third-party trackers. The analytics comply with IAB Podcast Measurement Guidelines for accurate download counting. Data stays on your server.

What audio format should I upload to Castopod?

Upload pre-encoded MP3 files (128-192 kbps for talk, 256-320 kbps for music). Castopod does not transcode audio server-side — it serves exactly what you upload. MP3 is the universal standard for podcast distribution and works everywhere. Include proper ID3 tags (title, artist, artwork) before uploading.

Comments