Applications Azure

Castopod 1.15 on Ubuntu 24.04 on Azure User Guide

| Product: Castopod 1.15 on Ubuntu 24.04 LTS on Azure

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, hosts multiple podcasts on one instance, and has ActivityPub 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 episodes be placed on any website. The cloudimg image ships Castopod 1.15 served by nginx and PHP 8.3 FPM on a hardened, fully patched Ubuntu 24.04 LTS base, together with a bundled local MariaDB server and ffmpeg for video clips, so the appliance is complete and useful on its own. The install wizard is already completed, so the platform is ready the moment the instance boots. The bundled MariaDB listens only on the loopback interface (127.0.0.1:3306) and keeps its data on a dedicated Azure data disk. A unique administrator password is generated on the first boot of every VM. Backed by 24/7 cloudimg support.

What is included:

  • Castopod 1.15 served by nginx and PHP 8.3 FPM, managed by systemd
  • A bundled MariaDB server holding the Castopod database, already installed and ready
  • 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 first boot 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
  • MariaDB bound to 127.0.0.1 only, never exposed to the network
  • A dedicated Azure data disk carrying both the MariaDB database and the Castopod application tree with uploaded podcast media
  • A systemd timer running Castopod's scheduled tasks (Fediverse broadcasting, WebSub, RSS imports) every minute
  • nginx.service, php8.3-fpm.service and mariadb.service as enabled systemd units
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus 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 catalogues or heavy media processing. NSG inbound: allow 22/tcp from your management network, 80/tcp for the application and 443/tcp if 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 cloudimg, 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 Review + create then Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name castopod \
  --image <marketplace-image-urn> \
  --size Standard_D2s_v3 \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Then open ports 80 and 443:

az vm open-port --resource-group <your-rg> --name castopod --port 80,443

Step 3 - Confirm the services are running

SSH in as azureuser and confirm nginx, PHP FPM and MariaDB are all active. Note that MariaDB listens only on 127.0.0.1:3306 while nginx serves Castopod on port 80.

systemctl is-active nginx php8.3-fpm mariadb
ss -tlnp | grep -E ':80 |:3306 ' | sed 's/  */ /g'

The nginx, php8.3-fpm and mariadb services active, with nginx on port 80 and MariaDB bound to loopback 127.0.0.1:3306

Step 4 - Retrieve the per VM administrator password

Every VM generates its own Castopod administrator password on first boot and writes it, along with the login email and the application URL, to a root only credentials file. Read it with sudo:

sudo cat /root/castopod-credentials.txt

The per VM Castopod credentials file, showing the admin login email, the generated password masked, the application URL and the loopback MariaDB details

You sign in to Castopod with the email and password from this file. On the box 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.

The Castopod admin sign in page showing the email address and password fields and the login button

After signing in you land on the Castopod admin dashboard, which summarises your podcasts, episodes and storage usage at a glance.

The Castopod admin dashboard after signing in, with the left navigation, the podcasts, episodes and storage tiles, and the monthly storage and bandwidth charts

Step 6 - Create your first podcast

Open Podcasts then 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.

The Castopod create podcast form with the cover upload, title, markdown description and podcast type fields

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 are shown at the top of the podcast dashboard.

The Castopod podcast dashboard for a show, with the RSS feed link, the Fediverse handle and the episodes, analytics, broadcast and monetization navigation

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, so 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 cloudimg image ships with an empty database and no shipped superadmin, and the real per VM administrator is created with a unique random password on the first boot of every VM. No known or blank credential authenticates. You can prove this with the built in round trip check, which confirms 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.sh

The admin account as the only Castopod superadmin, and the round trip check confirming the per VM admin authenticates via the Castopod login form while blank and weak guesses are rejected

Step 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 (bind mounted onto /var/lib/mysql), and the Castopod application tree with its uploaded podcast media lives on the same disk (bind mounted onto /var/www/castopod), so all of your podcast data is kept separate from the operating system disk and rides with the VM:

grep CP_VERSION /var/www/castopod/app/Config/Constants.php
curl -sI http://127.0.0.1/healthz | head -1
findmnt -no SOURCE,TARGET,FSTYPE /data
findmnt -no SOURCE,TARGET /var/lib/mysql
findmnt -no SOURCE,TARGET /var/www/castopod

The installed Castopod version 1.15.5, the healthz endpoint returning 200, and the ext4 data disk mounted at /data and bind mounted onto /var/lib/mysql and /var/www/castopod

Adding 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 and 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 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-fpm

Scheduled 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 -5

Backing 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 media

Copy 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 catalogues 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 above, or front the VM with Azure Application Gateway.
  • The bundled MariaDB listens on 127.0.0.1 only and is never reachable from the network. Administer it through Castopod or over SSH with sudo mariadb.
  • The administrator password is unique per VM and no known or blank credential authenticates. Keep /root/castopod-credentials.txt protected. To rotate the password, sign in and change it under your account, or reset it from the box with the Castopod CLI.
  • The per instance analytics salt (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/tcp and 443/tcp in 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. This image is an independent packaging of the open source Castopod software by cloudimg and is not affiliated with, sponsored by, or endorsed by the Castopod project or Ad Aures.

Support

This image is maintained by cloudimg with 24/7 support. If you need help deploying or operating Castopod on Azure, contact us at cloudimg.co.uk.