Icecast 2.4.4 with Liquidsoap 2.4.6
Overview
This guide covers launching and using the Icecast 2.4.4 with Liquidsoap 2.4.6 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud media servers listing on AWS Marketplace. You select it as the software version when you subscribe and launch.
The image is a complete internet radio station. Icecast, from the Xiph.Org Foundation, is the streaming server. It relays one incoming stream to many listeners and publishes a status page, playlists and an admin interface. Liquidsoap, from the Savonet project, is the programmable audio engine that feeds it. It plays playlists, mixes live shows, crossfades, normalises loudness and encodes the result into the stream. On this image Liquidsoap is already connected to Icecast and streaming, so a listener can tune in seconds after the instance boots.
What you get:
- A station that works on first boot. Liquidsoap runs as the
sac-radioservice and streams a quiet 440 Hz reference tone, encoded as Ogg Vorbis, tohttps://<your-host>/stream.ogg. No third-party audio ships on the image. Step 7 shows how to play your own music instead. - Liquidsoap 2.4.6 built from source, with clean licensing. The prebuilt Liquidsoap packages link the Fraunhofer FDK AAC codec, which may not be redistributed with GPL software. SecureAnyCloud compiles Liquidsoap 2.4.6 from its checksum-verified release with Ogg, Vorbis, Opus, FLAC and LAME (MP3 encoding) support, and with no FDK AAC or FFmpeg. The compiler and build tools are removed before the image is captured.
- HTTPS from the first boot. nginx serves the status page, the admin interface and the listener streams on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS.
- Source clients over TLS. Live presenters connect to port 8443 with TLS switched on, so the source password never crosses the network in clear text.
- Three passwords unique to your instance. Admin, source and relay passwords are generated on first boot and written to
/root/icecast-liquidsoap-credentials.txt. Liquidsoap receives only the source password, from a file readable by root and its own service. The upstream default password appears nowhere and never works. - Fail closed. Icecast and Liquidsoap refuse to start while their configuration still holds a template value or the upstream default, and nginx refuses to start until first boot has finished.
- Icecast on loopback. Icecast listens only on
127.0.0.1:8000and Liquidsoap listens on nothing. nginx is the only service on the network. - Hardened defaults. Icecast and Liquidsoap each run as their own unprivileged user in a systemd sandbox. Icecast, Liquidsoap and nginx are all blocked from the instance metadata service, and the AMI requires IMDSv2.
- Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: Icecast 2.4.4 (the stock Ubuntu 24.04 icecast2 package, so it inherits Ubuntu's security maintenance), Liquidsoap 2.4.6 in /opt/liquidsoap (compiled by SecureAnyCloud, with its complete corresponding source in /usr/local/src/liquidsoap-2.4.6-source), nginx with its stream module, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.
Default user: ubuntu. Architecture: x86_64. Recommended instance type: m5.large.
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet
- A security group that allows the following inbound traffic:
- TCP 22 (SSH) from your own networks only
- TCP 443 (status page, admin interface and listeners) from wherever your listeners are, usually anywhere
- TCP 80 (redirects to HTTPS) from the same sources as 443
- TCP 8443 (live source clients over TLS) from your presenters' networks only
Encoding one Ogg Vorbis stream takes a small fraction of a CPU core, and Icecast relays without re-encoding, so listener count is mostly a bandwidth question. A 128 kbit/s stream to 100 listeners needs about 13 Mbit/s outbound.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Select Icecast 2.4.4 with Liquidsoap 2.4.6 on Ubuntu 24.04 as the software version, choose your Region, and choose Launch through EC2. Select m5.large, your key pair and a security group as described above.
To launch with the AWS CLI instead, replace the values in angle brackets:
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=radio}]'Connect to your instance
On Icecast 2.4.4 with Liquidsoap 2.4.6 on Ubuntu 24.04, the SSH user is ubuntu. Connect with your key pair:
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
First boot generates the certificate and the three passwords, then starts Icecast, Liquidsoap and nginx. Check the services:
systemctl is-active icecast2 sac-radio nginx icecast-liquidsoap-firstboot
sudo test -f /var/lib/sac/data/icecast-liquidsoap-firstboot.done && echo FIRSTBOOT_DONE liquidsoap --version | head -n 1All four units are active, the first boot marker is present and Liquidsoap reports its version:
active active active active FIRSTBOOT_DONE Liquidsoap 2.4.6nginx is the only service on public addresses (80, 443 and 8443). Icecast listens on loopback, and Liquidsoap listens on nothing:
sudo ss -lntpH | awk '{split($6, a, "\""); print $4, a[2]}' | sort0.0.0.0:22 sshd 0.0.0.0:443 nginx 0.0.0.0:80 nginx 0.0.0.0:8443 nginx 127.0.0.1:8000 icecast2 127.0.0.53%lo:53 systemd-resolve 127.0.0.54:53 systemd-resolve [::]:22 sshd [::]:443 nginx [::]:80 nginx [::]:8443 nginxGet your URLs and passwords
Display the credentials file. Only root can read it:
sudo cat /root/icecast-liquidsoap-credentials.txtThe file looks like this:
# Icecast 2.4.4 with Liquidsoap 2.4.6 - generated on first boot by icecast-liquidsoap-firstboot.service
# These passwords are unique to this instance; none was baked into the image. Keep this file secret.
# The three are independent: a presenter with the source password has no admin access. ICECAST_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ ICECAST_STREAM_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/stream.ogg ICECAST_ADMIN_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/admin/ ICECAST_ADMIN_USER=admin ICECAST_ADMIN_PASSWORD=<ICECAST_ADMIN_PASSWORD> ICECAST_SOURCE_HOST=ec2-<public-ip-dashed>.<region>.compute.amazonaws.com ICECAST_SOURCE_PORT=8443 ICECAST_SOURCE_USER=source ICECAST_SOURCE_PASSWORD=<ICECAST_SOURCE_PASSWORD> ICECAST_RELAY_USER=relay ICECAST_RELAY_PASSWORD=<ICECAST_RELAY_PASSWORD>
# Live stream: ICECAST_STREAM_URL (Liquidsoap plays a generated 440 Hz demo tone out of the box)
# Status page: ICECAST_URL (self-signed certificate minted on first boot)
# Admin UI: ICECAST_ADMIN_URL (user admin)
# Your own playlist: edit /opt/sac-radio/sac-radio.liq, then
sudo systemctl restart sac-radio
# Your own source client (butt, Mixxx, OBS): server ICECAST_SOURCE_HOST, port 8443 with TLS/SSL on,
# user source, password ICECAST_SOURCE_PASSWORD, a mount of your own such as /live.ogg
# Change the name it is served as:
sudo icecast-liquidsoap-set-hostname <your-dns-name>
# User guide: https://secureanycloud.com/stacks/icecast-2-4-4-with-liquidsoap-2-4-6/ICECAST_STREAM_URLis the station's live stream. Open it in VLC, a browser or any player that understands Ogg Vorbis.ICECAST_ADMIN_PASSWORDsigns you in to theadmininterface as user admin.ICECAST_SOURCE_PASSWORDis what asourceclient uses, with user source, to broadcast. Liquidsoap on the instance uses it too.ICECAST_RELAY_PASSWORDis used by another Icecast server that pulls a relay from this one.
The URLs use the instance's public DNS name from EC2 instance metadata. The certificate also names the public and private IP addresses, so https://<public-ip>/ works too. To use your own DNS name, see Step 10.
To share the file, for example in a support request, print it with the passwords masked:
sudo sed -E 's/^(ICECAST_[A-Z_]*PASSWORD=).*/\1********/' /root/icecast-liquidsoap-credentials.txt | grep -E '^ICECAST_'Check the server from the command line
Port 80 redirects to HTTPS, the health check is open for load balancers, and Icecast reports its version. Run these commands to check:
H=$(sudo grep '^ICECAST_URL=' /root/icecast-liquidsoap-credentials.txt | sed -E 's#^ICECAST_URL=https://([^/]+)/.*#\1#')
curl -s -o /dev/null -w 'http:// -> %{http_code}\n' --resolve "$H:80:127.0.0.1" "http://$H/"
curl -sk -o /dev/null -w 'healthz -> HTTP %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/healthz"
curl -sk --resolve "$H:443:127.0.0.1" "https://$H/status-json.xsl" | jq -r '.icestats.server_id'http:// -> 301 healthz -> HTTP 200 Icecast 2.4.4The admin interface refuses a request with no password and one with the upstream default password. It accepts this instance's admin password. The commands pass the password to curl on standard input, so it never appears in the process list or your shell history:
sudo bash -c ' F=/root/icecast-liquidsoap-credentials.txt P=$(grep "^ICECAST_ADMIN_PASSWORD=" $F | cut -d= -f2-) H=$(grep "^ICECAST_URL=" $F | sed -E "s#^ICECAST_URL=https://([^/]+)/.*#\1#") R="--resolve $H:443:127.0.0.1" D="hack""me" curl -sk $R -o /dev/null -w "admin, no password -> HTTP %{http_code}\n" "https://$H/admin/stats" printf "user = \"admin:%s\"\n" "$D" | curl -K - -sk $R -o /dev/null -w "admin, upstream default -> HTTP %{http_code}\n" "https://$H/admin/stats" printf "user = \"admin:%s\"\n" "$P" | curl -K - -sk $R -o /dev/null -w "admin, this instance -> HTTP %{http_code}\n" "https://$H/admin/stats" 'admin, no password -> HTTP 401 admin, upstream default -> HTTP 401 admin, this instance -> HTTP 200Listen to the station
Liquidsoap is already on air. The following commands read the first few kilobytes of the live stream through nginx and show what Icecast reports for the mountpoint:
H=$(sudo grep '^ICECAST_URL=' /root/icecast-liquidsoap-credentials.txt | sed -E 's#^ICECAST_URL=https://([^/]+)/.*#\1#')
curl -sk -m 5 --resolve "$H:443:127.0.0.1" "https://$H/stream.ogg" | head -c 4; echo
curl -sk --resolve "$H:443:127.0.0.1" "https://$H/status-json.xsl" | jq -r '.icestats.source | .listenurl, .server_name, .server_type'OggS https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/stream.ogg sac radio application/oggOggS is the start of an Ogg stream.
On your own computer, open the ICECAST_STREAM_URL from Step 4 in VLC (Media > Open Network Stream) or in a browser. Accept the self-signed certificate the first time, and you hear the reference tone. Players also accept the M3U playlist at https://<your-host>/stream.ogg.m3u.
Play your own music with Liquidsoap
Liquidsoap reads its script from /opt/sac-radio/sac-radio.liq. The script on the image plays the reference tone:
grep -vE '^\s*(#|$)' /opt/sac-radio/sac-radio.liqsettings.log.stdout := true settings.log.file := false source_password = environment.get("ICECAST_SOURCE_PASSWORD") radio = mksafe(amplify(0.3, sine(440.))) output.icecast( %vorbis(quality=0.2), host="127.0.0.1", port=8000, password=source_password, mount="/stream.ogg", name="sac radio", description="Icecast 2.4.4 with Liquidsoap 2.4.6 on Ubuntu 24.04 (generated reference tone)", genre="Demo", public=false, radio)The service user can check the script at any time. The check type-checks the whole program without starting it:
sudo -u sac-radio liquidsoap --check /opt/sac-radio/sac-radio.liq && echo SCRIPT_OKSCRIPT_OKTo play your own music, copy your files to the instance and put them in /srv/sac-radio/music. This build decodes Ogg Vorbis, Opus and FLAC files. It has no MP3 decoder, by design, so convert MP3 files first. For example, run ffmpeg -i song.mp3 -c:a libvorbis -q:a 5 song.ogg on your own computer.
scp -i <your-key.pem> *.ogg ubuntu@<public-ip>:/tmp/ ssh -i <your-key.pem> ubuntu@<public-ip> 'sudo install -m 0644 /tmp/*.ogg /srv/sac-radio/music/ && rm -f /tmp/*.ogg'Then edit the script with sudo nano /opt/sac-radio/sac-radio.liq. Replace the radio = ... line with a shuffled playlist of that folder, and keep the tone as a fallback for when the folder is empty:
radio = fallback(track_sensitive=false, [ playlist(mode="randomize", reload_mode="watch", "/srv/sac-radio/music"), amplify(0.3, sine(440.)) ]) radio = mksafe(radio)Keep the output.icecast(...) block as it is. It already sends to the local Icecast with this instance's source password, which Liquidsoap reads from its environment. Check the script as the service user, then apply it:
sudo -u sac-radio liquidsoap --check /opt/sac-radio/sac-radio.liq
sudo systemctl restart sac-radio journalctl -u sac-radio -n 20 --no-pagerreload_mode="watch" picks up files that you add to the folder later, without a restart. The Liquidsoap 2.4 documentation covers scheduling, crossfades, jingles, live input and loudness normalisation. To serve a second format, add another output.icecast(...) with, for example, %opus and mount="/stream.opus".
Broadcast live from your own computer
A live source client runs on your machine and pushes audio to its own mountpoint, alongside the Liquidsoap stream. Use the values from Step 4, and switch TLS (or SSL) on:
Server / host : ICECAST_SOURCE_HOST (or your DNS name from Step 10) Port : 8443 with TLS / SSL enabled Mountpoint : /live.ogg (or /live.mp3, /live.opus) Username : source Password : the ICECAST_SOURCE_PASSWORD value Format : Ogg Vorbis, Opus or MP3- butt (Broadcast Using This Tool): add an Icecast server on port 8443 and select Use TLS. Accept the certificate when butt asks, or install your own certificate (Step 10).
- Mixxx: in Preferences > Live Broadcasting, set the type to Icecast 2, the port to 8443, and TLS on.
- ffmpeg: for example, to stream a file on a loop, run the following command.
ffmpeg -re -stream_loop -1 -i show.ogg -c:a libvorbis -q:a 4 -f ogg \
-method PUT -content_type audio/ogg -chunked_post 0 -send_expect_100 0 -auth_type basic \
-tls_verify 0 "https://source:<ICECAST_SOURCE_PASSWORD>@<ICECAST_SOURCE_HOST>:8443/live.ogg"Listeners tune in to a live show at https://<your-host>/live.ogg. The Liquidsoap stream on /stream.ogg keeps running alongside it.
Use the status page and the admin interface
Open ICECAST_URL in your browser. The certificate is self-signed, so your browser asks you to confirm it the first time, unless you install your own (Step 10). The public status page lists every active mountpoint with its stream name, description, content type, listener count and current track, with M3U and XSPF playlist links:
Open ICECAST_ADMIN_URL and sign in as admin with the admin password. Admin Home shows the global server statistics, including the configured host and the server version:
Mountpoint List shows each mountpoint with its controls. Use List Clients to see listeners, Move Listeners to move an audience to another mountpoint without dropping it, and Update Metadata to change the track title that listeners see. Use Kill Source to disconnect a source. Liquidsoap reconnects on its own a few seconds later:
List Clients shows each connected listener with a Kick action. Listeners reach Icecast through nginx, so the IP column shows 127.0.0.1. The real listener addresses are in /var/log/nginx/access.log, and source connections on port 8443 are logged in /var/log/nginx/icecast-source.log.
Use your own DNS name and certificate
Point a DNS record at the instance (an Elastic IP keeps the address stable), then tell the instance its name. The command regenerates the self-signed certificate for that name, updates the stream URLs that Icecast advertises and the credentials file, and reloads nginx and Icecast:
sudo icecast-liquidsoap-set-hostname radio.your-domain.exampleTo use a certificate from a public CA instead, replace /etc/ssl/icecast-liquidsoap/icecast.crt (full chain) and /etc/ssl/icecast-liquidsoap/icecast.key (mode 0600), then run sudo systemctl reload nginx. The same certificate serves port 443 and port 8443.
Security checks
The upstream default password is nowhere in the configuration, Icecast listens only on loopback, and Icecast and Liquidsoap cannot start without the first-boot passwords. Verify each point:
sudo grep -c "hack""me" /etc/icecast2/icecast.xml /opt/sac-radio/sac-radio.liq || echo "(no match in either file)"
sudo grep -E '<(port|bind-address)>' /etc/icecast2/icecast.xml systemctl show icecast2 sac-radio -p Requires --value ps -o user:16=,comm= -C liquidsoap/etc/icecast2/icecast.xml:0 /opt/sac-radio/sac-radio.liq:0 (no match in either file) <port>8000</port> <bind-address>127.0.0.1</bind-address> icecast-liquidsoap-firstboot.service system.slice -.mount sysinit.target system.slice -.mount sysinit.target icecast-liquidsoap-firstboot.service sac-radio liquidsoapIcecast, Liquidsoap and nginx are blocked from the instance metadata service, so nothing they fetch (relays, URL authentication or a remote playlist) can reach your instance's credentials:
systemctl show icecast2 sac-radio nginx -p IPAddressDeny --valuefd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32Liquidsoap has clean licensing. It links no FDK AAC or FFmpeg library, and the build reports those encoders as absent:
ldd /opt/liquidsoap/bin/liquidsoap | grep -ciE 'fdk|libav' || true grep -E '^ *- *(FDK-AAC|FFmpeg|Vorbis|Opus) *:' /usr/share/doc/liquidsoap-sac/build-config.txt | sort -u0 - FDK-AAC : no (requires fdkaac) - FFmpeg : no (requires ffmpeg) - Opus : yes - Vorbis : yesMaintenance
- Icecast configuration: The file is
/etc/icecast2/icecast.xml. Apply changes withsudo systemctl restart icecast2. Common changes are raising<clients>in<limits>for a larger audience, and adding<mount>sections for per-mountpoint limits, fallbacks or authentication. Keep the single listen socket on127.0.0.1:8000. nginx publishes it, and Icecast refuses to start with any other socket layout. - Liquidsoap script: The script is
/opt/sac-radio/sac-radio.liq. Check it withsudo -u sac-radio liquidsoap --checkand apply it withsudo systemctl restart sac-radio. The log is in the journal:journalctl -u sac-radio. - Changing the source password: Set
<source-password>(12 or more characters) in/etc/icecast2/icecast.xmlandICECAST_SOURCE_PASSWORDin/var/lib/sac/config/sac-radio/sac-radio.envto the same value. Then restarticecast2andsac-radio, and update/root/icecast-liquidsoap-credentials.txt. The admin and relay passwords live only inicecast.xml. First boot runs only once, so it never overwrites your changes. - Logs: Icecast writes to
/var/log/icecast2/, nginx (with the real client addresses) writes to/var/log/nginx/, and Liquidsoap logs to the journal. - Backups: The configuration files and your music folder
/srv/sac-radio/musicare the only state worth keeping. - Security updates: Unattended security upgrades are on and cover Icecast, nginx and every library that Liquidsoap uses. Reboot when a new kernel is installed. A new version of this image updates Liquidsoap itself.
Licences and source code
Icecast is developed by the Xiph.Org Foundation and licensed under the GNU General Public License version 2. Its source is available from the Ubuntu archive with apt-get source icecast2.
Liquidsoap is developed by the Savonet project and licensed under the GNU General Public License version 2 or later. This build links the GPL version 3 or later ocaml-metadata library, so the Liquidsoap binary on this image is distributed under the GNU General Public License version 3 or later. The licence text, the exact build configuration and the list of every OCaml package used are in /usr/share/doc/liquidsoap-sac/. The complete corresponding source, which includes every archive the binary was built from, is in /usr/local/src/liquidsoap-2.4.6-source/.
Support
SecureAnyCloud provides 24/7/365 technical support for this image. Contact sales@secureanycloud.com. SecureAnyCloud provides this image and is not affiliated with or endorsed by the Xiph.Org Foundation or the Savonet project.
Deploy on AWS
Launch Icecast 2.4.4 with Liquidsoap 2.4.6 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com