Docker: Jellyfin y Nextcloud mediante proxy inverso

Introducción

Vamos a ver como poder aprovechar que tenemos funcionando el contenedor de Letsencrypt para realizar un proxy inverso y poder acceder desde diferentes nombres de subdominios duckdns (nextcloud.duckdns.org, jellyfin.duckdns.org, etc) a nuestro servidor, sin necesidad de tener que estar abriendo puertos para cada servicio, bastara con tener abierto solo el puerto 443, y el propio contenedor de Letsencrypt se encargara redirigir cada petición a su correspondiente servicio.

Pongo un pequeño gráfico para que se entienda mejor:

Cuando deseemos acceder a nuestro servidor Nextcloud, lo haremos a mediante del subdominio nextcloud.duckdns.org , evidentemente lo haremos a través del protocolo https (puerto 443) utilizando el certificado de Letsencrypt, ya vimos como crearlos en este articulo.

El router de nuestra casa debe de tener el puerto 443 abierto para poder redirigir las peticiones al contenedor de Letsencrypt

Yo redirigo las peticiones que llegan al router por el puerto 443 al puerto 1443, que es donde esta escuchando el contenedor Letsencrypt, que como veremos a continuación, hace de proxy inverso y se encarga de reenviar al puerto adecuado de cada contenedor cada petición, 443 para el servidor de Nextcloud y si la llamada llega desde el subdominio jellyfin.duckdns.org lo envía al puerto 8096 del contenedor de jellyfin.

Bueno después de todo esta teoría, vamos a ver el proceso, si ya estás corriendo el contenedor de Letsencrypt para generar/renovar tus certificados, ya deberías de tener abierto el puerto 443 en tu router, y si seguiste el articulo que escribí, también deberías de tener redirigido todas las peticiones al puerto 443 del router al puerto 1443, o el que hayas elegido.

Lo siguiente a realizar es acceder a la carpeta de configuración del docker de Letsencript

Y abrir la carpeta /nginx/proxy-confs, donde veremos ficheros de configuración ya predefinidos y listos para ser usados.

Configuración para Nextcloud

Por ejemplo para configurar el proxy inverso para Nextcloud, copiamos el fichero nextcloud.subdomain.conf.example y lo renombramos a nextcloud.subdomain.conf

Abrimos el fichero nextcloud.subdomain.conf para configurarlo

Cambia server_name nextcloud por el nombre de tu subdominio duckdns, por ejemplo, server_name nextcloud.duckdns.org;

Si tu servidor Nextcloud escucha por el puerto 443 no toques nada, si escucha por otro puerto cámbialo en la configuración.

Por ultimo, si no quieres que los robots de búsqueda indexen tu sitio coloca las siguientes lineas en el fichero

add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive";
add_header X-Robots-Tag "none";
# make sure that your dns has a cname set for nextcloud
# assuming this container is called "letsencrypt", edit your nextcloud container's config
# located at /config/www/nextcloud/config/config.php and add the following lines before the ");":
#  'trusted_proxies' => ['letsencrypt'],
#  'overwrite.cli.url' => 'https://nextcloud.your-domain.com/',
#  'overwritehost' => 'nextcloud.your-domain.com',
#  'overwriteprotocol' => 'https',
#
# Also don't forget to add your domain name to the trusted domains array. It should look somewhat like this:
#  array (
#    0 => '192.168.0.1:444', # This line may look different on your setup, don't modify it.
#    1 => 'nextcloud.your-domain.com',
#  ),

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name nextcloud.duckdns.org;

    include /config/nginx/ssl.conf;

    client_max_body_size 0;

    location / {
        include /config/nginx/proxy.conf;
        resolver 127.0.0.11 valid=30s;
        set $upstream_nextcloud nextcloud;
        proxy_max_temp_file_size 2048m;
        proxy_pass https://$upstream_nextcloud:443;
    }
}

Guarda los cambios y reinicia el contenedor Letsencrypt

Todavía nos queda una última cosa, modificar el fichero de configuración de Nextcloud, config.php.

Añade una nueva entrada en array con el nombre del subdominio

También añade las siguientes entradas al fichero

'trusted_proxies' => ['letsencrypt'],
'overwrite.cli.url' => 'https://nextcloud.your-domain.com/',
'overwritehost' => 'nextcloud.your-domain.com',
'overwriteprotocol' => 'https',

Cambia los valores por los de tu servidor

<?php
$CONFIG = array (
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'datadirectory' => '/data',
  'instanceid' => 'ockp77exp3qk',
  'passwordsalt' => 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
  'secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  'trusted_domains' =>
  array (
    0 => '192.168.1.43',
    1 => 'nextcloud.duckdns.org',
  ),
  'dbtype' => 'mysql',
  'version' => '16.0.3.0',
  'trusted_proxies' =>
  array (
    0 => 'letsencrypt',
  ),
  'overwriteprotocol' => 'https',
  'dbname' => 'nextcloud',
  'dbhost' => '192.168.1.43',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => 'xxxxx',
  'dbpassword' => 'xxxxxxxxxxxxxxx',
  'installed' => true,
  'maintenance' => false,
  'overwrite.cli.url' => 'https://nextcloud.duckddns.org',
  'overwritehost' => 'cloud-gomoca.duckdns.org',
  'theme' => '',
  'loglevel' => 2,
  'app_install_overwrite' =>
  array (
    0 => 'calendar',
  ),
);

Reinicia el contenedor, si todo ha ido bien deberías de poder acceder a tu servidor desde tu subdominio con su correspondiente certificado

Configuración para Jellyfin

El proceso es muy parecido al que hemos visto para Nextcloud, empezamos modificando el docker para poder acceder a los certificados que se encuentran en el docker de Letsencrypt en la carpeta /etc/letsencrypt/etc/live

Guardamos los cambios y reiniciamos el contenedor

Ahora debemos de configurar el proxy inverso de Letsencript, al igual que para Nextcloud, disponemos de un fichero de ejemplo para jellyfin, lo renombramos a jellyfin.subdomain.conf

Procedemos a editarlo, si has configurado el docker en modo host, como es mi caso, debes de cambiar proxy_pass http://$upstream_jellyfin:8096; por proxy_pass http://HOSTIP:8096; donde HOSTIP bes la dirección IP del servidor de jellyfin.

# make sure that your dns has a cname set for jellyfin, if jellyfin is running in bridge mode, the below config should work as is, although,
# the container name is expected to be "jellyfin", if not, replace the lines "set $upstream_jellyfin jellyfin;" with "set $upstream_jellyfin <containername>;"
# for host mode, replace the lines "proxy_pass http://$upstream_jellyfin:8096;" with "proxy_pass http://HOSTIP:8096;" HOSTIP being the IP address of jellyfin
# in jellyfin settings, under "Advanced" change the public https port to 443, leave the local ports as is, set the "external domain" to your url,
# and set the "Secure connection mode" to "Handled by reverse proxy"

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name jellyfin.duckdns.org;

    include /config/nginx/ssl.conf;

    client_max_body_size 0;

    location / {
        include /config/nginx/proxy.conf;
        resolver 127.0.0.11 valid=30s;
        set $upstream_jellyfin jellyfin;
        proxy_pass http://192.168.1.43:8096;

        proxy_set_header Range $http_range;
        proxy_set_header If-Range $http_if_range;
    }

    location ~ (/jellyfin)?/embywebsocket {
        include /config/nginx/proxy.conf;
        resolver 127.0.0.11 valid=30s;
        set $upstream_jellyfin jellyfin;
        proxy_pass http://192.168.1.43:8096;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $http_connection;
   }
}

Debemos configurar jellyfin, desde el panel de control y debemos de cambiar el número de puerto público de https a 443, el nombre de nuestro subdominio y la ubicación del certificado

También debemos cambiar el modo de conexión segura a Gestionado por proxy inverso

Grabamos los cambios y reiniciamos el contenedor jellyfin.

Ahora deberías poder de acceder a jellyfin desde su nombre de dominio

Espero que te haya gustado, pasa un buen día… 🐧