Seedbox

Ubuntu 20.04 / Debian 10 – An Anonymous and Secured Seedbox – (Part 2) Remote access with Nginx

If you want to access your services via a URL like http://mydomain.com/deluge, http://mydomain.com/jackett, etc., you need a reverse proxy. The reverse proxy serves as a gateway between the outside (Internet) and your server’s local network.

5 – Nginx

We will use Nginx HTTP server because of its lack of performance issues. Nginx is known for its high performance, stability, feature set, simple configuration, and low resource consumption.

5.1 – Installation

  • Go back under your superuser:

    exit
  • Install the nginx package:

    sudo apt-get update && sudo apt-get -y install nginx
  • Edit the following properties in the Nginx configuration file /etc/nginx/nginx.conf:

    user www-data;
    worker_processes 8;
    pid /run/nginx.pid;
    include /etc/nginx/modules-enabled/*.conf;
    
    events {
        worker_connections 768;
        # multi_accept on;
    }
    
    http {
    
        ##
        # Basic Settings
        ##
    
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        server_tokens off;
    
        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;
    
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
    ...
    • worker_processes: to take full advantage of the power of your server, it is recommended to put as many worker_processes as cores available on your server. To find out the number of cores on your server, simply run the command:

      grep processor /proc/cpuinfo | wc -l
      8
    • server_tokens: For security reasons, it is recommended to deactivate sending information such as your Nginx version number. To do this, uncomment this directive in the http block.
  • Reload the Nginx configuration:

    sudo systemctl reload nginx.service

5.2 – Vhosts


Don’t forget to change the dns rules in the administrator interface of the provider of your domain name to point to the ip of your server. If your server is hosted at your home, you would also have to create a redirection of port 80 and 443 to your server in the configuration interface of your router.


  • Create the /etc/nginx/sites-available/media file and change the highlighted line to your domain name:
    upstream plex_backend {
        server                   localhost:32400;
        keepalive                32;
    }
    
    map $http_upgrade $connection_upgrade {
        default                  upgrade;
        ''                       close;
    }
    
    server {
        listen                   80;
        listen                   [::]:80;
        server_name              mydomain.com;
    
        location ^~ /deluge {
            proxy_pass           http://127.0.0.1:8112/;
            proxy_set_header     X-Deluge-Base "/deluge/";
            add_header           X-Frame-Options SAMEORIGIN;
            include              proxy_params;
        }
    
        location ^~ /jackett {
            proxy_pass           http://127.0.0.1:9117;
            include              proxy_params;
        }
    
        location ^~ /sonarr {
            proxy_pass           http://127.0.0.1:8989/sonarr;
            include              proxy_params;
        }
    
        location ^~ /radarr {
            proxy_pass           http://127.0.0.1:7878/radarr;
            include              proxy_params;
        }
        
        location ^~ /lidarr {
            proxy_pass           http://127.0.0.1:8686/lidarr;
            include              proxy_params;
        }
    
        location /web {
            proxy_pass           http://plex_backend;
    
            #Plex has A LOT of javascript, xml and html. This helps a lot, but if it causes playback issues with devices turn it off. (Haven't encountered any yet)
            gzip                 on;
            gzip_vary            on;
            gzip_min_length      1000;
            gzip_proxied         any;
            gzip_types           text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml;
            gzip_disable         "MSIE [1-6].";
    
            #Nginx default client_max_body_size is 1MB, which breaks Camera Upload feature from the phones.
            #Increasing the limit fixes the issue. Anyhow, if 4K videos are expected to be uploaded, the size might need to be increased even more
            client_max_body_size 100M;
    
            #Forward real ip and host to Plex
            include              proxy_params;
    
            #Plex headers
            proxy_set_header     X-Plex-Client-Identifier $http_x_plex_client_identifier;
            proxy_set_header     X-Plex-Device $http_x_plex_device;
            proxy_set_header     X-Plex-Device-Name $http_x_plex_device_name;
            proxy_set_header     X-Plex-Platform $http_x_plex_platform;
            proxy_set_header     X-Plex-Platform-Version $http_x_plex_platform_version;
            proxy_set_header     X-Plex-Product $http_x_plex_product;
            proxy_set_header     X-Plex-Token $http_x_plex_token;
            proxy_set_header     X-Plex-Version $http_x_plex_version;
            proxy_set_header     X-Plex-Nocache $http_x_plex_nocache;
            proxy_set_header     X-Plex-Provides $http_x_plex_provides;
            proxy_set_header     X-Plex-Device-Vendor $http_x_plex_device_vendor;
            proxy_set_header     X-Plex-Model $http_x_plex_model;
    
            proxy_set_header     Host $server_addr;
            proxy_set_header     Referer $server_addr;
            proxy_set_header     Origin $server_addr;
    
            #Plex Websockets
            proxy_http_version   1.1;
            proxy_set_header     Upgrade $http_upgrade;
            proxy_set_header     Connection "upgrade";
    
            #Buffering off send to the client as soon as the data is received from Plex.
            proxy_redirect       off;
            proxy_buffering      off;
        }
    
        location /plex {
            proxy_pass           http://localhost:32400/web;
        }
    }
  • Activate the virtual host:

    sudo ln -s /etc/nginx/sites-available/media /etc/nginx/sites-enabled/media
  • Reload the Nginx configuration:

    sudo systemctl reload nginx.service

5.3 – Configuration

To access Deluge, Jackett, Sonarr, Radarr, and Lidarr services via a domain name, it is necessary to specify the access URL in their respective configuration files.

Deluge

  • Log in with the media user and go to the personal directory of this user:

    su media
    cd
  • Stop the deluge deluge container:

    docker-compose stop deluge
  • Change the value of the base property in the Deluge configuration file /home/media/deluge/config/web.conf:

    {
        "file": 2,
        "format": 1
    }{
        "base": "/deluge",
        "cert": "ssl/daemon.cert",
        "default_daemon": "",
        "enabled_plugins": [],
        "first_login": false,
        "https": false,
        "interface": "0.0.0.0",
        "language": "",
        "pkey": "ssl/daemon.pkey",
        "port": 8112,
    
        [...]
    
    }
  • Start the deluge container:

    docker-compose start deluge
  • Deluge is now accessible at: http://mydomain.com/deluge

Jackett

  • Change the value of the BasePathOverride property in /home/media/jackett/config/Jackett/ServerConfig.json:

    {
      "Port": 9117,
      "AllowExternal": true,
      "APIKey": "***secret***",
      "AdminPassword": "***secret***",
      "InstanceId": "5pcp7hnvu69gmiq4gc7xgv47358d1gi7fkcvl088koieankn07adpt8ciob2umvj",
      "BlackholeDir": null,
      "UpdateDisabled": false,
      "UpdatePrerelease": false,
      "BasePathOverride": "/jackett",
      "OmdbApiKey": null,
      "ProxyUrl": null,
      "ProxyType": 0,
      "ProxyPort": null,
      "ProxyUsername": null,
      "ProxyPassword": null,
      "ProxyIsAnonymous": true
    }
  • Restart the jackett container:

    docker-compose restart jackett
  • Jackett is now accessible at: http://mydomain.com/jackett

Radarr

  • Change the value of the UrlBase property in /home/media/radarr/config/config.xml:

    <Config>
      <LogLevel>Info</LogLevel>
      <Port>7878</Port>
      <UrlBase>/radarr</UrlBase>
      <BindAddress>*</BindAddress>
      <SslPort>9898</SslPort>
      <EnableSsl>False</EnableSsl>
      <ApiKey>4242424242424242424242</ApiKey>
      <AuthenticationMethod>None</AuthenticationMethod>
      <Branch>develop</Branch>
    </Config>
  • Restart the radarr container:

    docker-compose restart radarr
  • Radarr is now accessible at: http://mydomain.com/radarr

Sonarr

  • Change the value of the UrlBase property in /home/media/sonarr/config/config.xml:

    <Config>
      <LogLevel>Info</LogLevel>
      <Port>8989</Port>
      <UrlBase>/sonarr</UrlBase>
      <BindAddress>*</BindAddress>
      <SslPort>9898</SslPort>
      <EnableSsl>False</EnableSsl>
      <ApiKey>4242424242424242424242</ApiKey>
      <AuthenticationMethod>None</AuthenticationMethod>
      <Branch>master</Branch>
      <LaunchBrowser>True</LaunchBrowser>
      <SslCertHash></SslCertHash>
      <UpdateMechanism>BuiltIn</UpdateMechanism>
    </Config>
  • Restart the sonarr container:

    docker-compose restart sonarr
  • Sonarr is now accessible at: http://mydomain.com/sonarr

Lidarr

  • Change the value of the UrlBase property in /home/media/lidarr/config/config.xml:

    <Config>
      <LogLevel>Info</LogLevel>
      <EnableSsl>False</EnableSsl>
      <Port>8686</Port>
      <SslPort>6868</SslPort>
      <UrlBase>/lidarr</UrlBase>
      <BindAddress>*</BindAddress>
      <ApiKey>4242424242424242424242</ApiKey>
      <AuthenticationMethod>None</AuthenticationMethod>
      <Branch>master</Branch>
    </Config>
  • Restart the lidarr container:

    docker-compose restart lidarr
  • Lidarr est désormais accessible via: http://mydomain.com/lidarr

Plex

For remote access, it is necessary to associate the Plex web interface with your server. For this, you must specify the URL and an association code whose validity is 4 minutes.
  1. Ask for the association code at the following address: https://www.plex.tv/claim/

  2. Edit your /home/media/docker-compose.yml file and add the following lines, specifying the code obtained previously:

    version: '3.7'
    services:
      [...]
    
      plex:
        image: linuxserver/plex:latest
        container_name: plex
        restart: unless-stopped
        network_mode: "host"
        ports:
          - 32400:32400
        environment:
          - VERSION=latest
          - PUID=${PUID}
          - PGID=${PGID}
          - TZ=Europe/Paris
          - PLEX_CLAIM=claim-424242424242
        volumes:
          - /home/media/plex/config:/config
          - ${PATH_MEDIA}:/data
    [...]
    
  3. Restart the Plex container with the command:

    docker-compose up -d
  4. Plex is now accessible at: http://mydomain.com/plex


5.4 – Secure your seedbox with SSL/TLS

Let’s Encrypt is a free, automated, and open certification platform. This platform provides free X.509 certificates for the SSL/TLS cryptographic protocol through an automated process designed to bypass the current complex process involving manual creation, validation, signing, installation and renewal of certificates for securing websites. By May 2018, Let’s Encrypt had issued more than 70 million certificates.

Enable superuser in your terminal and install software-properties-common et certbot packages:

sudo apt-get install -y software-properties-common
sudo apt-get install -y certbot

5.5 – Creation of certificates

Let’s Encrypt allows you to automatically generate certificates in several ways. The standalone method allows you to simply generate a certificate. However, it requests to stop the Nginx server each time the certificate is renewed. There are also fully automated apache et nginx plugins. These plugins automatically update the configuration of virtual hosts but the nginx plugin is still experimental. In this article, we recommend using the webroot plugin which allows you to generate and renew your certificate without interrupting the Nginx server.

The webroot plugin creates a temporary .well-known/acme-challenge file in a specific folder accessible to Nginx. This will allow Let’s Encrypt servers to access this temporary file and thus validate your certificate.

  • Create the directory for the temporary file of Let’s Encrypt:

    sudo mkdir -p /var/www/letsencrypt
  • Create the /etc/nginx/snippets/letsencrypt file with the following lines to redirect Let’s Encrypt to the previously created local folder:

    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        root         /var/www/letsencrypt;
    }
    
  • Import the file previously created in your virtual host:

    upstream plex_backend {
        server                   localhost:32400;
        keepalive                32;
    }
    
    map $http_upgrade $connection_upgrade {
        default                  upgrade;
        ''                       close;
    }
    
    server {
        listen                   80;
        listen                   [::]:80;
        server_name              mydomain.com;
    
        location ^~ /deluge {
            proxy_pass           http://127.0.0.1:8112/;
            proxy_set_header     X-Deluge-Base "/deluge/";
            add_header           X-Frame-Options SAMEORIGIN;
            include              proxy_params;
        }
    
        location ^~ /jackett {
            proxy_pass           http://127.0.0.1:9117;
            include              proxy_params;
        }
    
        location ^~ /sonarr {
            proxy_pass           http://127.0.0.1:8989/sonarr;
            include              proxy_params;
        }
    
        location ^~ /radarr {
            proxy_pass           http://127.0.0.1:7878/radarr;
            include              proxy_params;
        }
        
        location ^~ /lidarr {
            proxy_pass           http://127.0.0.1:8686/lidarr;
            include              proxy_params;
        }
    
        location /web {
            proxy_pass           http://plex_backend;
    
            #Plex has A LOT of javascript, xml and html. This helps a lot, but if it causes playback issues with devices turn it off. (Haven't encountered any yet)
            gzip                 on;
            gzip_vary            on;
            gzip_min_length      1000;
            gzip_proxied         any;
            gzip_types           text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml;
            gzip_disable         "MSIE [1-6].";
    
            #Nginx default client_max_body_size is 1MB, which breaks Camera Upload feature from the phones.
            #Increasing the limit fixes the issue. Anyhow, if 4K videos are expected to be uploaded, the size might need to be increased even more
            client_max_body_size 100M;
    
            #Forward real ip and host to Plex
            include              proxy_params;
    
            #Plex headers
            proxy_set_header     X-Plex-Client-Identifier $http_x_plex_client_identifier;
            proxy_set_header     X-Plex-Device $http_x_plex_device;
            proxy_set_header     X-Plex-Device-Name $http_x_plex_device_name;
            proxy_set_header     X-Plex-Platform $http_x_plex_platform;
            proxy_set_header     X-Plex-Platform-Version $http_x_plex_platform_version;
            proxy_set_header     X-Plex-Product $http_x_plex_product;
            proxy_set_header     X-Plex-Token $http_x_plex_token;
            proxy_set_header     X-Plex-Version $http_x_plex_version;
            proxy_set_header     X-Plex-Nocache $http_x_plex_nocache;
            proxy_set_header     X-Plex-Provides $http_x_plex_provides;
            proxy_set_header     X-Plex-Device-Vendor $http_x_plex_device_vendor;
            proxy_set_header     X-Plex-Model $http_x_plex_model;
    
            proxy_set_header     Host $server_addr;
            proxy_set_header     Referer $server_addr;
            proxy_set_header     Origin $server_addr;
    
            #Plex Websockets
            proxy_http_version   1.1;
            proxy_set_header     Upgrade $http_upgrade;
            proxy_set_header     Connection "upgrade";
    
            #Buffering off send to the client as soon as the data is received from Plex.
            proxy_redirect       off;
            proxy_buffering      off;
        }
    
        location /plex {
            proxy_pass           http://plex_backend;
        }
    
        include                  /etc/nginx/snippets/letsencrypt;
    }
  • Reload your Nginx configuration:

    sudo systemctl reload nginx.service
  • Generate your certificate with the command below. Replace email@mydomain.com and mydomain.com by your personal information:

    sudo certbot certonly --webroot -w /var/www/letsencrypt --agree-tos --no-eff-email --email email@mydomain.com -d mydomain.com --rsa-key-size 4096

    You will get 4 files in the /etc/letsencrypt/live/mydomain.com directory:

    • cert.pem: the certificate of your domain mydomain.com
    • chain.pem: Let’s Encrypt certificate
    • fullchain.pem: cert.pem and chain.pem certificates combined
    • privkey.pem: the private key of the certificate.
  • SSL/TLS uses an asymmetric encryption system (like RSA or Diffie-Hellman) to secure your data exchanges. By default, Nginx uses a 1048-bit key. By increasing the key length to 4096 bits, you will increase the security of your SSL/TLS protocol. Generate a new 4096-bit Diffie-Hellman (DH) key and give it minimum permissions:

    sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
    sudo chmod 600 /etc/ssl/certs/dhparam.pem

5.6 – Adding certificates to Vhost and activating SSL/TLS

  • Edit your virtual host by adding the highlighted lines. Make sure to modify the server_name, ssl_certificate, ssl_certificate_key and ssl_trusted_certificate according to your configuration:

    upstream plex_backend {
        server                    localhost:32400;
        keepalive                 32;
    }
    
    map $http_upgrade $connection_upgrade {
        default                   upgrade;
        ''                        close;
    }
    
    server {
        listen                    80;
        listen                    [::]:80;
        server_name               mydomain.com;
        return                    301 https://$server_name$request_uri;
    }
    
    server {
        listen                    443 ssl http2;
        listen                    [::]:443 ssl http2;
        server_name               mydomain.com;
    
        ssl_certificate           /etc/letsencrypt/live/mydomain.com/fullchain.pem;
        ssl_certificate_key       /etc/letsencrypt/live/mydomain.com/privkey.pem;
        ssl_trusted_certificate   /etc/letsencrypt/live/mydomain.com/chain.pem;
    
        ssl_dhparam               /etc/ssl/certs/dhparam.pem;
    
        ssl_protocols             TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        #Intentionally not hardened for security for player support and encryption video streams has a lot of overhead with something like AES-256-GCM-SHA384.
        ssl_ciphers               TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
        ssl_ecdh_curve            secp384r1;
    
        ssl_stapling              on;
        ssl_stapling_verify       on;
    
        location ^~ /deluge {
            proxy_pass            http://127.0.0.1:8112/;
            proxy_set_header      X-Deluge-Base "/deluge/";
            add_header            X-Frame-Options SAMEORIGIN;
            include               proxy_params;
        }
    
        location ^~ /jackett {
            proxy_pass            http://127.0.0.1:9117;
            include               proxy_params;
        }
    
        location ^~ /sonarr {
            proxy_pass            http://127.0.0.1:8989/sonarr;
            include               proxy_params;
        }
    
        location ^~ /radarr {
            proxy_pass            http://127.0.0.1:7878/radarr;
            include               proxy_params;
        }
        
        location ^~ /lidarr {
            proxy_pass            http://127.0.0.1:8686/lidarr;
            include               proxy_params;
        }
    
        location /web {
            proxy_pass            http://plex_backend;
    
            #Plex has A LOT of javascript, xml and html. This helps a lot, but if it causes playback issues with devices turn it off. (Haven't encountered any yet)
            gzip                  on;
            gzip_vary             on;
            gzip_min_length       1000;
            gzip_proxied          any;
            gzip_types            text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml;
            gzip_disable          "MSIE [1-6].";
    
            #Nginx default client_max_body_size is 1MB, which breaks Camera Upload feature from the phones.
            #Increasing the limit fixes the issue. Anyhow, if 4K videos are expected to be uploaded, the size might need to be increased even more
            client_max_body_size  100M;
    
            #Forward real ip and host to Plex
            include               proxy_params;
    
            #Plex headers
            proxy_set_header      X-Plex-Client-Identifier $http_x_plex_client_identifier;
            proxy_set_header      X-Plex-Device $http_x_plex_device;
            proxy_set_header      X-Plex-Device-Name $http_x_plex_device_name;
            proxy_set_header      X-Plex-Platform $http_x_plex_platform;
            proxy_set_header      X-Plex-Platform-Version $http_x_plex_platform_version;
            proxy_set_header      X-Plex-Product $http_x_plex_product;
            proxy_set_header      X-Plex-Token $http_x_plex_token;
            proxy_set_header      X-Plex-Version $http_x_plex_version;
            proxy_set_header      X-Plex-Nocache $http_x_plex_nocache;
            proxy_set_header      X-Plex-Provides $http_x_plex_provides;
            proxy_set_header      X-Plex-Device-Vendor $http_x_plex_device_vendor;
            proxy_set_header      X-Plex-Model $http_x_plex_model;
    
            proxy_set_header      Host $server_addr;
            proxy_set_header      Referer $server_addr;
            proxy_set_header      Origin $server_addr;
    
            #Plex Websockets
            proxy_http_version    1.1;
            proxy_set_header      Upgrade $http_upgrade;
            proxy_set_header      Connection "upgrade";
    
            #Buffering off send to the client as soon as the data is received from Plex.
            proxy_redirect        off;
            proxy_buffering       off;
        }
    
        location /plex {
            proxy_pass            http://plex_backend;
        }
    
        include                   /etc/nginx/snippets/letsencrypt;
    }
  • Reload your Nginx configuration:

    sudo systemctl reload nginx.service

You can check the strength of your SSL/TLS protocol by checking your Plex, for example, on SSL Labs. With such a configuration, you should get an A.

5.7 – Automatic certificate renewal

The certificates issued by Let’s Encrypt are valid for 90 days. A scheduled task to renew all the certificates present on your server is provided with the certbot tool. The scheduled task is performed twice a day, and the certificates are renewed if and only if your certificates expire in less than 30 days.

  • Test if the automatic renewal is functional with the following command:

    sudo certbot renew --dry-run

6 – Configuration

We will now configure the applications so that they can communicate with each other and that each of them has a minimum of security.

Next (configuration and issues)


Ubuntu Server 20.04Docker 19.03.8
Docker Compose 1.25.5
Nginx 1.17.10
Deluge 2.0.4
Jackett 0.16.105.0
Sonarr 2.0.0.5344
Radarr 0.2.0.1480
Lidarr 0.7.1.1381



Evaluez ce tutoriel !
0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *