Ubuntu 20.04 / Debian 10 – An Anonymous and Secured Seedbox – (Part 2) Remote access with Traefik
A reverse proxy is a server that sits in front of web servers and forwards client HTTP requests to the appropriate backend service. In our case, a reverse proxy directs client requests to the appropriate Docker container. We have a multitude of Docker containers and we cannot listen to them all on port 80 or 443, hence the use of a reverse proxy. Add to that a nice domain name to your seedbox by securing everything with the SSL / TLS protocol and a Let’s Encrypt certificate.
5 – Traefik
Traefik is a modern reverse-proxy and load-balancer designed to facilitate the deployment of microservices (Docker, Kubernetes, AWS, etc.). Traefik is extremely simple to configure and automatically manages your certificates issued by Let’s Encrypt. In addition, it is able to load your containers dynamically without service interruption and has a dashboard displaying all of your configured routes.
We will detail here the procedure with the Deluge AirVPN image but it remains of course compatible with PIA images and without VPN if it is followed conscientiously.
5.1 – Traefik user
If you have several docker-compose.yml or if you plan to create one later, it is better to isolate and dedicate a docker-compose.yml for Traefik. It is not recommended to launch it under your superuser, so it’s better to create a dedicated user.
-
Create a traefik user:
sudo adduser traefik
-
Add it to the docker group:
sudo adduser traefik docker
5.2 – Traefik network
In the first part of this howto, each Docker container shares the network of your machine to be accessible locally with the network_mode: "host"
property. With a reverse proxy, this configuration is no longer necessary and we will take the opportunity to add a little more security by isolating your containers in a network only accessible by Traefik.
-
Log in under the traefik user:
su traefik
-
Move to the home directory of this user:
cd
-
Create the network dedicated to Traefik and all of your containers:
docker network create traefik_network
5.3 – Network isolation between containers and the Docker host
Create the file /home/traefik/docker-compose.yml with the following content (do not change anything):
version: '3.7' services: traefik: image: "traefik:v2.2" container_name: "traefik" restart: unless-stopped networks: - traefik_network ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - /home/traefik/traefik.toml:/traefik.toml:ro - /home/traefik/acme.json:/acme.json networks: traefik_network: external: true
- /var/run/docker.sock:/var/run/docker.sock:ro : specifies the Unix socket of your docker. Leave this default.
- /home/traefik/traefik.toml:/traefik.toml:ro : specifies the path to the Traefik configuration file. We will create it in the next step.
- /home/traefik/acme.json:/acme.json : specifies the path of the file containing the information relating to your certificates.
- traefik_network : specifies the network created previously and dedicated to Traefik. We will add the different containers to this network later.
5.4 – Traefik configuration
Traefik can be configured in different ways, we will detail here, the configuration recommended by Traefik, namely by a static file in TOML format.
-
Traefik stores information related to the certificate in an acme.json file. First you must create the file and assign it a minimum of permissions:
touch /home/traefik/acme.json && chmod 600 /home/traefik/acme.json
-
Create the Traefik configuration file /home/media/traefik/traefik.toml by adding the following lines (you just need to edit the email property):
[providers.docker] endpoint = "unix:///var/run/docker.sock" watch = true exposedByDefault = false [entryPoints.web] address = ":80" [entryPoints.web.http.redirections.entryPoint] to = "websecure" scheme = "https" [entryPoints.websecure] address = ":443" [certificatesResolvers.leresolver.acme] email = "votre-adresse@email.com" storage = "acme.json" [certificatesResolvers.leresolver.acme.httpChallenge] entryPoint = "web"
- [providers.docker]: this option enables Docker support.
- endpoint = "unix:///var/run/docker.sock": specifies the Unix socket of your Docker at Traefik. Leave the default.
- watch = true: allows hot deployment of containers as soon as a change in configuration is detected.
- exposedByDefault = false: does not expose containers by default to the outside world. It is preferable to activate this option in the docker-compose.yml file because, if for some reason, you no longer wish to make a container accessible from the outside.
- [entryPoints.web] and [entryPoints.websecure]: these options define the entry points for your Traefik. web and websecure are purely indicative, you can name them differently but they must correspond to the labels that we will define later in the docker-compose.yml file. The adress properties specify the ports on which Traefik « listens » depending on the entry point.
- [entryPoints.web.http.redirections.entryPoint]: forces port 80 to port 443 forwarding so forces HTTP over HTTPS.
- [certificatesResolvers.[NOM_RESOLVEUR].acme]: we indicate that we wish to use the ACME protocol (therefore the Let’s Encrypt service) to obtain a certificate. The name of the resolver is purely indicative, it must simply correspond to the labels that we will define later in the docker-compose.yml file.
- storage = "acme.json": the storage property specifies to Traefik the file (which we created previously) where the information relating to certificates will be stored. The common error is to indicate the absolute path (/home/media/traefik/acme.json in our case), here the path to be filled in is the one inside the Traefik container, so you must leave this value by default.
- [certificatesResolvers.[NOM_RESOLVEUR].acme.httpChallenge]: this option simply specifies by which entry point (in our case port 80) Traefik can obtain a certificate.
-
Move to the home directory of the traefik user and start the container:
cd docker-compose up -d
5.5 – Labels and traefik network
-
Log in under the media user and move to the home directory of this user:
su media cd
-
Start by declaring your domain in the /home/media/.env file by adding the NETWORK and BASE_HOST properties by modifying the value by your domain. Be careful here to fill in the base of your domain (no sub-domain or even www):
[...] NETWORK=traefik_network BASE_HOST=mondomaine.com
-
Edit your /home/media/docker-compose.yml file and replace all
network_mode: "host"
properties through your new network.Please note, the Deluge image without VPN also has this directive. In addition, all port exposures are useless, you can delete all directives
ports:
with associated ports.Then, add the labels allowing to communicate with Traefik and finish by adding the network traefik_network at the end of the file:
version: '3.7' services: deluge: image: binhex/arch-delugevpn:latest container_name: deluge restart: unless-stopped networks: - ${NETWORK} cap_add: - NET_ADMIN environment: - PUID=${PUID} - PGID=${PGID} - VPN_ENABLED=yes - VPN_PROV=airvpn - ENABLE_PRIVOXY=yes - LAN_NETWORK=${LAN_NETWORK} - NAME_SERVERS=209.222.18.222,37.235.1.174,8.8.8.8,209.222.18.218,37.235.1.177,8.8.4.4 - UMASK=000 - DEBUG=false volumes: - /home/deluge/config:/config - /etc/localtime:/etc/localtime:ro - ${PATH_MEDIA}:/data labels: - "traefik.enable=true" - "traefik.docker.network=${NETWORK}" - "traefik.http.routers.deluge.entrypoints=web,websecure" - "traefik.http.routers.deluge.rule=Host(`deluge.${BASE_HOST}`)" - "traefik.http.services.deluge.loadbalancer.server.port=8112" - "traefik.http.routers.deluge.tls=true" - "traefik.http.routers.deluge.tls.certresolver=leresolver" jackett: image: linuxserver/jackett:latest container_name: jackett restart: unless-stopped networks: - ${NETWORK} environment: - PUID=${PUID} - PGID=${PGID} - TZ=Europe/Paris volumes: - /home/media/jackett/config:/config - /etc/localtime:/etc/localtime:ro labels: - "traefik.enable=true" - "traefik.docker.network=${NETWORK}" - "traefik.http.routers.jackett.entrypoints=web,websecure" - "traefik.http.routers.jackett.rule=Host(`jackett.${BASE_HOST}`)" - "traefik.http.services.jackett.loadbalancer.server.port=9117" - "traefik.http.routers.jackett.tls=true" - "traefik.http.routers.jackett.tls.certresolver=leresolver" sonarr: image: linuxserver/sonarr:latest container_name: sonarr restart: unless-stopped networks: - ${NETWORK} environment: - PUID=${PUID} - PGID=${PGID} - TZ=Europe/Paris volumes: - /home/media/sonarr/config:/config - ${PATH_MEDIA}:/data labels: - "traefik.enable=true" - "traefik.docker.network=${NETWORK}" - "traefik.http.routers.sonarr.entrypoints=web,websecure" - "traefik.http.routers.sonarr.rule=Host(`sonarr.${BASE_HOST}`)" - "traefik.http.services.sonarr.loadbalancer.server.port=8989" - "traefik.http.routers.sonarr.tls=true" - "traefik.http.routers.sonarr.tls.certresolver=leresolver" radarr: image: linuxserver/radarr:latest container_name: radarr restart: unless-stopped networks: - ${NETWORK} environment: - PUID=${PUID} - PGID=${PGID} - TZ=Europe/Paris volumes: - /home/media/radarr/config:/config - ${PATH_MEDIA}:/data labels: - "traefik.enable=true" - "traefik.docker.network=${NETWORK}" - "traefik.http.routers.radarr.entrypoints=web,websecure" - "traefik.http.routers.radarr.rule=Host(`radarr.${BASE_HOST}`)" - "traefik.http.services.radarr.loadbalancer.server.port=7878" - "traefik.http.routers.radarr.tls=true" - "traefik.http.routers.radarr.tls.certresolver=leresolver" lidarr: image: linuxserver/lidarr:latest container_name: lidarr restart: unless-stopped networks: - ${NETWORK} environment: - PUID=${PUID} - PGID=${PGID} - TZ=Europe/Paris volumes: - /home/media/lidarr/config:/config - ${PATH_MEDIA}:/data labels: - "traefik.enable=true" - "traefik.docker.network=${NETWORK}" - "traefik.http.routers.lidarr.entrypoints=web,websecure" - "traefik.http.routers.lidarr.rule=Host(`lidarr.${BASE_HOST}`)" - "traefik.http.services.lidarr.loadbalancer.server.port=8686" - "traefik.http.routers.lidarr.tls=true" - "traefik.http.routers.lidarr.tls.certresolver=leresolver" plex: image: linuxserver/plex:latest container_name: plex restart: unless-stopped networks: - ${NETWORK} environment: - VERSION=latest - PUID=${PUID} - PGID=${PGID} - TZ=Europe/Paris volumes: - /home/media/plex/config:/config - ${PATH_MEDIA}:/data labels: - "traefik.enable=true" - "traefik.docker.network=${NETWORK}" - "traefik.http.routers.plex.entrypoints=web,websecure" - "traefik.http.routers.plex.rule=Host(`plex.${BASE_HOST}`)" - "traefik.http.services.plex.loadbalancer.server.port=32400" - "traefik.http.routers.plex.tls=true" - "traefik.http.routers.plex.tls.certresolver=leresolver" networks: traefik_network: external: true
- traefik.enable=true: this label exposes the container to the outside world. It overloads the exposedByDefault property of your /home/media/traefik/traefik.toml file.
- traefik.docker.network=traefik_network : this label specifies to Traefik the network to use.
- traefik.http.routers.[NOM_DU_CONTAINER].entrypoints: each routing rule specific to a container must be specified by a name, here we simply use the name of the container. The entrypoints label specifies that incoming requests on the web (port 80) and websecure (port 443) entry points will be transmitted to the container.
- traefik.http.routers.[NOM_DU_CONTAINER].rule=Host(`[SERVICE].${BASE_HOST}`): here we specify a rule, any request arriving on http://SERVICE.mydomain.com will be transmitted to the associated Docker container.
- traefik.http.services.[NOM_DU_CONTAINER].loadbalancer.server.port=[PORT]: we specify the port of the container on which the requests must be transmitted.
- traefik.http.routers.[NOM_CONTAINER].tls: enable SSL/TLS support.
- traefik.http.routers.[NOM_CONTAINER].tls.certresolver: specifies the resolver and therefore the certificates to be used.
-
Move to the home directory of the media user and start all the containers with the command:
cd docker-compose up -d
5.6 – Services configuration
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.-
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 networks: - ${NETWORK} environment: - VERSION=latest - PUID=${PUID} - PGID=${PGID} - TZ=Europe/Paris - PLEX_CLAIM=claim-424242424242 - ADVERTISE_IP=plex.${BASE_HOST}:443 volumes: - /home/media/plex/config:/config - ${PATH_MEDIA}:/data labels: - "traefik.enable=true" - "traefik.docker.network=${NETWORK}" - "traefik.http.routers.plex.entrypoints=web,websecure" - "traefik.http.routers.plex.rule=Host(`plex.${BASE_HOST}`)" - "traefik.http.services.plex.loadbalancer.server.port=32400" - "traefik.http.routers.plex.tls=true" - "traefik.http.routers.plex.tls.certresolver=media-resolver" [...]
-
Restart the Plex container with the command:
docker-compose up -d
- Deluge : http://deluge.mydomain.com
- Jackett : http://jackett.mydomain.com
- Sonarr : http://sonarr.mydomain.com
- Radarr : http://radarr.mydomain.com
- Lidarr : http://lidarr.mydomain.com
- Plex : http://plex.mydomain.com
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)
Debian 10 BlusterDocker 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!