Icecast2 on Ubuntu 20.04 with Nginx, Certbot SSL and Liquidsoap

This is a complete “Howto” with the best settings to quickstart a basic webradio station with a playlist, smart crossfades and autodj rotation. We assume, that you install this on a domain “radio.yourdomain.com“.

Setup Icecast2

Install Icecast. During installation you will be asked for some passwords. Write them down, because you will need it for liquidsoap!

apt-get install icecast2

After installation you will find your configuration in “/etc/icecast2/icecast.xml”. It is a xml file, so you can change all later and modify to your needs.

Edit “/etc/default/icecast2” and insert this:

# Change this to true when done to enable the init.d script
ENABLE=true

Start Icecast:

/etc/init.d/icecast2 start

You will see your radio page on http://radio.yourdomain.com:8000

Stop Icecast:

/etc/init.d/icecast2 stop

That’s it, that was the easy part 🙂

Setup NGINX (as a proxy)

Install:

apt-get install nginx

Now open http://radio.yourdomain.com and you will see a nginx welcome page. Yeah! But we need some proxying and not a webserver. So let’s go deeper now.

Edit the file “/etc/nginx/sites-available/default” and replace all with this (replace radio.yourdomain.com with your domain):

server {
        listen 80;
        listen [::]:80;

	server_name  radio.yourdomain.com;

        access_log /var/log/nginx/reverse-access.log;
        error_log /var/log/nginx/reverse-error.log;

        location / {
                    proxy_pass http://localhost:8000;
  	}
}

Restart nginx now, we want to activate the changes:

/etc/init.d/nginx restart

Voila, you see your webradio page on http://radio.yourdomain.com. You do not need the port number anymore.

But we need SSL/https support, so let’s go to the next part.

Setup Certbot and SSL

Enable the universe repository:

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo apt-get update

Install certbot:

sudo apt-get install certbot python3-certbot-nginx

Start certbot:

sudo certbot --nginx
  1. You will be asked to type a number: Chose 1 to activate SSL on “radio.yourdomain.com”
  2. When you are asked, if you want a redirect, chose “2: Redirect”
  3. Finally you will see the changes in “/etc/nginx/sites-available/default”

Restart nginx:

/etc/init.d/nginx restart

Update the webbrowser and you will be automatically redirected to “https://radio.yourdomain.com”. Voila, you have successfully enabled an icecast webradio with https support.

Liquidsoap 1.4.1 (the “auto dj”)

Main setup:

apt-get install liquidsoap

And some additonal plugins and tools:

apt-get install libaudio2 libbluray-bdj libcamomile-ocaml-dev libfftw3-bin libfftw3-dev libgd-tools libvisual-0.4-plugins jackd2 liblo-dev file opus-tools pulseaudio libraw1394-doc librsvg2-bin lm-sensors serdi sndiod sordi libsox-fmt-all speex festival mplayer youtube-dl  libaacs0 libgdk-pixbuf2.0-bin gstreamer1.0-plugins-base librsvg2-common va-driver-all vdpau-driver-all mesa-vulkan-drivers vulkan-icd vorbis-tools vorbisgain

This has to be done, so the libs are also automatically loaded by Liquidsoap:

mkdir /usr/share/liquidsoap/1.4.1
mv /usr/share/liquidsoap/libs /usr/share/liquidsoap/1.4.1/libs
mv /usr/share/liquidsoap/bin /usr/share/liquidsoap/1.4.1/bin

Add a folder for your playlist, music and configuration:

mkdir /etc/liquidsoap
mkdir /etc/liquidsoap/daemon
touch /etc/liquidsoap/daemon/pid.txt

Save this as “/etc/liquidsoap/crossfade.liq”:

# Crossfade between tracks, 
# taking the respective volume levels 
# into account in the choice of the 
# transition.
# @category Source / Track Processing
# @param ~start_next   Crossing duration, if any.
# @param ~fade_in      Fade-in duration, if any.
# @param ~fade_out     Fade-out duration, if any.
# @param ~width        Width of the volume analysis window.
# @param ~conservative Always prepare for
#                      a premature end-of-track.
# @param s             The input source.
def smart_crossfade (~start_next=5.,~fade_in=3.,
                     ~fade_out=3., ~width=2.,
		     ~conservative=false,s)
  high   = -20.
  medium = -32.
  margin = 4.
  fade.out = fade.out(type="sin",duration=fade_out)
  fade.in  = fade.in(type="sin",duration=fade_in)
  add = fun (a,b) -> add(normalize=false,[b,a])
  log = log(label="smart_crossfade")

  def transition(a,b,ma,mb,sa,sb)

    list.iter(fun(x)-> 
       log(level=4,"Before: #{x}"),ma)
    list.iter(fun(x)-> 
       log(level=4,"After : #{x}"),mb)

    if
      # If A and B and not too loud and close, 
      # fully cross-fade them.
      a <= medium and 
      b <= medium and 
      abs(a - b) <= margin
    then
      log("Transition: crossed, fade-in, fade-out.")
      add(fade.out(sa),fade.in(sb))

    elsif
      # If B is significantly louder than A, 
      # only fade-out A.
      # We don't want to fade almost silent things, 
      # ask for >medium.
      b >= a + margin and a >= medium and b <= high
    then
      log("Transition: crossed, fade-out.")
      add(fade.out(sa),sb)

    elsif
      # Do not fade if it's already very low.
      b >= a + margin and a <= medium and b <= high
    then
      log("Transition: crossed, no fade-out.")
      add(sa,sb)

    elsif
      # Opposite as the previous one.
      a >= b + margin and b >= medium and a <= high
    then
      log("Transition: crossed, fade-in.")
      add(sa,fade.in(sb))

    # What to do with a loud end and 
    # a quiet beginning ?
    # A good idea is to use a jingle to separate 
    # the two tracks, but that's another story.

    else
      # Otherwise, A and B are just too loud 
      # to overlap nicely, or the difference 
      # between them is too large and 
      # overlapping would completely mask one 
      # of them.
      log("No transition: just sequencing.")
      sequence([sa, sb])
    end
  end

  cross(width=width, duration=start_next, 
              conservative=conservative,
              transition,s)
end

Save this as “/etc/liquidsoap/main.liq” and modify it according to your needs. Copy a default mp3 to “/etc/liquidsoap/music/default.mp3”, this will be the fallback for your radio if something goes wrong. Replace “hackme” with the Icecast2 source password.

set("init.allow_root",true)

set("init.daemon.pidfile.path", "/etc/liquidsoap/daemon/pid.txt")
set("init.daemon",true)

%include "crossfade.liq"

myplaylist = playlist(reload=43200,"playlist.pls")
security = single("/etc/liquidsoap/music/default.mp3")

radio = myplaylist
radio = normalize(radio)
radio = smart_crossfade(start_next=8., fade_in=6., fade_out=6., width=2., conservative=true, radio)

radio = fallback(track_sensitive = false, [radio, security])

output.icecast(%vorbis.cbr(samplerate=44100, channels=2, bitrate=128),host = "localhost", port = 8000, password = "hackme", mount = "/stream",name="My cool webradio name", description="A nice description for my webradio",radio)

Now copy all your mp3 files into ” /etc/liquidsoap/music” and run this command to generate a playlist file:

find /etc/liquidsoap/music -type f > /etc/liquidsoap/playlist.pls

If you want to use “ogg” and convert all your mp3 files to ogg, use this:

apt-get install dir2ogg
dir2ogg -r /etc/liquidsoap/music

Start Liquidsoap with this command:

liquidsoap /etc/liquidsoap/main.liq

Stop Liquidsoap:

killall liquidsoap