Applications Azure

AzuraCast on Ubuntu 24.04 on Azure User Guide

| Product: AzuraCast 0.24.0 on Ubuntu 24.04 LTS on Azure

Overview

This guide covers deploying and verifying AzuraCast 0.24.0 on Ubuntu 24.04 LTS from cloudimg on Microsoft Azure.

AzuraCast is a free, self-hosted web radio management suite (AGPL-3.0). From one web interface you run internet radio stations: upload a music library, build playlists and schedules (including the grouped "clockwheel" playlists new in 0.24.0), let DJs broadcast live, take listener requests, publish podcasts, and give listeners a public player page. Broadcasting is done by Liquidsoap feeding an Icecast server, all inside AzuraCast's official container.

AzuraCast 0.24.0 (25 October 2026) carries a set of security fixes for problems reported against 0.23.x, among them shell command injection through StereoTool and Supervisor settings, Shoutcast configuration injection by station users without broadcasting rights, webhook connectors that could be redirected to internal addresses, missing permission checks on waveform and media endpoints, and CSV formula injection in exports. Earlier fixes it includes cover password reset poisoning through X-Forwarded-Host (0.23.6) and an unauthenticated injection in API sorting (0.23.8).

What is on the image:

  • AzuraCast 0.24.0 from the official upstream container image ghcr.io/azuracast/azuracast:0.24.0, pinned by digest sha256:2a4aa1e0b2fdc93170ef1dbc51ae2ea036053f0a74931692b23d0d7c072e5c06 and shipped unmodified. One container holds AzuraCast's own nginx, PHP 8.5.12, MariaDB, Valkey (Redis), Centrifugo, SFTPGo, Liquidsoap and Icecast
  • Docker CE (official Docker apt repository) running the container under one systemd unit, azuracast.service
  • HTTPS on port 443 from AzuraCast's own web server, with a self-signed certificate the container creates on your VM; port 80 redirects to HTTPS
  • A per-VM super administrator and per-VM MariaDB passwords, generated on first boot into root-only files
  • One station, cloudimg Radio, ready to receive your music and streaming through HTTPS
  • azuracast-set-hostname, a helper that serves AzuraCast under your own DNS name

Admin user: the one you choose at deployment (this guide uses azureuser) · Image: x64, Hyper-V Generation 2 · OS disk: 30 GiB

Security posture

  • No first-visitor takeover. A new AzuraCast installation gives the super administrator account to whoever opens its setup page first. This image closes that before the network can reach it: first boot runs AzuraCast with only a loopback port, creates the super administrator with a 24-character password generated on your VM, proves that it can sign in, and only then lets azuracast.service publish ports 80 and 443. The setup page is already complete for the first request anyone else can make, and self-hosted AzuraCast has no public sign-up.
  • Fails closed. azuracast.service will not publish anything until first boot has written its ready marker, and its start guard refuses to run if the database passwords are missing, short, equal, readable by other users or AzuraCast's published sample value (azur4c457). If first boot cannot seed the administrator, the web ports simply never open.
  • Per-VM secrets. The super administrator password, the MariaDB application and root passwords, the station's Icecast and DJ passwords, its internal API key, the SFTP host keys and the TLS key are all created on your VM. None is in the image, so no two VMs share one. No secret is ever passed on a command line.
  • Only the web server faces the network. The container publishes exactly ports 80 and 443. MariaDB, Valkey, Icecast (8000), the live DJ input (harbor), Liquidsoap's control port and SFTP (2022) listen only inside the container. Listeners and the web DJ reach the station through https://<host>/listen/... on 443 (AzuraCast's "Use Web Proxy for Radio", on).
  • The host name comes from configuration, never from a request. First boot reads the VM's public IP address from the Azure Instance Metadata Service and sets it as AzuraCast's Site Base URL with Prefer Browser URL off, so links AzuraCast builds (password reset e-mails included) cannot be steered by a request. A cloudimg include in AzuraCast's nginx answers only this VM's own names and addresses (any other Host gets its connection closed), refuses client-sent X-Forwarded-Host, X-Forwarded-Proto and X-Forwarded-Port headers (400), and redirects HTTP to HTTPS.
  • Client address from the connection. AzuraCast's IP Address Source is set to the local connection, so a forged X-Forwarded-For header cannot change the address AzuraCast rate-limits sign-ins by or records for song requests. This was proved at build time: a sign-in carrying X-Forwarded-For: 127.0.0.1 was logged with the real peer address.
  • HTTPS only. Always Use HTTPS is on, so AzuraCast's session cookie is Secure and HttpOnly. TLS 1.2 and 1.3 are offered; TLS 1.1 is refused.
  • Cross-site requests refused. The three addresses that change state or make AzuraCast fetch something on a plain GET (/logout, /endsession and the update check /api/admin/updates) answer only requests that come from AzuraCast's own pages (the browser's Sec-Fetch-Site, Origin or Referer must name this VM). A link or image on another site that points at them gets 403, so another site cannot sign you out or make the server call out.
  • The container cannot reach Azure metadata. Webhooks, remote relays and remote playlists fetch addresses your station users enter, so the container is blocked from the Azure Instance Metadata Service (169.254.169.254) and the Azure WireServer (168.63.129.16) by Docker DOCKER-USER firewall rules (IPv4 and IPv6) that are in place before the container starts and survive Docker restarts. Docker, containerd and azuracast.service are blocked by systemd IPAddressDeny as well. The Azure agent (walinuxagent) and cloud-init are not affected: nothing is blocked host-wide. AzuraCast's own Filter Local User-provided URLs is on as well.
  • PHP2Shell fixed. The PHP inside the container is 8.5.12, the upstream release that fixes CVE-2026-109618 and CVE-2026-109619 (built 21 October 2026); no Debian PHP package is installed in it.
  • No update phone-home. AzuraCast's update check (Show Update Announcements) is off, so AzuraCast contacts central.azuracast.com only when an administrator opens Administration > Updates, and the external IP AzuraCast would otherwise ask central.azuracast.com for is filled in from Azure metadata at every start.
  • What is public. The sign-in page, each station's public player page, its stream and the now-playing API are public by design (they are what listeners use). Everything else needs a signed-in account.
  • Hardened SSH and system. SSH refuses root login, empty passwords and X11 forwarding (proved with sshd -T); key or password sign-in is the choice you make when you deploy. Core dumps are disabled for AzuraCast, Docker and containerd, and inside the container. The fwupd LVFS refresh timer is masked. SSH host keys, the machine ID and Docker's engine ID are generated fresh on every VM.
  • A note on the container environment. AzuraCast reads its database password from the container environment (it has no file-based option). It is visible to root on the host (docker inspect) and to processes inside the container, the same as on any AzuraCast installation. AzuraCast's own database tools (the migration run on the first start and after an upgrade, and the backups under Administration > Backups) also hand that password to mariadb-dump on its command line inside the container, which MariaDB overwrites as soon as it starts. The database itself is reachable only from inside the container, so the password is of no use to anyone who cannot already use Docker (root).

Prerequisites

  1. An Azure subscription and permission to create virtual machines
  2. An SSH key pair (or a password, if you choose password authentication)
  3. Outbound internet access from the VM if you want AzuraCast to fetch album art, send e-mail or relay remote streams

Recommended size: Standard_B2s (2 vCPU, 4 GiB) for one station. With one station AzuraCast uses well under 1 GiB of memory and little CPU; for several stations, many listeners or audio processing choose Standard_B2ms or larger. Music libraries live on the OS disk: increase it at deployment (or later) to fit your media.

Step 1: Deploy from the Azure Marketplace

  1. In the Azure portal choose Create a resource, search the Marketplace for AzuraCast by cloudimg, select the Default plan and choose Create.
  2. On Basics, pick your subscription, resource group and region, name the VM and choose Standard_B2s (or larger). Choose SSH public key authentication with the admin username azureuser and your public key.
  3. On Disks, increase the OS disk size if you will upload a large music library.
  4. On Networking, allow inbound SSH (22), HTTP (80) and HTTPS (443). Restrict SSH to your own IP address afterwards in the network security group. Leave 80 and 443 open to your listeners (a public radio station is usually open to the internet).
  5. Choose Review + create, then Create. When the VM is running, note its public IP address.

Step 2: Deploy from the Azure CLI

Run these on your own workstation. They create a resource group, the VM, and network security group rules for HTTP and HTTPS (az vm create opens SSH by default; restrict it to your own address range):

az group create --name my-resource-group --location eastus
az vm image terms accept --urn cloudimg1647283583153:azuracast:default:latest
az vm create \
  --resource-group my-resource-group \
  --name azuracast \
  --image cloudimg1647283583153:azuracast:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_rsa.pub \
  --public-ip-sku Standard \
  --os-disk-size-gb 64
az vm open-port --resource-group my-resource-group --name azuracast --port 443 --priority 900
az vm open-port --resource-group my-resource-group --name azuracast --port 80 --priority 910

--os-disk-size-gb 64 grows the OS disk for a music library; leave it out to keep 30 GiB. A Standard public IP keeps its address while the VM is stopped; if you deallocate a VM with a dynamic address, AzuraCast follows the new address at the next boot.

Step 3: Connect and find your login

Connect as azureuser with your key (replace <vm-ip> with the VM's public IP address):

ssh azureuser@<vm-ip>

First boot finishes a few minutes after the VM starts (the first start reads AzuraCast's 2.3 GB container image from the disk). It sets the address AzuraCast is served as (the VM's public IP from Azure metadata), generates the secrets, seeds the super administrator over loopback, creates and starts the cloudimg Radio station, and writes /root/azuracast-credentials.txt (mode 0600, root). Only then does azuracast.service open ports 80 and 443. These are the entries in the credentials file and the database environment file (the secrets are not shown here):

sudo grep -E '^AZURACAST_(URL|ADMIN_EMAIL)=' /root/azuracast-credentials.txt
sudo grep -oE '^[A-Z_]+=' /root/azuracast-credentials.txt
sudo stat -c '%a %U:%G %n' /root/azuracast-credentials.txt /etc/azuracast/azuracast.env
sudo grep -oE '^MYSQL_[A-Z_]*PASSWORD=' /etc/azuracast/azuracast.env
AZURACAST_URL=https://203.0.113.10/
AZURACAST_ADMIN_EMAIL=admin@azuracast.local
AZURACAST_URL=
AZURACAST_ADMIN_EMAIL=
AZURACAST_ADMIN_PASSWORD=
600 root:root /root/azuracast-credentials.txt
600 root:root /etc/azuracast/azuracast.env
MYSQL_PASSWORD=
MYSQL_ROOT_PASSWORD=
Value What it is for
AZURACAST_URL The address of this VM's AzuraCast
AZURACAST_ADMIN_EMAIL Sign-in e-mail of the super administrator (admin@azuracast.local; change it after signing in)
AZURACAST_ADMIN_PASSWORD Super administrator password, generated on this VM
MYSQL_PASSWORD, MYSQL_ROOT_PASSWORD MariaDB passwords for AzuraCast and for the database root account, generated on this VM (in /etc/azuracast/azuracast.env)

To read the values, run sudo cat /root/azuracast-credentials.txt in your own session and store them in your password manager.

Step 4: Confirm AzuraCast is running

Docker, the metadata firewall rule and AzuraCast are active, and the container runs the pinned 0.24.0 image. Only sshd and Docker's port forwarder for 80 and 443 listen beyond loopback. 2022/tcp (SFTP) and 9000/tcp appear in docker ps because the image declares them, but neither is published on the host:

systemctl is-active docker.service cloudimg-docker-imds-deny.service azuracast.service
sudo docker ps --format '{{.Names}} {{.Image}}'
sudo docker ps --format '{{.Ports}}' | tr ',' '\n' | sed 's/^ //'
sudo ss -Htlnp | awk '{print $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g' | sort -u
sudo docker exec azuracast azuracast_cli --version
sudo docker exec azuracast php -r 'echo "PHP ", PHP_VERSION, "\n";'
active
active
active
azuracast ghcr.io/azuracast/azuracast:0.24.0
0.0.0.0:80->80/tcp
[::]:80->80/tcp
2022/tcp
0.0.0.0:443->443/tcp
[::]:443->443/tcp
9000/tcp
0.0.0.0:22 users:(("sshd"),("systemd"))
0.0.0.0:443 users:(("docker-proxy"))
0.0.0.0:80 users:(("docker-proxy"))
127.0.0.53%lo:53 users:(("systemd-resolve"))
127.0.0.54:53 users:(("systemd-resolve"))
[::]:22 users:(("sshd"),("systemd"))
[::]:443 users:(("docker-proxy"))
[::]:80 users:(("docker-proxy"))
AzuraCast Command Line Tools (Production) 0.24.0
PHP 8.5.12

Docker, the metadata firewall unit and AzuraCast active, the pinned AzuraCast 0.24.0 container running, only SSH and Docker's forwarder for ports 80 and 443 listening beyond loopback, and PHP 8.5.12 inside the container

Step 5: Prove the login and the web defaults

The sign-in page answers, the setup page is already complete, and the administration API refuses a signed-out request. Plain HTTP redirects to HTTPS, an unknown Host header gets no answer, a client-sent X-Forwarded-Host is refused and TLS 1.1 is not offered. The last command is the image's own round-trip check: it signs in with this VM's administrator password, proves that blank and wrong passwords are refused, and reads the station list with the session:

H=$(sed -n 's#^https://##p' /etc/azuracast/base-url)
C=(--connect-to ::127.0.0.1:)
curl -sk "${C[@]}" -o /dev/null -w 'sign-in page -> %{http_code}\n' "https://$H/login"
curl -sk "${C[@]}" -o /dev/null -w 'setup page -> %{http_code} %{redirect_url}\n' "https://$H/setup/register"
curl -sk "${C[@]}" -o /dev/null -w 'admin API, signed out -> %{http_code}\n' "https://$H/api/admin/stations"
curl -s "${C[@]}" -o /dev/null -w 'http -> %{http_code} %{redirect_url}\n' "http://$H/login"
curl -sk -o /dev/null -w 'unknown Host -> %{http_code}\n' -H 'Host: evil.example' https://127.0.0.1/login || true
curl -sk "${C[@]}" -o /dev/null -w 'client-sent X-Forwarded-Host -> %{http_code}\n' -H 'X-Forwarded-Host: evil.example' "https://$H/login"
curl -sk "${C[@]}" -o /dev/null -w 'TLS 1.1 -> %{http_code}\n' --tlsv1.1 --tls-max 1.1 "https://$H/login" || true
sudo /usr/local/sbin/azuracast-roundtrip.sh
sign-in page -> 200
setup page -> 302 https://203.0.113.10/setup/complete
admin API, signed out -> 403
http -> 301 https://203.0.113.10/login
unknown Host -> 000
client-sent X-Forwarded-Host -> 400
TLS 1.1 -> 000
OK round-trip https://203.0.113.10/: login page 200; /setup/register closed; anonymous, wrong and blank password get no admin API; per-VM super administrator logs in (Secure HttpOnly session) and reads the station list; unknown Host dropped; HTTP 301 to HTTPS

--connect-to ::127.0.0.1: sends each request to this VM while keeping the real host name in the request, exactly as a browser would send it. 000 means the server closed the connection without an answer.

The setup page already complete, the admin API refusing a signed-out request, plain HTTP redirected to HTTPS, an unknown Host and a client-sent X-Forwarded-Host refused, TLS 1.1 refused, and the per-VM login round-trip passing

Step 6: Sign in to AzuraCast

Browse to AZURACAST_URL (https://<vm-public-ip>/). The certificate is self-signed, so your browser warns once; accept it for this address, or set up a Let's Encrypt certificate (Step 10). Sign in with AZURACAST_ADMIN_EMAIL and AZURACAST_ADMIN_PASSWORD:

The AzuraCast sign-in page asking for the e-mail address and password of the super administrator generated on this VM

The dashboard lists your stations with their listener counts and what is playing. Open My Account (top right) first and change the e-mail address to your own and, if you like, the password; then add accounts for your team under Administration > Users (there is no public sign-up):

The AzuraCast dashboard for the super administrator with the My Account and Administration buttons, the listeners per station chart and the station overview

Step 7: Put music on the air

Open cloudimg Radio from the dashboard. Its Icecast broadcasting service and Liquidsoap AutoDJ are already running; until you add music the Now Playing panel reads Station Offline and the stream carries AzuraCast's fallback audio. Rename the station under Edit Station Settings, then:

  1. Media > Music Files: upload MP3, OGG, FLAC or other audio files (or folders), then select them and add them to a playlist from the Playlists menu. Files uploaded while you view a playlist's tracks are added to that playlist directly.
  2. Playlists: the station starts with a default playlist; create more playlists and schedules here. Grouped playlists (new in 0.24.0) let one "clockwheel" run several smaller playlists in a set order.
  3. Overview: the station page shows the HTTPS stream address, the public player link and the state of the broadcasting and AutoDJ services, with their Restart and Stop buttons.

The cloudimg Radio station overview in AzuraCast with the HTTPS stream address, the public page link, and the Icecast broadcasting and Liquidsoap AutoDJ services running

Listeners use the public player page or the stream address directly in any media player. Both are served over HTTPS on port 443:

H=$(sed -n 's#^https://##p' /etc/azuracast/base-url)
C=(--connect-to ::127.0.0.1:)
curl -sk "${C[@]}" "https://$H/api/nowplaying" | jq -r '.[] | "\(.station.name) | \(.station.shortcode) | \(.station.listen_url) | public page: \(.station.public_player_url)"'
sudo docker exec azuracast supervisorctl status | awk '/^station_/{print $1, $2}'
curl -sk "${C[@]}" -m 5 -o /dev/null -w 'stream -> %{http_code} %{content_type}\n' "https://$H/listen/cloudimg_radio/radio.mp3" || true
curl -sk "${C[@]}" -o /dev/null -w 'Icecast admin, no password -> %{http_code}\n' "https://$H/listen/cloudimg_radio/admin/"
cloudimg Radio | cloudimg_radio | https://203.0.113.10/listen/cloudimg_radio/radio.mp3 | public page: https://203.0.113.10/public/cloudimg_radio
station_1:station_1_backend RUNNING
station_1:station_1_frontend RUNNING
stream -> 200 audio/mpeg
Icecast admin, no password -> 401

The stream request stops itself after five seconds (-m 5); a stream never ends on its own. The public player page:

The public AzuraCast player page for cloudimg Radio with the play button, volume, song history and playlist download

Step 8: Live DJs, extra stations and opening station ports

Web DJ. On the station overview choose Enable in the Streamers/DJs panel (or turn on Allow Streamers / DJs under Edit Station Settings > Streamers/DJs), then create DJ accounts under Streamers/DJs. DJs can broadcast from their browser with the station's Web DJ page, which works over HTTPS on 443 with no extra port.

DJ software and more stations. DJ software (butt, Mixxx, Rocket Broadcaster) connects to the station's DJ port (8005 for the first station), and stations you add get their own Icecast port (8000, 8010, 8020 and so on). Those ports are not published by default. To publish a range for your stations, add it to the ports in /etc/azuracast/compose.public.yaml on the VM and restart AzuraCast:

services:
  web:
    ports:
      - "80:80"
      - "443:443"
      - "8000-8099:8000-8099"
sudo systemctl restart azuracast

Then open the same range on the VM's network security group, limited to the networks your DJs and listeners use (run this on your workstation; replace the source range with your own):

az network nsg rule create --resource-group my-resource-group --nsg-name azuracastNSG \
  --name azuracast-stations --priority 920 --direction Inbound --access Allow --protocol Tcp \
  --destination-port-ranges 8000-8099 --source-address-prefixes 198.51.100.0/24

azuracastNSG is the network security group az vm create made for a VM named azuracast; in the portal it is under the VM's Networking page. SFTP uploads (port 2022) work the same way: add "2022:2022" to the ports and open 2022 to your own network only.

Step 9: Check the security controls

The DOCKER-USER chains drop traffic from the container to the Azure Instance Metadata Service and the WireServer while ordinary internet access works; the VM itself (and the Azure agent) still reaches the metadata service. Docker, containerd and AzuraCast's unit carry IPAddressDeny, the Azure agent carries none. PHP inside the container is the fixed 8.5.12 build with no Debian PHP package installed, and SSH runs with the cloudimg pins:

sudo iptables -S DOCKER-USER
sudo ip6tables -S DOCKER-USER
sudo docker exec azuracast curl -s -m 10 https://checkip.amazonaws.com/ >/dev/null && echo "container -> internet: reachable"
sudo docker exec azuracast curl -s -m 5 -H 'Metadata: true' 'http://169.254.169.254/metadata/instance?api-version=2021-02-01' >/dev/null || echo "container -> Azure metadata: blocked (curl exit $?)"
sudo docker exec azuracast curl -s -m 5 'http://168.63.129.16/?comp=versions' >/dev/null || echo "container -> WireServer: blocked (curl exit $?)"
curl -s -m 5 -o /dev/null -w 'VM -> Azure metadata: %{http_code}\n' -H 'Metadata: true' 'http://169.254.169.254/metadata/instance?api-version=2021-02-01'
for u in docker containerd azuracast walinuxagent; do echo "$u: $(systemctl show -p IPAddressDeny --value $u.service | tr ' ' '\n' | sort | tr '\n' ' ')"; done
sudo docker exec azuracast sh -c 'php -v | head -1; dpkg-query -W -f="\${db:Status-Abbrev} \${Package}\n" "php*" | grep -c "^ii" || true'
sudo sshd -T | grep -E '^(permitrootlogin|permitemptypasswords|x11forwarding) '
-N DOCKER-USER
-A DOCKER-USER -d 168.63.129.16/32 -j DROP
-A DOCKER-USER -d 169.254.169.254/32 -j DROP
-N DOCKER-USER
-A DOCKER-USER -d ::ffff:168.63.129.16/128 -j DROP
-A DOCKER-USER -d ::ffff:169.254.169.254/128 -j DROP
-A DOCKER-USER -d fd00:ec2::254/128 -j DROP
container -> internet: reachable
container -> Azure metadata: blocked (curl exit 28)
container -> WireServer: blocked (curl exit 28)
VM -> Azure metadata: 200
docker: 168.63.129.16/32 169.254.169.254/32 ::ffff:168.63.129.16/128 ::ffff:169.254.169.254/128 fd00:ec2::254/128
containerd: 168.63.129.16/32 169.254.169.254/32 ::ffff:168.63.129.16/128 ::ffff:169.254.169.254/128 fd00:ec2::254/128
azuracast: 168.63.129.16/32 169.254.169.254/32 ::ffff:168.63.129.16/128 ::ffff:169.254.169.254/128 fd00:ec2::254/128
walinuxagent:
PHP 8.5.12 (cli) (built: Oct 21 2026 15:49:51) (NTS)
0
permitrootlogin no
x11forwarding no
permitemptypasswords no

The DOCKER-USER rules, the container reaching the internet but not the Azure metadata service or the WireServer, the VM itself still reaching the metadata service, IPAddressDeny on Docker, containerd and AzuraCast but not on the Azure agent, and the sshd pins

Exit code 28 is curl's timeout: the request is dropped, not answered. The cloudimg settings are visible under Administration > System Settings: on Settings, the Site Base URL is your VM's address and Prefer Browser URL is off; on Security & Privacy, Always Use HTTPS is on, IP Address Source is the local connection and Filter Local User-provided URLs is on; on Services, Show Update Announcements is off.

Step 10: Serve AzuraCast under your own DNS name

Point a DNS record (for example radio.example.com) at the VM's public IP address, or give the public IP an Azure DNS name label (<label>.<region>.cloudapp.azure.com) under the public IP's Configuration page. Then tell the image to serve that name. It rewrites the nginx host guard, sets AzuraCast's Site Base URL and keeps the name across reboots:

sudo azuracast-set-hostname radio.example.com

For a trusted certificate, open Administration > System Settings > Services, enter the name under LetsEncrypt > Domain Name(s) (and optionally an e-mail address) and save. AzuraCast requests the certificate over port 80 (the image leaves /.well-known/acme-challenge/ on plain HTTP for exactly this) and renews it itself. Port 80 must be reachable from the internet while it does.

Without your own name, the VM keeps following its public IP when it changes after a deallocate and start (azuracast-hostname.service updates it at boot from Azure metadata).

Step 11: Behind a load balancer or Application Gateway

The image is built for AzuraCast to face the network directly. An Azure Application Gateway, Front Door or another proxy adds X-Forwarded-Proto, X-Forwarded-Port and X-Forwarded-For headers, which the host guard refuses. If you put AzuraCast behind your own proxy: allow the proxy's address only in the network security group, remove the three X-Forwarded lines from /etc/azuracast/nginx.d/10-cloudimg-host.conf (sudo azuracast-set-hostname writes them back, so do this after any name change), reload with sudo docker exec azuracast supervisorctl signal HUP nginx, and set IP Address Source to Reverse Proxy (X-Forwarded-For) in Security & Privacy. Only do this when every request really arrives through your proxy.

Step 12: Change passwords

  • Super administrator: sign in and use My Account > Change Password, so the new password never appears on a command line or in your shell history. The file /root/azuracast-credentials.txt is not updated; remove the old password from it (sudo nano /root/azuracast-credentials.txt) once you have stored the new one.
  • Station passwords (Icecast admin, source, relay and DJ): Edit Station Settings > Broadcasting for the station.
  • The MariaDB passwords in /etc/azuracast/azuracast.env are used only inside the container and do not need changing.

Maintenance

  • Operating system updates: unattended security upgrades are on. Reboot when /var/run/reboot-required exists; AzuraCast starts again by itself.
  • AzuraCast updates: the image runs AzuraCast's 0.24.0 release pinned by digest, and AzuraCast's in-app updater is not used. To move to a newer release, replace the image: line in /etc/azuracast/compose.yaml with the new release tag and digest from AzuraCast's releases, then run sudo docker pull <image> and sudo systemctl restart azuracast. Take a backup first; AzuraCast runs its database migrations on start.
  • Backups: Administration > Backups creates scheduled or manual backups (database, media and configuration) inside the container's backups volume; copy them off the VM or point backups at an S3-compatible storage location. Azure Backup or a snapshot of the OS disk captures everything.
  • Logs: sudo docker logs azuracast for the container, and Administration > System Logs in the web interface.
  • What the VM contacts: AzuraCast itself contacts only what you configure (webhooks, remote relays, album art services, e-mail, Let's Encrypt). The operating system contacts the Azure agent endpoints, Ubuntu's package mirrors for updates, and snapd.

Troubleshooting

  • The web page does not load right after deployment: first boot is still running. sudo journalctl -u azuracast-firstboot.service -f shows its progress, and the ports open when it finishes.
  • Browser shows "connection closed" for an address: the host guard answers only this VM's own names and addresses. Use AZURACAST_URL, or run sudo azuracast-set-hostname <name> for a new name.
  • azuracast.service failed: sudo journalctl -u azuracast.service -n 50 shows the start guard's reason; sudo docker logs azuracast | tail -50 shows AzuraCast's own startup.
  • A station does not play: on the station's Overview use Restart for the broadcasting service and the AutoDJ; check that Media holds files and that they are in a playlist.
  • DJ software cannot connect: the station ports are not published by default; follow Step 8 to publish them and open them on the network security group.

Licensing

AzuraCast is licensed under the GNU Affero General Public License v3.0 or later. The image runs the official upstream container unmodified; the licence text and the written offer of source are on the VM in /usr/share/doc/azuracast/, and the complete corresponding source is at github.com/AzuraCast/AzuraCast/tree/0.24.0. cloudimg is not affiliated with, endorsed by or sponsored by the AzuraCast project.

Support

cloudimg provides 24/7 technical support for this image by email and live chat: deployment, first login, HTTPS and DNS setup, upgrades and troubleshooting. Contact support@cloudimg.co.uk.