icecast and https in December 2023

The Problem

It's not really a problem. Today most everything on the web has moved from http to https. This is generally a good thing. However, in the case of icecast, all of the services that I could find for pay-as-you-go internet radio services don't offer icecast+https services to customers.

Ok, wait Mike. Why do I need https on icecast?

Normally, this isn't an issue. You can (still) happily click through all of the 'safety' warnings that web browsers show you when you connect to an http web server. You accept the risks and move on. It's only an issue if you're trying to connect to an endpoint service that will refer to your icecast stream point to play your tream THROUGH it's https web site.

What are you really talking about?

The specific example I was wrestling with was that I was on a pay-as-you-go plan (great plan, actually) from internet-radio.com. They offered an http endpoint with no way to upgrade to https. This works well for most podcasts that want to just stream the audio from their show to their listeners using, for example, the Podcasting 2.0 Live Item Tag (LIT). However, now we live in the age of modern podcast applications, Live Item Tag, and "Wallet Switching Technology" to allow listeners to load up their podcast app's wallet with satoshis and stream and/or boost through the live music podcast to the artist/musician that is playing at that specific time in the live show.

How does that happen? Well today, that only happens through Steven Bell's The Split Kit (TSK). TSK is a remarkable web application that allows podcasters to create a variety of types of "Events"; one of which is great for enabling music to be played during a live podcast, but the main feature is that listeners can go to the Event page published by the podcaster that is hosted by TSK. On that page, you will see album art, and other links, including a link to "Boost" the podcast and/or the song currently playing while you are on that page. The audio feed eminating from that page is the podcast's live feed, effectively 'relayed' through the split kit, and that event web page has all of the machinery within it to get those sats to the right place; something you could never do on a plain ole' icecast server.

TL;DR

So in summary, we need for listeners to live events presented by TSK to be able to hear the live audio stream when they click the 'play' button on the event page hosted by TSK. Most all icecast hosting services still use http. The Split Kit (TSK) needs an incoming https icecast stream to relay through it's own https event page.

Hello to self-hosting icecast

First thing that you need to host icecast is a Virtual Private Server (VPS). I have set up My icecast/internet radio service provider does not, and most importantly, the icecast build available through my standard Ubuntu 22.04 build doesn't support https. Why?

Although I started here Host Your Own Icecast Streaming Server for $3.50/month, which is a nice overview from five years ago on starting from scratch; shiny fresh Vultr VPS onward, I really should have started with his other fine article that he wrote 18 months later, Icecast HTTPS/SSL with Let’s Encrypt: Setup Guide, and referenced back to that first article

BTW, Icecast is maintained and documented here.

Not straightforward...

Let's Do This

Enough ramble. Here's the quick and dirty of what I did. I'll try not to skip too many steps. :)

Set up a fresh VPS

For me, I set up a $5 Ubuntu 22.04 LTS VPS on Linode.com with backup ($7 + tax/month, all in), tightened things up a bit, ran the usual updates, set my hostname ("streams"), and then set my DNS to point to the FQDN "streams.mydomain.com" (well, my real FQDN). I set up both IPv4 and IPv6 DNS records. This is kinda important to do now, because you'll need to have this working properly by the time you get icecast2 installed and certainly in order to set up https using Let's Encrypt.

Once your server is up and idling, and your DNS resolves correctly to your IP address, it's time to install icecast2.

Install icecast2

Two important things:
1. Download an icecast2 for your distro that has https support pre-built into it. The standard distros do NOT support https.
2. install libssl1.1 - icecast2's https support relies on this old version of the SSL library, but these get patched-up fairly well because of old builds of code that rely on them.

I thought about adding the Xiph icecast2 distro to my Ubuntu sources list, but not only is the signing key expired (2024-06-07, without replacement that I can see), but apt-key is strongly depreciated and won't be available at all beyond Ubuntu 22.04. I'm just going to install directly using dpkg and set a calendar reminder to check Xiph every six months or so. Maybe.

Download what you need; openssl1.1 and of course icecast2

Let's get that older version of openssl installed first. Although it's an older version, some valiant developers maintain/patch older ssl implementations for just the occasion we are facing; old software that runtime dependencies to old SSL versions. It's been built recently (November 2023).

wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.20_amd64.deb
dpkg -i ./libssl1.1_1.1.1f-1ubuntu2.20_amd64.deb

Now for Icecast2

https://www.icecast.org/download/ gives the scoop on downloading icecast for your distro.

On Ubuntu, the most recent build is https://download.opensuse.org/repositories/multimedia:/xiph/xUbuntu_18.04/amd64/ (March 2022). Which leads to doing a

wget https://download.opensuse.org/repositories/multimedia:/xiph/xUbuntu_18.04/amd64/icecast2_2.4.4-1_amd64.deb

apt install ./icecast2_2.4.4-1_amd64.deb

apt comes back with "Suggested packages: ices2 speex", which if you continue down that trail of suggested packages, your installation list goes on forever... I just said "Y" to continue and ignored the optional/suggested packages.

This takes you straight in to the configuration dialogs. Don't skip any of these. Heed the advice on Icecast hosting Setup Guide - Install Icecast and fill everything out and make sure you don't loose your passwords. After the dialogs are complete, icecast should start and be running.

Check with systemctl status icecast2

user@streams:~$ systemctl status icecast2
● icecast2.service - LSB: Icecast2 streaming media server
     Loaded: loaded (/etc/init.d/icecast2; generated)
     Active: active (running) since Wed 2023-11-29 21:19:10 CST; 1min 32s ago
       Docs: man:systemd-sysv-generator(8)
    Process: 3494 ExecStart=/etc/init.d/icecast2 start (code=exited, status=0/SUCCESS)
      Tasks: 4 (limit: 1013)
     Memory: 6.4M
        CPU: 45ms
     CGroup: /system.slice/icecast2.service
             └─3499 /usr/bin/icecast2 -b -c /etc/icecast2/icecast.xml

Configure icecast2 to answer on Port 80 - VERY IMPORTANT

Don't argue with The Man (not me, I'm not 'The Man'); the author of this note: https://lists.xiph.org/pipermail/icecast/2015-February/013171.html. This works and is mandatory. He explained it a bit more here https://stackoverflow.com/questions/63440977/how-to-get-icecast-to-run-on-port-80

Edit two lines in /etc/default/icecast2:

USERID=root
GROUPID=root

Edit the following lines in /etc/icecast2/icecast.xml:

this must be the first entry

    <listen-socket>
        <port>80</port>
    <listen-socket>

then in the security section:

        <changeowner>
            <user>icecast2</user>
            <group>icecast</group>
        </changeowner>

for yp listings, make sure <hostname> resolves to your Icecast server (not your homepage!) and remove the <!-- --> around the <directory> section.

Start Icecast through its init script / systemd:

user@streams:~$ sudo systemctl restart icecast2
user@streams:~$ sudo systemctl status icecast2
● icecast2.service - LSB: Starts the icecast audio streaming server daemon
     Loaded: loaded (/etc/init.d/icecast2; generated)
     Active: active (running) since Tue 2023-12-19 02:48:06 UTC; 9s ago
       Docs: man:systemd-sysv-generator(8)
    Process: 3143 ExecStart=/etc/init.d/icecast2 start (code=exited, status=0/SUCCESS)
      Tasks: 4 (limit: 1013)
     Memory: 2.7M
        CPU: 18ms
     CGroup: /system.slice/icecast2.service
             └─3145 /usr/bin/icecast2 -b -c /etc/icecast2/icecast.xml

Dec 19 02:48:06 streams icecast2[3143]: Starting icecast2:
Dec 19 02:48:06 streams icecast2[3144]: Starting icecast2
Dec 19 02:48:06 streams icecast2[3144]: Detaching from the console
Dec 19 02:48:06 streams icecast2[3143]: icecast2.
Dec 19 02:48:06 streams systemd[1]: Started LSB: Starts the icecast audio streaming server daemon.
Dec 19 02:48:06 streams icecast2[3145]: Starting icecast2
Dec 19 02:48:06 streams icecast2[3145]: Detaching from the console
Dec 19 02:48:06 streams icecast2[3145]: Changed groupid to 118.
Dec 19 02:48:06 streams icecast2[3145]: Changed supplementary groups based on user: icecast2.
Dec 19 02:48:06 streams icecast2[3145]: Changed userid to 114.  

You can now just go to http://streams.yourdomain.com and you'll see your server running. Clicking on "Admin Home", and entering Username: admin, Password: to see the number of active connections, listeners, etc.

For me, it's up and running on Port 80. Now to enable ssl...

Adding SSL using LetsEncrypt

Now let's enable SSL using LetsEncrypt: https://www.mediarealm.com.au/articles/icecast-https-ssl-setup-lets-encrypt/

apt-get install certbot

sudo certbot certonly --webroot-path="/usr/share/icecast2/web" -d 'streams.yourdomain.com'

Choose option 2, the 'webroot' option.

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/streams.yourdomain.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/streams.yourdomain.com/privkey.pem
This certificate expires on 2024-02-28.

But icecast2 doesn't know how to handle those two files. We need to create a new file that is a concatenation of those two files.

cat /etc/letsencrypt/live/streams.mydomain.com/fullchain.pem /etc/letsencrypt/live/streams.mydomain.com/privkey.pem > /etc/icecast2/bundle.pem

Since we configured icecast to run as icecast2 in the port 80 activation step, above, we can chown, rather than chmod the file with a not-so-great read permission for all, because that file contains the private key of our server certificate.

chown icecast2:root /etc/icecast2/bundle.pem

The LetsEncrypt certificate will expire in 90 days, so let's make sure that we can do a renewal.

Enabling LetsEncrypt Certificate Renewal

I wrote a short script since the string given by the OP didn't work well for me. Probably a string error encapsulating a few commands, but regardless, this script seems to do the trick, or more likely, something changed in the certbot implementation/parsing of that file (c.f. a comment on the OP).

Regardless, I wrote this script...

/etc/icecast2/concatforice.sh and set the permissions mask to 750 and ownershipw to icecast2:root

#!/bin/sh

cat /etc/letsencrypt/live/streams.mydomain.com/fullchain.pem /etc/letsencrypt/live/streams.mydomain.com/privkey.pem > /etc/icecast2/bundle.pem

chown icecast2:root /etc/icecast2/bundle.pem
chmod 640 /etc/icecast2/bundle.pem

systemctl restart icecast2

Now we go to the LetsEncrypt renewal configuration file for the FDQN.

vi /etc/letsencrypt/renewal/streams.mydomain.com.conf

and add this to the [renewalparams] section:

post_hook = /etc/icecast2/concatforice.sh  

Do a test certificate renewal to check that it will/should work correctly:
certbot renew --dry-run

Configure icecast to use SSL

We have our certificate, now we need to configure icecast to use that server certificate that will be maintained by LetsEncrypt for us. Edit icecast.xml in a text editor: vi /etc/icecast2/icecast.xml adding
/etc/icecast2/bundle.pem

And add the following section to the document in the root XML node:

<listen-socket>
    <port>443</port>
    <ssl>1</ssl>
</listen-socket>  

Remember that the listen-socket section for port 80 must be the first listed. I just added the port 443 section directly below the port 80 section to avoid any confusion.

Now just restart the icecast service: service icecast2 restart

You should be able to now browse to https://streams.mydomain.com and listen to and serve your stream over https.

social