Castopod
Overview
Castopod is the open source platform for hosting and publishing podcasts. It serves standards-compliant RSS feeds with Podcasting 2.0 tags such as chapters, transcripts, funding and location, and it hosts multiple podcasts on one instance. ActivityPub is built in, so every podcast is its own Fediverse account that listeners on Mastodon and other platforms can follow, comment on and share. Privacy-friendly analytics report episode downloads by country and player with no third-party trackers, and embeddable players let you place episodes on any website.
The SecureAnyCloud image ships Castopod 1.15 served by nginx and PHP 8.3 FPM on a hardened Ubuntu 24.04 LTS base, patched at build time. A bundled local MariaDB server and ffmpeg for video clips make the appliance complete on its own, and the install wizard is already completed, so the platform is ready the moment the instance boots.
What you get:
- Castopod 1.15 served by nginx and PHP 8.3 FPM, managed by systemd.
- A bundled MariaDB server that holds the Castopod database, already installed and ready. It is bound to
127.0.0.1only (port 3306 on the loopback interface) and is never exposed to the network, and it keeps its data on the dedicated data disk. - ffmpeg installed for Castopod video clip generation.
- The install wizard already completed, so no setup wizard is ever exposed.
- A per-VM administrator password, generated on the first boot of every VM and recorded in a root-only file.
- No shipped default login. The image ships an empty database, and the real per-VM superadmin is created on first boot.
- A dedicated Azure data disk that carries both the MariaDB database and the Castopod application tree with uploaded podcast media.
- A systemd timer that runs Castopod's scheduled tasks (Fediverse broadcasting, WebSub, RSS imports) every minute.
nginx.service,php8.3-fpm.serviceandmariadb.serviceas enabled systemd units.- An unauthenticated
/healthzendpoint for Azure Load Balancer health probes. - 24/7 SecureAnyCloud support.
Prerequisites
- An active Azure subscription.
- An SSH key pair.
- A VNet and subnet in the target region.
- Standard_D2s_v3 (2 vCPU / 8 GiB RAM) is a sensible starting point for typical use. A larger size such as Standard_D4s_v3 suits busier catalogs or heavy media processing.
- NSG inbound rules that allow
22/tcpfrom your management network,80/tcpfor the application and443/tcpif you terminate TLS on the VM.
The bundled MariaDB is never exposed. It listens on 127.0.0.1 only, so port 3306 stays off the network.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Castopod by SecureAnyCloud, and select Create.
On Basics, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22), HTTP (80) and HTTPS (443).
Review the dedicated data disk on the Disks tab, then choose Review + create and Create.
Step 2 - Deploy from the Azure CLI
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:castopod-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name castopod \
--image sac1647283583153:castopod-ubuntu-24-04:default:latest \
--size Standard_D2s_v3 \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku StandardThen open ports 80 and 443:
az vm open-port --resource-group <your-rg> --name castopod --port 80,443Step 3 - Confirm the services are running
SSH in as azureuser and confirm that nginx, PHP FPM and MariaDB are all active. MariaDB listens only on 127.0.0.1:3306, while nginx serves Castopod on port 80.
systemctl is-active nginx php8.3-fpm mariadbss -tlnp | grep -E ':80 |:3306 ' | sed 's/ */ /g'Step 4 - Retrieve the per-VM administrator password
Every VM generates its own Castopod administrator password on first boot. It writes the password, along with the login email and the application URL, to a root-only credentials file. Read the file with sudo:
sudo cat /root/castopod-credentials.txtYou sign in to Castopod with the email and password from this file. On the VM itself, you can also run sudo mariadb to reach the database directly over the local socket without a password.
Step 5 - Sign in
Browse to http://<vm-public-ip>/cp-admin. You land on the Castopod admin sign-in page. Enter the admin email and the password from Step 4.
After you sign in, you land on the Castopod admin dashboard, which summarizes your podcasts, episodes and storage usage at a glance.
Step 6 - Create your first podcast
Open Podcasts > New podcast. Give the podcast a square cover image (at least 1400px), a title and a description. Pick the type, language and category, and set the Fediverse handle that listeners will use to follow the show.
Save to create the podcast.
Step 7 - Add episodes and manage the podcast
Each podcast has its own dashboard for episodes, analytics, broadcasting and contributors. Open the podcast, choose Add an episode, upload the audio file and publish.
The RSS feed link and the Fediverse handle appear at the top of the podcast dashboard.
Step 8 - Publish your RSS feed and federate
Castopod serves a standards-compliant RSS feed with Podcasting 2.0 tags for every podcast. Share the feed link from the podcast dashboard and submit it to Apple Podcasts, Spotify and other directories.
Because ActivityPub is built in, each podcast is also a Fediverse account. Listeners on Mastodon and other platforms can follow the handle, comment on episodes and boost them. Castopod's scheduled tasks broadcast new episodes to the Fediverse and run WebSub and RSS imports automatically every minute.
Step 9 - No known or default credentials
The SecureAnyCloud image ships with an empty database and no shipped superadmin. The real per-VM administrator is created with a unique random password on the first boot of every VM, and no known or blank credential authenticates.
You can prove this with the built-in round-trip check. It confirms that the per-VM administrator signs in through Castopod's own login form, while a blank password and common weak guesses are all rejected. The admin account is the only Castopod superadmin:
sudo mariadb -N -B castopod -e "SELECT CONCAT(username,' (Castopod superadmin)') FROM cp_users WHERE is_owner=1"sudo bash /usr/local/sbin/castopod-cred-roundtrip.shStep 10 - Verify the stack and where your data lives
Confirm the installed Castopod release, the health endpoint and the dedicated data disk.
The MariaDB database lives on the data disk mounted at /data and bind-mounted onto /var/lib/mysql. The Castopod application tree with its uploaded podcast media lives on the same disk, bind-mounted onto /var/www/castopod. All of your podcast data is therefore kept separate from the operating system disk and moves with the VM:
grep CP_VERSION /var/www/castopod/app/Config/Constants.phpcurl -sI http://127.0.0.1/healthz | head -1findmnt -no SOURCE,TARGET,FSTYPE /data
findmnt -no SOURCE,TARGET /var/lib/mysql
findmnt -no SOURCE,TARGET /var/www/castopodAdding your own domain and TLS
A real podcast needs a stable public address, because directories and apps remember your feed URL. Point a DNS record at your VM, then obtain a certificate with Let's Encrypt:
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain>Then set your domain as the Castopod base URL, so that feeds and links use it, and clear the cache:
sudo sed -i 's|^app.baseURL=.*|app.baseURL="https://<your-domain>/"|' /var/www/castopod/.env
sudo sed -i 's|^media.baseURL=.*|media.baseURL="https://<your-domain>/"|' /var/www/castopod/.env
sudo -u www-data php /var/www/castopod/spark cache:clear
sudo systemctl restart php8.3-fpmScheduled tasks
Castopod's scheduled tasks (Fediverse broadcasting, WebSub, RSS imports and video clips) run automatically every minute through a systemd timer. Check the timer and its schedule:
systemctl status castopod-tasks.timer --no-pager | head -5Backing up
Your podcast data is the Castopod database plus the uploaded media. Dump the database and archive the media directory:
sudo mysqldump castopod > /tmp/castopod-backup.sql
sudo tar czf /tmp/castopod-media-backup.tar.gz -C /var/www/castopod/public mediaCopy both files off the VM on your usual schedule.
To restore, load the SQL dump into the castopod database and unpack the archive back to /var/www/castopod/public/media. For large catalogs, you can move media to S3-compatible object storage, configured in the Castopod settings.
Security notes
- Castopod serves plain HTTP on port 80 out of the box. For anything beyond a trusted network, add your own domain and TLS as described above, or front the VM with Azure Application Gateway.
- The bundled MariaDB listens on
127.0.0.1only and is never reachable from the network. Administer it through Castopod or over SSH withsudo mariadb. - The administrator password is unique per VM, and no known or blank credential authenticates. Keep
/root/castopod-credentials.txtprotected. To rotate the password, sign in and change it under your account, or reset it from the VM with the Castopod CLI. - The per-instance analytics salt, which is used to hash listener IP addresses, is regenerated on first boot. Keep it private.
- Apply operating system updates regularly with
sudo apt update && sudo apt upgrade. Unattended security updates are enabled by default. - Restrict inbound
80/tcpand443/tcpin your NSG to the networks that need access.
Trademark
Castopod is an open source project distributed under the GNU Affero General Public License version 3. SecureAnyCloud packages the open source Castopod software independently. It is not affiliated with, sponsored by or endorsed by the Castopod project or Ad Aures.
Support
SecureAnyCloud maintains this image and provides 24/7 support. If you need help deploying or operating Castopod on Azure, contact us at secureanycloud.com.
Deploy on Azure
Launch Castopod 1.15 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Castopod is a free, open source platform for hosting and publishing podcasts. It serves standards-compliant RSS feeds with Podcasting 2.0 tags (chapters, transcripts, funding, location) and hosts multiple podcasts on one instance. ActivityPub is built in, so every podcast is its own Fediverse account that listeners on Mastodon and other platforms can follow, comment on and share. Privacy-friendly analytics report episode downloads by country and player with no third-party trackers, and embeddable players let you place episodes on any website.
This SecureAnyCloud Amazon Machine Image delivers Castopod fully installed and configured on Ubuntu 24.04, so a complete podcast platform is running within minutes of launch. Castopod is a CodeIgniter 4 application on PHP 8.3 with OPcache, served by nginx with php-fpm and backed by MariaDB. The install wizard is already completed, so you land directly on the admin sign-in page.
This guide covers connecting to your instance, retrieving the per-instance administrator credentials, signing in, creating your first podcast and episode, and enabling HTTPS.
Architecture at a glance
- Application: Castopod 1.15 (CodeIgniter 4), served from /var/www/castopod/public
- Web server: nginx, listening on port 80
- PHP: PHP 8.3 (php8.3-fpm) with OPcache
- Database: MariaDB 10.11, with its data directory on a dedicated EBS volume at /var/lib/mysql
- Application storage: code and uploaded media on a dedicated EBS volume at /var/www
- Scheduled tasks: castopod-tasks.timer runs spark tasks:run every minute
- Admin console: http://<instance-public-ip>/cp-admin
The database tier and the application tier (including all uploaded podcast media under /var/www/castopod/public/media) each live on their own independently resizable EBS volume, separate from the operating-system disk. You can grow storage for either tier without disturbing the other.
Connecting to your instance
Connect over SSH on port 22 as the default login user for your operating system. On Ubuntu 24.04, the SSH login user is ubuntu.
ssh -i /path/to/your-key.pem ubuntu@<instance-public-ip>Replace <instance-public-ip> with the public IPv4 address of your instance, which the EC2 console shows. Replace /path/to/your-key.pem with the private key you launched the instance with.
Per-instance credentials
On the first boot of every instance, a one-shot service (castopod-firstboot.service) generates state that is unique to that instance:
- A fresh database schema. The image ships with no content.
- A fresh MariaDB database password.
- A fresh analytics salt, used to anonymize listener IP addresses.
- A fresh administrator (superadmin) password.
The instance's own address is set as the application base URL automatically. No shared or default credentials and no content ship in the image. Retrieve the generated administrator login with:
sudo cat /root/castopod-credentials.txtThe file (mode 0600, root only) contains the administrator email and password, the admin console URL and the database credentials.
Castopod signs in by email. The generated superadmin is admin / admin@example.com with a per-instance random password.
Verifying the service
The services that back Castopod should all report active: nginx, php-fpm, MariaDB and the scheduled-tasks timer.
systemctl is-active nginx php8.3-fpm mariadb castopod-tasks.timerExpected output:
active active active activeConfirm the installed Castopod version:
grep -o "CP_VERSION., .[0-9.]*" /var/www/castopod/app/Config/Constants.phpCP_VERSION', '1.15.5Confirm the admin sign-in page is served:
curl -s -o /dev/null -w '%{http_code}\n' http://localhost/cp-auth/login200Confirm the database and application tiers are on their dedicated EBS volumes:
df -h /var/www /var/lib/mysqlFilesystem Size Used Avail Use% Mounted on /dev/nvme2n1 30G 173M 28G 1% /var/www /dev/nvme1n1 20G 195M 19G 2% /var/lib/mysqlSigning in
Browse to the admin console and sign in with the administrator email and password from /root/castopod-credentials.txt:
http://<instance-public-ip>/cp-adminAfter you sign in, you land on the Admin dashboard, which shows podcasts, episodes and storage use across the whole instance.
Change the administrator password, and create additional named user accounts (with per-podcast roles) from Users in the admin sidebar.
Creating your first podcast
In the admin sidebar, choose Podcasts > New podcast. Provide a title, a handle (the podcast's unique name in URLs and on the Fediverse), a description, a language, a category and a square cover image of at least 1400x1400 pixels, then save.
Each podcast gets its own dashboard with episodes, analytics, broadcast (Fediverse and WebSub) and contributor management:
To publish your first episode, choose Add an episode, upload your audio file (mp3 or m4a), give it a title and description, save, and then choose Publish.
The first time, you must also publish the podcast itself. Castopod shows a draft-mode banner until you do.
Once published, the episode has a public page with an embeddable web player, comments and Fediverse activity, and is included in the podcast's RSS feed at http://<instance-public-ip>/@<handle>/feed.xml:
Every podcast is also a Fediverse actor: listeners on Mastodon and other ActivityPub platforms can follow @<handle>@<your-domain>, and announcement posts you write from the podcast's page federate to followers.
Scheduled tasks
Castopod relies on a once-a-minute background task runner for Fediverse broadcasting, WebSub hub notification, RSS imports and video-clip generation. The image wires this up as a systemd timer (castopod-tasks.timer), so no cron configuration is needed:
systemctl list-timers castopod-tasks.timer --no-pagerNEXT LEFT LAST PASSED UNIT ACTIVATES Fri 2026-06-12 15:20:00 UTC 2s Fri 2026-06-12 15:19:01 UTC 55s ago castopod-tasks.timer castopod-tasks.service 1 timers listed. Pass --all to see loaded but inactive timers, too.Administering from the command line
Castopod ships CodeIgniter's spark CLI. Run admin tasks as the www-data user from the application root:
sudo -u www-data php /var/www/castopod/spark <command>Common tasks:
... spark listlists every available command.... spark tasks:runruns the scheduled tasks immediately. The timer does this every minute.... spark cache:clearclears the application cache.
The instance configuration (base URL, database connection, email settings) lives in /var/www/castopod/.env. To configure outgoing email, which password-reset links and premium-subscriber instructions need, add your SMTP gateway to that file. The user guide on email configuration is at docs.castopod.org. After editing, restart php-fpm with sudo systemctl restart php8.3-fpm.
Manage the services with systemctl (nginx, php8.3-fpm, mariadb, castopod-tasks.timer).
Enabling HTTPS
The image serves Castopod over HTTP on port 80 so it works immediately behind whatever networking you place in front of it. For production podcast hosting, serve Castopod over HTTPS on a proper domain, because podcast directories and Fediverse federation expect it.
Point a DNS name at the instance's public IP, then install Certbot and request a certificate. Run the following, replacing the values in angle brackets with your own domain and email:
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com -m you@example.com --agree-tos --no-eff-emailCertbot obtains a certificate and reconfigures nginx for HTTPS. After enabling HTTPS, update Castopod's base URLs in /var/www/castopod/.env to the https:// address:
app.baseURL="https://your-domain.example.com/" media.baseURL="https://your-domain.example.com/" app.forceGlobalSecureRequests=trueThen clear the application cache and restart php-fpm:
sudo -u www-data php /var/www/castopod/spark cache:clear
sudo systemctl restart php8.3-fpmChanging the domain after listeners have subscribed changes your RSS feed URLs, so set up your final domain before you submit feeds to podcast directories.
Support
This is a repackaged open source software product. Castopod itself is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
SecureAnyCloud provides 24/7 technical support for this image by email and chat. Support covers Castopod deployment, upgrades, HTTPS and domain configuration, email and S3 media storage setup, Fediverse federation, RSS migration from other hosts, performance tuning and database administration.
All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on AWS
Launch Castopod with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com