Netflix casero: como montar tu propio streaming con NixOS (y por que Stremio no es suficiente)


28 de febrero de 2026

La historia: solo queriamos ver Paprika

Todo empezo porque Pascual queria ver Paprika (2006, Satoshi Kon, peliculon). Teniamos Stremio montado en Docker, le damos play y… "video not supported". Probamos otro stream. Mismo error. Y otro. Igual.

Resulta que el streaming server dentro del container llevaba dias muerto. El nginx del frontend servia la UI bonita, pero cuando pedias un video real, 502. Connection refused al puerto 11470. Fantastico.

Lo reiniciamos. Ahora arranca, pero transcodea 4K HEVC por software en un AMD FX-8350 sin GPU. A ver, el FX-8350 es un clasico, pero transcodear 4K x265 en tiempo real no es lo suyo. El resultado: buffering infinito, artefactos, y Pascual diciendo "esto va como el culo".

Intentamos descargar el torrent directamente con aria2. Resultado: archivo de 5.3GB que parecia completo pero estaba corrupto. Preallocado pero vacio por dentro. Peerflix? Roto con Node 22. Webtorrent-cli? Eliminado de nixpkgs. El cliente desktop de Stremio? Depende de qtwebengine que nixpkgs marca como inseguro por CVEs.

Sabado por la noche y no pudimos ver la peli.

El domingo dijimos: se acabo el chapuceo. Vamos a montar esto bien.

El problema con Stremio (y servicios similares)

Stremio es genial como concepto: buscas una peli, le das play, y ya. Pero tiene problemas fundamentales cuando lo autoalojas:

La solucion no es arreglar Stremio. Es montar un sistema que separe las responsabilidades.

La arquitectura: 4 piezas, cada una hace una cosa

TU (movil/tablet/portatil/smart TV)
          |
          v
┌─────────────────┐
│    Jellyfin     │  <- reproductor (Netflix UI)
│    :8096        │     sin transcodeo, direct play
└────────┬────────┘
         |
 lee archivos de
         |
/storage/media/movies/
         ^
         |
  mueve aqui cuando
  termina descarga
         |
┌─────────────────┐
│     Radarr      │  <- gestor de peliculas
│     :7878       │     busca, elige calidad, organiza
└────────┬────────┘
         |
    busca en           descarga via
         |                  |
┌────────v────────┐  ┌──────v──────────┐
│    Prowlarr     │  │  Transmission   │
│    :9696        │  │     :9091        │
│ (indexador)     │  │ (cliente torrent)│
└─────────────────┘  └─────────────────┘
         |
  busca en sitios
  (TPB, 1337x, etc.)

Jellyfin: el reproductor (puerto 8096)

Jellyfin es tu Netflix privado. Interfaz web bonita, apps para movil, smart TV, Fire Stick, Chromecast. Escanea tu carpeta de pelis, descarga caratulas, sinopsis, puntuaciones, y te lo presenta como un catalogo.

La clave: direct play. Jellyfin no transcodea si el dispositivo soporta el codec. Un navegador moderno con un mkv h264 1080p? Direct play. Cero CPU. El FX-8350 descansa.

Por eso descargamos en 1080p x264: compatible con todo sin transcodear.

Radarr: el gestor de peliculas (puerto 7878)

Radarr es el cerebro. Le dices "quiero Paprika" y el:

  1. Busca en todos los indexadores configurados (via Prowlarr)
  2. Filtra por calidad (1080p, x264, idioma)
  3. Elige la mejor release
  4. Manda el torrent a Transmission
  5. Cuando termina, renombra el archivo y lo mueve a la carpeta correcta
  6. Jellyfin detecta el archivo nuevo y lo anade a tu biblioteca

Tu no tocas nada. Buscas, click, y cuando esta listo aparece en Jellyfin.

Prowlarr: el indexador (puerto 9696)

Prowlarr busca en sitios de torrents por ti. Le configuras los indexadores una vez (The Pirate Bay, 1337x, RARBG, etc.) y Radarr busca a traves de el.

Sin Prowlarr tendrias que ir a cada web de torrents, buscar manualmente, copiar el magnet link, pegarlo en el cliente torrent… exactamente lo que Pascual decia que era "un poculoo". Prowlarr elimina todo eso.

Transmission: el cliente torrent (puerto 9091)

Transmission descarga. Punto. Es ligero, estable, y tiene web UI por si quieres ver el progreso. Radarr le manda los torrents automaticamente y el los descarga a /storage/media/downloads/. Cuando termina, Radarr lo mueve a /storage/media/movies/.

Como fluye todo junto

Quieres ver Coco con el crio:

  1. Abres Radarr (:7878), buscas "Coco", click en Add Movie
  2. Radarr pregunta a Prowlarr: "oye, tienes Coco 2017 en 1080p?"
  3. Prowlarr busca en The Pirate Bay, encuentra 8 releases, se las pasa a Radarr
  4. Radarr elige la mejor (1080p Remux, audio castellano, 7.1), y le dice a Transmission: "descarga esto"
  5. Transmission descarga el torrent. Tarda lo que tarda tu conexion
  6. Cuando termina, Radarr mueve el archivo a /storage/media/movies/Coco (2017)/, bien nombrado
  7. Jellyfin detecta el archivo nuevo, descarga la caratula de TMDB, y lo anade al catalogo
  8. Abres Jellyfin (:8096) en el movil/tablet/tele y le das play. Direct play, sin buffering

Total de clicks tuyos: 3 (buscar, anadir, play). El resto es automatico.

Por que esto es mejor que Stremio

Stremio Media Stack
Buscar peli En la app En Radarr
Descarga Streaming en tiempo real Descarga completa primero
Calidad Lo que pille el torrent Tu eliges calidad y idioma
Codec problems "video not supported" Direct play, sin transcodeo
Biblioteca No tiene, efimero Jellyfin con caratulas y metadatos
Offline No Si, los archivos son tuyos
Multi-dispositivo Solo web browser Apps nativas (movil, TV, Fire Stick)
Fiabilidad Streaming server se muere 4 servicios independientes, cada uno reinicia solo

La ventaja clave: los archivos son tuyos. Estan en tu disco. No dependes de que haya seeders en el momento que quieras ver la peli. Descargas una vez, ves cuando quieras, desde donde quieras.

La implementacion: un modulo NixOS

Todo el stack esta en un unico modulo NixOS: media-stack.nix. 107 lineas.

# En hosts/vespino/default.nix - esto es TODO lo que necesitas
dotfiles.media-stack = {
  enable = true;
  mediaPath = "/storage/media";
};

Dos lineas. Eso levanta Jellyfin, Radarr, Prowlarr y Transmission, crea los directorios con permisos correctos, configura el grupo compartido media para que todos los servicios se entiendan, y abre los puertos del firewall.

El modulo completo:

{ config, lib, pkgs, ... }:

let
  cfg = config.dotfiles.media-stack;
in
{
  options.dotfiles.media-stack = {
    enable = lib.mkEnableOption "Media stack (Jellyfin + Radarr + Prowlarr + Transmission)";
    mediaPath = lib.mkOption {
      type = lib.types.str;
      default = "/storage/media";
    };
  };

  config = lib.mkIf cfg.enable {
    services.jellyfin = { enable = true; openFirewall = true; };
    services.radarr   = { enable = true; openFirewall = true; };
    services.prowlarr = { enable = true; openFirewall = true; };

    services.transmission = {
      enable = true;
      package = pkgs.transmission_4;
      openFirewall = true;
      settings = {
        download-dir = "${cfg.mediaPath}/downloads";
        incomplete-dir = "${cfg.mediaPath}/downloads/.incomplete";
        incomplete-dir-enabled = true;
        rpc-bind-address = "0.0.0.0";
        rpc-whitelist-enabled = false;
        rpc-host-whitelist-enabled = false;
        peer-port = 51413;
      };
    };

    # Radarr sandboxed: necesita acceso explicito al storage
    systemd.services.radarr.serviceConfig.ReadWritePaths = [ cfg.mediaPath ];

    # Directorios con permisos correctos
    systemd.tmpfiles.rules = [
      "d ${cfg.mediaPath} 0775 root media -"
      "d ${cfg.mediaPath}/movies 0775 radarr media -"
      "d ${cfg.mediaPath}/downloads 0775 transmission media -"
      "d ${cfg.mediaPath}/downloads/.incomplete 0775 transmission media -"
    ];

    # Grupo compartido: todos los servicios leen/escriben
    users.groups.media = {};
    users.users.jellyfin.extraGroups = [ "media" ];
    users.users.radarr.extraGroups = [ "media" ];
    users.users.transmission.extraGroups = [ "media" ];

    # Puertos web UI accesibles desde LAN
    networking.firewall.allowedTCPPorts = [ 9091 7878 9696 ];
  };
}

Los bugs que encontramos

Porque nada funciona a la primera:

  1. Transmission 3 eliminado: NixOS ya no tiene transmission_3. Hay que poner package = pkgs.transmission_4 explicito.

  2. Radarr no ve /storage: Systemd sandboxea Radarr con ProtectHome y namespaces. Sin ReadWritePaths = [ "/storage/media" ] Radarr no puede leer ni escribir fuera de su directorio.

  3. Transmission no arranca: El servicio falla si los directorios de descarga no existen. systemd.tmpfiles.rules los crea automaticamente, pero en el primer rebuild los tmpfiles se ejecutan despues del servicio. Solucion: crear los directorios a mano la primera vez o reiniciar.

  4. Transmission rechaza conexiones remotas: rpc-host-whitelist-enabled esta a true por defecto. Desde otro PC de la LAN el hostname no coincide y devuelve 409. Hay que desactivarlo.

  5. openFirewall miente: services.transmission.openFirewall solo abre el peer port (51413), NO el puerto RPC (9091). Igual con Radarr y Prowlarr. Hay que abrir 9091, 7878 y 9696 manualmente en el firewall.

Configuracion inicial (una sola vez)

Despues del rebuild, los 4 servicios arrancan pero no se conocen entre si. Hay que presentarlos:

1. Jellyfin (:8096)

2. Prowlarr (:9696)

3. Radarr (:7878)

4. Buscar tu primera peli

El resultado

175 peliculas que teniamos desperdigadas en ~/Downloads/peliculicas/ ahora estan organizadas en Jellyfin con caratulas, sinopsis, puntuaciones y busqueda. Paprika y Coco descargandose automaticamente. El crio puede elegir peli desde la tablet.

Todo declarativo. Si vespino explota manana, dos lineas en el nuevo servidor y el stack vuelve a estar operativo. Solo hay que reconfigurar los indexadores y reconectar las piezas (5 minutos).

Y lo mejor: cero "video not supported".

Para el futuro

Pero eso ya sera otra tarde de sabado. Hoy toca ver Paprika.

Comparte este post:

Es tu post

Estas seguro? Esto no se puede deshacer.

Comentarios (1)

ambrosin — 28 Feb 2026 22:40
Y sí, toda la culpa es mía por decir que vieras Paprika. De nada 😏

Deja un comentario