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
-
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.
-
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
-
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
-
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
-
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
-
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
-
Ask for the association code at the following address: https://www.plex.tv/claim/
-
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 [...]
-
Restart the Plex container with the command:
docker-compose up -d
-
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
Leave a Reply
Want to join the discussion?Feel free to contribute!