Difference between revisions of "Streaming Service with Icecast"

From Run Your Own
Jump to: navigation, search
(TLS/SSL Support)
 
(21 intermediate revisions by the same user not shown)
Line 1: Line 1:
Note: we will be using the <code>icecast-kh</code> fork that contains some extra stuff (FIXME: unpack stuff).
+
'''Note:''' we will be using the <code>icecast-kh</code> fork that contains [https://github.com/karlheyes/icecast-kh/blob/master/NEWS some extra stuff and features/fixes/improvements] that may eventually land in vanilla <code>icecast</code>.
  
== Installation (Debian) ==
+
== Installation for a Simple Setup ==
 +
=== Software ===
 
'''Note:''' At time of writing, <code>icecast-kh</code> suffers from [https://github.com/karlheyes/icecast-kh/issues/260 a small compilation problem with OpenSSL].
 
'''Note:''' At time of writing, <code>icecast-kh</code> suffers from [https://github.com/karlheyes/icecast-kh/issues/260 a small compilation problem with OpenSSL].
  
* Install dependencies
+
* Install dependencies (Debian)
 
  apt install libxslt1-dev libogg-dev libvorbis-dev libtheora-dev libcurl4-openssl-dev
 
  apt install libxslt1-dev libogg-dev libvorbis-dev libtheora-dev libcurl4-openssl-dev
 
* Get the sources
 
* Get the sources
Line 14: Line 15:
 
  make
 
  make
 
  make install
 
  make install
 +
 +
=== Firewall ===
 
* Make sure you listen on 8000, adjust your <code>iptables</code>:
 
* Make sure you listen on 8000, adjust your <code>iptables</code>:
 
  -A INPUT -p tcp -m tcp --dport 8000 -j ACCEPT
 
  -A INPUT -p tcp -m tcp --dport 8000 -j ACCEPT
* Create a <code>systemd</code> service file:
+
 
 +
You can adjust to your liking, 8000 is the default for Icecast.
 +
 
 +
=== Basic Configuration ===
 +
Simple setup with <code>icecast</code> accepting 4 sources, changing process ownership to <code>nobody:nogroup</code>, and running in a <code>chroot</code>.
 +
 
 +
* log files in chroot:
 +
mkdir /usr/local/share/icecast/log
 +
chown nobody:nogroup /usr/local/share/icecast/log
 +
* <code>/usr/local/etc/icecast.xml</code>:
 +
<pre>
 +
  <icecast>
 +
      <location>𓅣</location>
 +
      <admin>top.cool@c_est.super.deluxe</admin>
 +
 
 +
      <limits>
 +
          <clients>64</clients>
 +
          <sources>4</sources>
 +
          <queue-size>524288</queue-size>
 +
          <client-timeout>30</client-timeout>
 +
          <header-timeout>15</header-timeout>
 +
          <source-timeout>10</source-timeout>
 +
          <burst-size>65535</burst-size>
 +
      </limits>
 +
 
 +
      <authentication>
 +
          <source-password>hackme</source-password>
 +
          <relay-password>hackme</relay-password>
 +
          <admin-user>admin</admin-user>
 +
          <admin-password>hackme</admin-password>
 +
      </authentication>
 +
 
 +
      <hostname>stream.domain.tld</hostname>
 +
 
 +
      <listen-socket>
 +
          <port>8000</port>
 +
      </listen-socket>
 +
 
 +
      <fileserve>1</fileserve>
 +
 
 +
      <paths>
 +
          <basedir>/usr/local/share/icecast</basedir>
 +
          <logdir>/log</logdir>
 +
          <webroot>/web</webroot>
 +
          <adminroot>/admin</adminroot>
 +
          <alias source="/" dest="/index.html"/>
 +
      </paths>
 +
 
 +
      <logging>
 +
          <accesslog>access.log</accesslog>
 +
          <errorlog>error.log</errorlog>
 +
          <loglevel>1</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
 +
          <logsize>10000</logsize> <!-- Max size of a logfile -->
 +
      </logging>
 +
 
 +
      <security>
 +
          <chroot>1</chroot>
 +
          <changeowner>
 +
              <user>nobody</user>
 +
              <group>nogroup</group>
 +
          </changeowner>
 +
      </security>
 +
  </icecast>
 +
</pre>
 +
 
 +
=== Service file and autostart (systemd) ===
 +
* Create a <code>/etc/systemd/system/icecast.service</code> unit file:
 
<pre>
 
<pre>
 
[Unit]
 
[Unit]
Line 26: Line 95:
 
ExecStart=/usr/local/bin/icecast -c /usr/local/etc/icecast.xml
 
ExecStart=/usr/local/bin/icecast -c /usr/local/etc/icecast.xml
 
ExecReload=/usr/bin/kill -HUP $MAINPID
 
ExecReload=/usr/bin/kill -HUP $MAINPID
 +
 
[Install]
 
[Install]
 
WantedBy=multi-user.target
 
WantedBy=multi-user.target
 
</pre>
 
</pre>
* Enable the service:
+
* Enable the service on boot:
 
  systemctl enable icecast
 
  systemctl enable icecast
 +
* Manage the service with
 +
service icecast start
 +
service icecast status
 +
service icecast stop
  
 +
== MOAR Configuration ==
 +
With the previous section you will get something up and running, stable and all. It's a good starting point to tweak things further.
 +
 +
=== NGINX Reverse Proxy ===
 +
At time of writing, reverse proxying for icecast is not really worth it. Will explain a bit more eventually.
 +
 +
=== TLS/SSL Support ===
 +
It's possible to use existing X.509 certificates to provide HTTPS access to both listeners and sources. For this to work the server and intermediate certificates with the private key.
 +
* merge <code>fullchain.pem</code> with <code>privkey.pem</code> (example with Let's Encrypt certs)
 +
cat /etc/letsencrypt/live/domain.tld/fullchain.pem > /usr/local/share/icecast/icecast.pem
 +
cat /etc/letsencrypt/live/domain.tld/privkey.pem >> /usr/local/share/icecast/icecast.pem
 +
* Adjust <code>icecast.xml</code> config file with <code><ssl-certificate></code> and <code><ssl-allowed-ciphers></code>:
 +
<pre>
 +
      <paths>
 +
          <basedir>/usr/local/share/icecast</basedir>
 +
          <logdir>/log</logdir>
 +
          <webroot>/web</webroot>
 +
          <adminroot>/admin</adminroot>
 +
          <ssl-certificate>/usr/local/share/icecast/icecast.pem</ssl-certificate>
 +
          <ssl-allowed-ciphers>ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:  RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS</ssl-allowed-ciphers>
 +
          <alias source="/" dest="/index.html"/>
 +
      </paths>
 +
</pre>
 +
 +
'''Note:''' If you have used the config file of this documentation, then icecast will be reachable both on <code>http://stream.domain.tld:8000</code> and <code>https://stream.domain.tld:port</code>. You may want to keep it like that as some clients (both for listening and emitting) do not support TLS/SSL. If you want enforce TLS/SSL, you can adjust your config file so that:
 +
<pre>
 +
    <listen-socket>
 +
            <port>999</port>
 +
            <ssl>1</ssl>
 +
    </listen-socket>
 +
</pre>
 +
 +
=== Moar Cores! ===
 +
In <code>icecast-kh</code> it's possible to choose how many threads to use for processing clients. This should be based on the number of CPUs or cores. This can be adjusted in <code>icecast.xml</code> with the following line inside <code><limits></code>:
 +
<workers>4</workers>
 +
 +
=== Relaying an External Stream (the lazy way) ===
 +
This can be done simply by just pointing to the stream you want to relay. Careful though, you need to point to the remote server IP, not the domain. If you add <code><on-demand></code>, the stream will be relayed only if it is requested.
 +
<pre>
 +
    <relay>
 +
        <server>10.10.10.10</server>
 +
        <port>1234</port>
 +
        <mount>/blabla.mp3</mount>
 +
        <local-mount>/blabla.mp3</local-mount>
 +
        <on-demand>1</on-demand>
 +
        <relay-shoutcast-metadata>0</relay-shoutcast-metadata>
 +
    </relay>
 +
</pre>
  
== Configuration ==
+
[[Category: Streaming]]

Latest revision as of 01:13, 16 March 2021

Note: we will be using the icecast-kh fork that contains some extra stuff and features/fixes/improvements that may eventually land in vanilla icecast.

Installation for a Simple Setup

Software

Note: At time of writing, icecast-kh suffers from a small compilation problem with OpenSSL.

  • Install dependencies (Debian)
apt install libxslt1-dev libogg-dev libvorbis-dev libtheora-dev libcurl4-openssl-dev
  • Get the sources
cd /usr/src
git clone https://github.com/karlheyes/icecast-kh
  • Compile and install
cd icecast-kh
./configure --with-openssl
make
make install

Firewall

  • Make sure you listen on 8000, adjust your iptables:
-A INPUT -p tcp -m tcp --dport 8000 -j ACCEPT

You can adjust to your liking, 8000 is the default for Icecast.

Basic Configuration

Simple setup with icecast accepting 4 sources, changing process ownership to nobody:nogroup, and running in a chroot.

  • log files in chroot:
mkdir /usr/local/share/icecast/log
chown nobody:nogroup /usr/local/share/icecast/log
  • /usr/local/etc/icecast.xml:
  <icecast>
      <location>𓅣</location>
      <admin>top.cool@c_est.super.deluxe</admin>
  
      <limits>
          <clients>64</clients>
          <sources>4</sources>
          <queue-size>524288</queue-size>
          <client-timeout>30</client-timeout>
          <header-timeout>15</header-timeout>
          <source-timeout>10</source-timeout>
          <burst-size>65535</burst-size>
      </limits>
  
      <authentication>
          <source-password>hackme</source-password>
          <relay-password>hackme</relay-password>
          <admin-user>admin</admin-user>
          <admin-password>hackme</admin-password>
      </authentication>
  
      <hostname>stream.domain.tld</hostname>
  
      <listen-socket>
          <port>8000</port>
      </listen-socket>
  
      <fileserve>1</fileserve>
  
      <paths>
          <basedir>/usr/local/share/icecast</basedir>
          <logdir>/log</logdir>
          <webroot>/web</webroot>
          <adminroot>/admin</adminroot>
          <alias source="/" dest="/index.html"/>
      </paths>
  
      <logging>
          <accesslog>access.log</accesslog>
          <errorlog>error.log</errorlog>
          <loglevel>1</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
          <logsize>10000</logsize> <!-- Max size of a logfile -->
       </logging>
  
      <security>
          <chroot>1</chroot>
          <changeowner>
              <user>nobody</user>
              <group>nogroup</group>
          </changeowner>
      </security>
  </icecast>

Service file and autostart (systemd)

  • Create a /etc/systemd/system/icecast.service unit file:
[Unit]
Description=Icecast
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/icecast -c /usr/local/etc/icecast.xml
ExecReload=/usr/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target
  • Enable the service on boot:
systemctl enable icecast
  • Manage the service with
service icecast start
service icecast status
service icecast stop

MOAR Configuration

With the previous section you will get something up and running, stable and all. It's a good starting point to tweak things further.

NGINX Reverse Proxy

At time of writing, reverse proxying for icecast is not really worth it. Will explain a bit more eventually.

TLS/SSL Support

It's possible to use existing X.509 certificates to provide HTTPS access to both listeners and sources. For this to work the server and intermediate certificates with the private key.

  • merge fullchain.pem with privkey.pem (example with Let's Encrypt certs)
cat /etc/letsencrypt/live/domain.tld/fullchain.pem > /usr/local/share/icecast/icecast.pem
cat /etc/letsencrypt/live/domain.tld/privkey.pem >> /usr/local/share/icecast/icecast.pem
  • Adjust icecast.xml config file with <ssl-certificate> and <ssl-allowed-ciphers>:
      <paths>
          <basedir>/usr/local/share/icecast</basedir>
          <logdir>/log</logdir>
          <webroot>/web</webroot>
          <adminroot>/admin</adminroot>
          <ssl-certificate>/usr/local/share/icecast/icecast.pem</ssl-certificate>
          <ssl-allowed-ciphers>ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:  RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS</ssl-allowed-ciphers>
          <alias source="/" dest="/index.html"/>
      </paths>

Note: If you have used the config file of this documentation, then icecast will be reachable both on http://stream.domain.tld:8000 and https://stream.domain.tld:port. You may want to keep it like that as some clients (both for listening and emitting) do not support TLS/SSL. If you want enforce TLS/SSL, you can adjust your config file so that:

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

Moar Cores!

In icecast-kh it's possible to choose how many threads to use for processing clients. This should be based on the number of CPUs or cores. This can be adjusted in icecast.xml with the following line inside <limits>:

<workers>4</workers>

Relaying an External Stream (the lazy way)

This can be done simply by just pointing to the stream you want to relay. Careful though, you need to point to the remote server IP, not the domain. If you add <on-demand>, the stream will be relayed only if it is requested.

    <relay>
        <server>10.10.10.10</server>
        <port>1234</port>
        <mount>/blabla.mp3</mount>
        <local-mount>/blabla.mp3</local-mount>
        <on-demand>1</on-demand>
        <relay-shoutcast-metadata>0</relay-shoutcast-metadata>
    </relay>