Icecast es un servidor de streaming de audio libre que recibe una señal de un cliente fuente (un programa de DJ, FFmpeg o un automatizador como Liquidsoap) y la reparte a todos los oyentes conectados en formatos como MP3, Ogg Vorbis u Opus. En este tutorial instalarás Icecast 2 en Ubuntu 24.04, configurarás contraseñas y un punto de montaje, montarás una radio automática 24/7 con Liquidsoap y la publicarás por HTTPS con Nginx.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. Con 1 GB de RAM es suficiente para cientos de oyentes; el límite real es el ancho de banda.
  • Un usuario no root con privilegios sudo.
  • Un dominio con un registro A que apunte a la IP del servidor, por ejemplo radio.tu_dominio, para el paso de HTTPS.
  • Ficheros de audio en MP3 u Ogg para la radio automática.

Para dimensionar el ancho de banda, multiplica el bitrate por los oyentes simultáneos: 128 kbps x 200 oyentes son unos 25 Mbps de salida sostenida.

Paso 1: Instalar Icecast

Icecast está en los repositorios de Ubuntu con el nombre icecast2:

sudo apt update
sudo apt install icecast2

Durante la instalación aparece un asistente que pregunta si quieres configurar Icecast2. Puedes responder No: en el siguiente paso editarás el fichero de configuración directamente, que es más claro y reproducible.

Comprueba que el servicio está activo y escucha en el puerto 8000:

sudo systemctl status icecast2 --no-pager
sudo ss -tlnp | grep 8000
LISTEN 0      5            0.0.0.0:8000       0.0.0.0:*    users:(("icecast2",pid=2143,fd=4))

Paso 2: Configurar contraseñas, límites y punto de montaje

Toda la configuración está en /etc/icecast2/icecast.xml. Haz una copia antes de editarlo:

sudo cp /etc/icecast2/icecast.xml /etc/icecast2/icecast.xml.orig

Genera tres contraseñas distintas, una para las fuentes, otra para los relays y otra para la administración:

for i in 1 2 3; do openssl rand -base64 18; done

Abre el fichero:

sudo nano /etc/icecast2/icecast.xml

Localiza el bloque <authentication> y sustituye las contraseñas por defecto (hackme) por las que acabas de generar:

<authentication>
    <source-password>contraseña_fuente</source-password>
    <relay-password>contraseña_relay</relay-password>
    <admin-user>admin</admin-user>
    <admin-password>contraseña_admin</admin-password>
</authentication>

Cambia el nombre de host, que Icecast usa para construir las URL de las listas de reproducción:

<hostname>radio.tu_dominio</hostname>

Revisa el bloque <limits>. Los valores por defecto están bien para empezar; ajusta clients al número máximo de oyentes que tu ancho de banda puede servir:

<limits>
    <clients>200</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-on-connect>1</burst-on-connect>
    <burst-size>65535</burst-size>
</limits>

Por último, añade un punto de montaje con los metadatos de la emisora. Colócalo dentro de <icecast>, por ejemplo justo después del bloque <authentication>:

<mount type="normal">
    <mount-name>/radio</mount-name>
    <stream-name>Mi Radio</stream-name>
    <stream-description>Música las 24 horas</stream-description>
    <genre>Varios</genre>
    <max-listeners>200</max-listeners>
    <public>0</public>
</mount>

Con <public>0</public> la emisora no se anuncia en directorios públicos como dir.xiph.org. Valida la sintaxis del XML antes de reiniciar:

sudo apt install libxml2-utils
xmllint --noout /etc/icecast2/icecast.xml && echo "XML correcto"
XML correcto

Reinicia el servicio:

sudo systemctl restart icecast2

Si usas UFW, abre el puerto 8000 para que los oyentes y los clientes fuente remotos puedan conectarse, además de SSH:

sudo ufw allow OpenSSH
sudo ufw allow 8000/tcp
sudo ufw enable

Abre http://ip_del_servidor:8000 en el navegador. Verás la página de estado de Icecast, todavía sin ningún punto de montaje activo porque no hay fuente emitiendo.

Paso 3: Emitir una prueba con FFmpeg

Antes de montar la automatización, comprueba que Icecast acepta fuentes emitiendo un fichero con FFmpeg. La opción -re lee el fichero a velocidad real, como haría una emisora:

sudo apt install ffmpeg
ffmpeg -hide_banner -re -i /ruta/a/cancion.mp3 \
  -c:a libmp3lame -b:a 128k -content_type audio/mpeg -f mp3 \
  "icecast://source:contraseña_fuente@localhost:8000/radio"

Mientras se emite, en otra terminal consulta las estadísticas públicas en JSON:

sudo apt install jq
curl -s http://localhost:8000/status-json.xsl | jq '.icestats.source | {listenurl, server_name, listeners}'
{
  "listenurl": "http://radio.tu_dominio:8000/radio",
  "server_name": "Mi Radio",
  "listeners": 0
}

Abre http://ip_del_servidor:8000/radio en un reproductor como VLC o en el navegador para escucharlo. Detén FFmpeg con Ctrl+C.

Los programas de escritorio como BUTT o Mixxx se conectan igual: servidor radio.tu_dominio, puerto 8000, tipo Icecast, usuario source, la contraseña de fuente y el punto de montaje /radio.

Paso 4: Radio automática con Liquidsoap

Liquidsoap es un lenguaje para crear emisoras: lee listas de reproducción, hace fundidos entre canciones, cambia a una señal en directo cuando se conecta un DJ y envía el resultado a Icecast. Instálalo desde los repositorios:

sudo apt install liquidsoap
liquidsoap --version

Crea un usuario de sistema para la radio y una carpeta para la música:

sudo useradd --system --home-dir /srv/radio --shell /usr/sbin/nologin radio
sudo mkdir -p /srv/radio/musica
sudo chown -R radio:radio /srv/radio

Copia tus ficheros de audio a /srv/radio/musica y crea el script de la emisora:

sudo nano /srv/radio/radio.liq
settings.log.stdout := true
settings.log.file := false

# Lista aleatoria que se relee cada hora para detectar canciones nuevas
musica = playlist(mode="randomize", reload=3600, "/srv/radio/musica")

# Fundido entre canciones y silencio si la lista se queda vacía
radio = mksafe(crossfade(musica))

output.icecast(
  %mp3(bitrate=128),
  host="localhost",
  port=8000,
  password="contraseña_fuente",
  mount="/radio",
  name="Mi Radio",
  description="Música las 24 horas",
  genre="Varios",
  radio
)

Como el script contiene la contraseña de fuente, restringe sus permisos y compruébalo sin emitir:

sudo chown radio:radio /srv/radio/radio.liq
sudo chmod 600 /srv/radio/radio.liq
sudo -u radio liquidsoap --check /srv/radio/radio.liq

Si no hay salida, el script es correcto. Crea un servicio de systemd para que la emisora arranque con el sistema y se reinicie si falla:

sudo nano /etc/systemd/system/liquidsoap-radio.service
[Unit]
Description=Radio automática con Liquidsoap
After=network-online.target icecast2.service
Wants=network-online.target

[Service]
User=radio
Group=radio
ExecStart=/usr/bin/liquidsoap /srv/radio/radio.liq
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Activa el servicio y revisa el log:

sudo systemctl daemon-reload
sudo systemctl enable --now liquidsoap-radio
journalctl -u liquidsoap-radio -n 20 --no-pager

Busca líneas indicando que la salida se ha conectado a Icecast y el nombre de la canción que está sonando. Vuelve a consultar status-json.xsl y verás el punto de montaje /radio activo, ahora sin depender de ninguna terminal abierta.

Paso 5: Publicar la radio por HTTPS con Nginx

Los navegadores bloquean el audio HTTP dentro de páginas HTTPS, así que para incrustar la radio en una web necesitas servirla por HTTPS. Instala Nginx y Certbot:

sudo apt install nginx certbot python3-certbot-nginx
sudo ufw allow "Nginx Full"

Crea el sitio para la radio:

sudo nano /etc/nginx/sites-available/radio
server {
    listen 80;
    listen [::]:80;
    server_name radio.tu_dominio;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # El audio es un flujo continuo: sin búfer y con timeouts largos
        proxy_buffering off;
        proxy_read_timeout 1h;
        proxy_send_timeout 1h;
    }
}

Activa el sitio, valida la configuración y pide el certificado de Let's Encrypt. Certbot añadirá el bloque HTTPS y la redirección:

sudo ln -s /etc/nginx/sites-available/radio /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d radio.tu_dominio

Comprueba que el flujo responde por HTTPS con el tipo de contenido correcto:

curl -s -o /dev/null -D - --max-time 3 https://radio.tu_dominio/radio | grep -i content-type
content-type: audio/mpeg

La URL para los oyentes es ahora https://radio.tu_dominio/radio. Puedes incrustarla en una web con <audio controls src="https://radio.tu_dominio/radio"></audio>.

Paso 6: Consultar oyentes y administrar la emisora

La interfaz de administración está en https://radio.tu_dominio/admin/ y pide el usuario y la contraseña de administración. Desde ahí puedes ver los oyentes, mover oyentes entre puntos de montaje o expulsar una fuente.

Los mismos datos están disponibles como XML para integrarlos en scripts o paneles:

curl -s -u admin:contraseña_admin "http://localhost:8000/admin/listclients?mount=/radio"

Para un recuento rápido de oyentes, la ruta pública status-json.xsl que usaste en el paso 3 no requiere credenciales.

Solución de problemas

Icecast no arranca tras editar la configuración. Casi siempre es un error de sintaxis XML. Ejecuta xmllint --noout /etc/icecast2/icecast.xml y revisa /var/log/icecast2/error.log.

La fuente se desconecta con Authentication failed. El usuario de fuente es source y la contraseña debe coincidir exactamente con <source-password>. Si la contraseña contiene caracteres como @ o /, en la URL icecast:// de FFmpeg tienes que codificarlos (%40, %2F) o generar una contraseña solo alfanumérica.

Mountpoint in use. Ya hay otra fuente emitiendo en ese punto de montaje, por ejemplo Liquidsoap mientras pruebas con FFmpeg. Detén una de las dos o usa otro punto de montaje.

Los oyentes sufren cortes. Revisa el ancho de banda de salida con vnstat -l o en las métricas del servidor. Si hay margen, aumenta <burst-size> para que los reproductores llenen antes su búfer; si no, baja el bitrate o limita <clients>.

Conclusión

Tienes una emisora de radio por internet con Icecast, emisión automática con Liquidsoap gestionada por systemd y acceso HTTPS a través de Nginx. A partir de aquí puedes añadir en Liquidsoap una entrada en directo con input.harbor para que un DJ tome el control, emitir una segunda calidad en Opus o AAC en otro punto de montaje, o repartir la carga entre varios servidores Icecast con relays.