Applications Azure

PodFetch on Ubuntu 24.04 on Azure User Guide

| Product: PodFetch on Ubuntu 24.04 LTS on Azure

Overview

PodFetch is an open source, self hosted podcast manager and downloader. You subscribe to podcast RSS feeds, PodFetch automatically downloads new episodes on a schedule, and you stream your whole library from anywhere through a modern in browser web player or any compatible mobile app. It also speaks the gpodder, Subsonic and AudiobookShelf sync APIs. The cloudimg image serves PodFetch 5.2.2 behind an nginx reverse proxy on a hardened, fully patched Ubuntu 24.04 LTS base, with the podcast database and downloaded episodes on a dedicated data disk.

The image is secure by default. No password is baked into it: on the first boot of every VM a unique administrator password is generated and written to a root only file, so no two deployments share a login. PodFetch's own HTTP Basic authentication and an nginx Basic Auth gate both protect the application with that per VM password, and because the PodFetch server binds to all interfaces the host firewall keeps its internal port off the network so the nginx reverse proxy on port 80 is the only reachable surface. Backed by 24/7 cloudimg support.

What is included:

  • PodFetch 5.2.2 served behind nginx, managed by systemd
  • The PodFetch web player and REST/gpodder/Subsonic/AudiobookShelf APIs on :80
  • A unique administrator password generated on first boot, never baked or shared
  • Layered HTTP Basic authentication: an nginx Basic Auth gate in front of PodFetch's own native Basic Auth, both using the per VM password
  • The PodFetch server kept off the network by ufw, reachable only through the nginx reverse proxy
  • A dedicated Azure data disk at /var/lib/podfetch for the SQLite database and the downloaded podcast library
  • podfetch.service and nginx.service as enabled systemd units
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point; size up for larger libraries or more concurrent listeners. NSG inbound: allow 22/tcp from your management network and 80/tcp for the web player. PodFetch serves plain HTTP on port 80; for production, terminate TLS in front of it with your own domain. The PodFetch server never faces the network directly: it is bound off the network by ufw and reached only through nginx on port 80, so its internal port 8000 stays private.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for PodFetch 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) and HTTP (80). 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 podfetch \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Then open port 80 to the web player:

az vm open-port --resource-group <your-rg> --name podfetch --port 80

Step 3 - Confirm the services are running

SSH in as azureuser and confirm PodFetch and nginx are active. Note that the PodFetch server listens on port 8000 but ufw keeps that port off the network, while nginx serves the web player on port 80.

systemctl is-active podfetch nginx podfetch-firstboot
sudo ss -tlnp | grep -E ':80 |:8000 ' | sed 's/  */ /g'
sudo ufw status | grep -E '22/tcp|80/tcp|443/tcp'

The podfetch, nginx and podfetch-firstboot services active, nginx listening on port 80 and the PodFetch server on 8000, with ufw allowing only 22, 80 and 443

Step 4 - Retrieve your per VM administrator password

The image ships with no baked password. On the first boot of every VM a one shot service generates a unique administrator password and writes it, together with the site URL and the username, to a root only file. Read it with sudo:

sudo cat /root/podfetch-credentials.txt

The username is admin and the password is unique to this VM. You can prove the whole authentication round trip from the command line at any time with the bundled self test, which confirms that an unauthenticated request is rejected with 401, a wrong password is rejected with 401, and the per VM password is accepted with 200:

sudo /opt/podfetch/podfetch-selftest.sh

You can also check it by hand. The health endpoint is unauthenticated, an unauthenticated API request is challenged, and the per VM password authenticates:

curl -s -o /dev/null -w 'GET /healthz -> HTTP %{http_code}\n' http://127.0.0.1/healthz
curl -s -o /dev/null -w 'GET /api/v1/podcasts (no credentials) -> HTTP %{http_code}\n' http://127.0.0.1/api/v1/podcasts
PODFETCH_PASSWORD=$(sudo grep '^PODFETCH_PASSWORD=' /root/podfetch-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'GET /api/v1/podcasts (per VM password) -> HTTP %{http_code}\n' -u "admin:$PODFETCH_PASSWORD" http://127.0.0.1/api/v1/podcasts

The PodFetch per VM credentials file showing the site URL and admin username, the self test proving 401 without credentials and 200 with the per VM password, and the health endpoint returning HTTP 200

Step 5 - Sign in to the web player

Browse to http://<vm-public-ip>/. Sign in with the username admin and the per VM password from Step 4. PodFetch presents its sign in screen, and once you authenticate you reach the web player. If you would rather not enter the credentials on every visit you can tick the memorize option, though only on a device that is yours.

The PodFetch sign in screen, where you enter the username admin and the per VM administrator password generated on first boot

Step 6 - The PodFetch home screen

After signing in you land in the PodFetch web player. The sidebar lets you move between your podcasts, the episode timeline, favourites and settings, and a search box lets you find and add new podcasts. Because the image ships with an empty library, this is where your podcasts appear once you subscribe to feeds in the next step.

The PodFetch home screen after sign in, showing the navigation sidebar and an empty podcast library ready for your first subscription

Step 7 - Subscribe to a podcast

Open the add or search view, type the name of a podcast or paste an RSS feed URL, and PodFetch searches the PodcastIndex and iTunes directories. Select a result to subscribe, and PodFetch begins downloading episodes on the schedule set by the polling interval so they are ready to stream offline. You can add as many feeds as you like and manage them from the podcasts view.

The PodFetch add podcast view, searching a podcast directory by name so you can subscribe to a feed and start downloading episodes

Step 8 - Verify the stack

Confirm the PodFetch version, that the services are enabled, the web player responds through nginx, and the dedicated data disk mount:

grep podfetch_version /opt/podfetch/VERSION
systemctl is-enabled podfetch nginx
curl -s -o /dev/null -w 'GET /healthz -> HTTP %{http_code}\n' http://127.0.0.1/healthz
findmnt -no SOURCE,TARGET,FSTYPE /var/lib/podfetch

The PodFetch 5.2.2 version, the enabled podfetch and nginx units, the health endpoint returning HTTP 200 through nginx, and the dedicated ext4 data disk mounted at /var/lib/podfetch

Step 9 - Where your data lives

The SQLite database and the downloaded podcast episodes both live on a dedicated Azure data disk mounted at /var/lib/podfetch, separate from the OS disk. This disk is captured into the image and re provisioned on every VM, and you can snapshot and resize it independently as your library grows. Confirm the mount and the free space:

df -h /var/lib/podfetch | tail -1
sudo du -sh /var/lib/podfetch/db /var/lib/podfetch/podcasts

Step 10 - Connect a podcast app

PodFetch exposes gpodder, Subsonic and AudiobookShelf compatible sync APIs, so a range of mobile and desktop podcast apps can sync subscriptions and playback against your server. Point the app at http://<vm-public-ip>/ and sign in with the admin username and the per VM password. To stream episodes with authentication enabled you may need to generate an API key for your user from the profile view in the web UI. You can also invite additional users from the user administration view so a household or team shares one server while you keep administrative control.

Security notes

  • PodFetch serves plain HTTP on port 80. For production, put it behind your own TLS terminating reverse proxy or an Azure Application Gateway with a certificate for your domain, and restrict port 80 in the NSG to trusted networks. A common approach is certbot with your-domain on a front end proxy.
  • The PodFetch server binds to port 8000 but ufw keeps that port off the network, so only nginx on port 80 faces the network. Both the nginx Basic Auth gate and PodFetch's own native Basic Auth require the per VM password.
  • The image ships with no baked password. A unique administrator password is generated on first boot and written to /root/podfetch-credentials.txt, readable only by root. Keep it somewhere safe, and change it or add scoped user accounts from the user administration view.
  • Keep the VM patched. The image ships fully patched with unattended security upgrades enabled.

Support

cloudimg images come with 24/7 support. If you have any questions about this PodFetch image or need help with your deployment, contact us through the cloudimg website.