FreshRSS es un agregador de feeds RSS y Atom autoalojado, rápido y ligero, que permite seguir cientos de fuentes desde una interfaz web y sincronizarlas con aplicaciones móviles gracias a su API compatible con Google Reader y Fever. En esta guía instalarás FreshRSS con Docker Compose en Ubuntu 24.04, lo publicarás con Nginx y un certificado de Let's Encrypt y lo conectarás a una app de lectura.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. Con 512 MB de RAM libres es suficiente para uso personal.
  • Un usuario no root con privilegios sudo.
  • Docker Engine y el plugin Docker Compose instalados desde el repositorio oficial de Docker.
  • Un subdominio, por ejemplo rss.tu_dominio.com, con un registro DNS A apuntando a la IP pública del servidor.
  • Los puertos 80 y 443 accesibles desde Internet.

Sustituye rss.tu_dominio.com por tu subdominio en todos los comandos y archivos.

Paso 1: Crear el archivo de Docker Compose

FreshRSS guarda la configuración, los usuarios y, con SQLite, también los artículos en su directorio data. Crea un directorio para el despliegue:

sudo mkdir -p /opt/freshrss
cd /opt/freshrss

Crea el archivo de Compose:

sudo nano /opt/freshrss/docker-compose.yml
services:
  freshrss:
    image: freshrss/freshrss:latest
    container_name: freshrss
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
    environment:
      TZ: Europe/Madrid
      CRON_MIN: "3,33"
      TRUSTED_PROXY: 172.16.0.1/12 192.168.0.1/16
    volumes:
      - ./data:/var/www/FreshRSS/data
      - ./extensions:/var/www/FreshRSS/extensions
    logging:
      options:
        max-size: 10m

Qué hace cada opción:

  • CRON_MIN activa el cron interno de la imagen, que actualiza todos los feeds en los minutos indicados (aquí, dos veces por hora).
  • TRUSTED_PROXY indica a FreshRSS que confíe en las cabeceras X-Forwarded-* que llegan desde las redes internas de Docker, donde está el Nginx del host visto desde el contenedor.
  • El puerto se publica solo en 127.0.0.1, porque el acceso público pasará por Nginx. Así el contenedor no queda expuesto aunque Docker gestione sus propias reglas de iptables.

Paso 2: Arrancar el contenedor

Levanta el servicio:

sudo docker compose up -d

Comprueba que está en marcha y que responde en el puerto local:

sudo docker compose ps
curl -I http://127.0.0.1:8080
NAME       IMAGE                      STATUS
freshrss   freshrss/freshrss:latest   Up 15 seconds

HTTP/1.1 200 OK

Una respuesta 200 o una redirección 302 indica que Apache y PHP funcionan dentro del contenedor. Mientras no esté instalado, FreshRSS muestra el asistente de instalación.

Paso 3: Publicar FreshRSS con Nginx y HTTPS

Instala Nginx y Certbot:

sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx

Crea el bloque de servidor:

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

    location / {
        proxy_pass http://127.0.0.1:8080;
        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;
        proxy_set_header X-Forwarded-Host $host;
        proxy_read_timeout 90s;
    }
}

Activa el sitio y recarga Nginx:

sudo ln -s /etc/nginx/sites-available/freshrss /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Si usas UFW, abre SSH y los puertos web:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Solicita el certificado. Certbot añadirá la configuración de HTTPS y la redirección desde HTTP:

sudo certbot --nginx -d rss.tu_dominio.com

Verifica el acceso por HTTPS:

curl -I https://rss.tu_dominio.com
HTTP/2 200

Paso 4: Completar el asistente de instalación

Abre https://rss.tu_dominio.com en el navegador. El asistente te guía en cuatro pantallas:

  1. Idioma: elige Español.
  2. Comprobaciones: todas deben aparecer en verde. Si falla la escritura en data, revisa el volumen del Paso 1.
  3. Base de datos: elige SQLite. Para un uso personal o familiar es la opción más simple y no necesita otro contenedor.
  4. Usuario administrador: define el nombre de usuario (por ejemplo tu_usuario) y una contraseña robusta.

Al terminar, inicia sesión. El asistente detecta la URL base a partir de la petición que le llega a través de Nginx y la guarda en /opt/freshrss/data/config.php. Compruébalo, porque la API y los enlaces dependen de ella:

sudo grep base_url /opt/freshrss/data/config.php
  'base_url' => 'https://rss.tu_dominio.com',

Paso 5: Añadir feeds y comprobar la actualización

Usa el botón + del menú lateral (Gestión de suscripciones) para añadir la URL de un feed, o importa tus suscripciones de otro lector desde Importar/exportar con un archivo OPML.

No hace falta esperar al cron para comprobar que las actualizaciones funcionan. Lanza una actualización manual como el usuario www-data del contenedor:

sudo docker compose exec --user www-data freshrss php ./app/actualize_script.php

La salida termina con un resumen de los feeds procesados. Para listar los usuarios y sus datos básicos:

sudo docker compose exec --user www-data freshrss php ./cli/list-users.php

La salida debe incluir el usuario que creaste en el asistente.

A partir de ahora el cron interno actualizará los feeds en los minutos definidos en CRON_MIN.

Paso 6: Activar la API para aplicaciones móviles

FreshRSS implementa la API de Google Reader, compatible con apps como Read You, FeedMe o NetNewsWire, y la API de Fever para clientes más antiguos.

  1. Como administrador, ve a Configuración > Administración > Autenticación y marca Permitir el acceso a la API.
  2. En Configuración > Cuenta > Perfil, define una contraseña de API. Es distinta de la contraseña de la web y es la que usarán las apps.

Comprueba que la autenticación de la API funciona:

curl -s 'https://rss.tu_dominio.com/api/greader.php/accounts/ClientLogin?Email=tu_usuario&Passwd=tu_contraseña_api'
SID=tu_usuario/0123456789abcdef...
LSID=null
Auth=tu_usuario/0123456789abcdef...

En la app, elige el tipo de cuenta FreshRSS o Google Reader API y usa como servidor https://rss.tu_dominio.com/api/greader.php, con tu usuario y la contraseña de API. La URL de la API de Fever es https://rss.tu_dominio.com/api/fever.php.

Paso 7: Instalar extensiones (opcional)

Las extensiones oficiales y de la comunidad se publican en el repositorio FreshRSS/Extensions. Para instalar una, copia su directorio xExtension-* al volumen de extensiones. Por ejemplo, la extensión de YouTube, que incrusta los vídeos de los feeds de canales:

sudo apt install -y git
git clone --depth 1 https://github.com/FreshRSS/Extensions.git /tmp/freshrss-extensions
sudo cp -r /tmp/freshrss-extensions/xExtension-YouTube /opt/freshrss/extensions/

Recarga la web y actívala en Configuración > Extensiones. Si no aparece, lista el contenido de /tmp/freshrss-extensions para comprobar el nombre exacto del directorio.

Paso 8: Copias de seguridad y actualización

Con SQLite, todo el estado está en /opt/freshrss/data. Además de copiar ese directorio, conviene exportar las suscripciones de cada usuario en OPML, un formato que cualquier lector importa:

sudo docker compose exec --user www-data freshrss php ./cli/export-opml-for-user.php --user tu_usuario | sudo tee /opt/freshrss/suscripciones.opml > /dev/null

Para actualizar FreshRSS a la última versión estable, descarga la imagen nueva y recrea el contenedor:

cd /opt/freshrss
sudo docker compose pull
sudo docker compose up -d

Solución de problemas

Los feeds no se actualizan solos. Comprueba que CRON_MIN está definido con sudo docker compose exec freshrss env | grep CRON_MIN y revisa el registro de cada usuario en Configuración > Registros. Si la actualización manual del Paso 5 funciona, el problema está en el cron; si falla, en la red o en el propio feed.

Las apps no conectan o devuelven "Unauthorized". Asegúrate de que el acceso a la API está activado, de que usas la contraseña de API y no la de la web, y de que la URL base del Paso 4 empieza por https://. Si no es así, corrige base_url en /opt/freshrss/data/config.php y recarga la página.

Enlaces o redirecciones apuntan a 127.0.0.1:8080. Falta la cabecera Host o TRUSTED_PROXY no incluye la red de Docker. Revisa el bloque de Nginx y el docker-compose.yml y recrea el contenedor con sudo docker compose up -d.

Conclusión

Tienes FreshRSS funcionando en Docker, publicado con HTTPS y accesible desde tus aplicaciones móviles mediante la API de Google Reader. Como siguientes pasos, crea cuentas para otros usuarios desde Configuración > Administración > Gestión de usuarios, desactiva el registro abierto si no lo necesitas y programa la copia de /opt/freshrss/data junto con el resto de copias de seguridad del servidor.