I really liked that the development of FreeNAS moved to TrueNAS and specially TrueNAS scale. All my servers are running Debian so having my NAS running the same OS was a great update. On top of that, TrueNAS scale comes with a new application management built on top of Kubernetes. I use Kubernetes a lot at work but I feel like using it at home for smaller scale projects is overkill, that’s why I have all my services running on Docker only. None of my services are critical and would require the orchestration of Kubernetes.
My plan was to use TrueNAS as any of my other server hosting docker containers. I use Traefik as my reverse proxy for 2 main reasons:
- The configuration can be done with labels on each container, which doesn’t require an extra configuration file. I can just backup my docker-compose files.
- Traefik can easily generate SSL certificate with Let’s encrypt. You don’t need an other container to take care of that.
Before going forward, you should have :
- a proper domain name
- a proper DNS server, ideally using a provider with an API that traefik can use. See here : https://doc.traefik.io/traefik/https/acme/#providers
- Your TrueNAS instance should be accessible by domain name. For example : https://truenas.domain.ovh
- Docker compose installed on the server ( https://docs.docker.com/compose/install/other/#on-linux )
The first issue with hosting any kind of reverse proxy on TrueNAS is that you cannot bind your container on standard HTTP/S ports 80 & 443. The reason is that the TrueNAS GUI (using nginx) is already using these ports.
The first thing to do is to change the TrueNAS GUI ports from the settings :
- System Settings -> General -> GUI -> Settings
- Change : Web Interface HTTP Port -> 81
- Change : Web Interface HTTPS Port -> 444
These changes will trigger the GUI to restart and you will have to add the port to the URL to access the GUI :
Now that there is nothing using ports 80 and 443, we can create our Traefik container. I am using the DNS challenge to generate my certificates which is really useful for services that are not accessible from the internet.
See below how my compose looks like, I will try to explain the important parts below :
version: "3.3"
services:
traefik:
image: traefik
container_name: traefik
hostname: traefik
restart: unless-stopped
labels:
traefik.enable: true
traefik.http.routers.traefik.rule: Host(`traefik.domain.ovh`)
traefik.http.routers.traefik.entrypoints: websecure
traefik.http.routers.traefik.tls.certresolver: domainresolver
traefik.http.routers.traefik.tls: true
traefik.http.routers.traefik.service: api@internal
command:
- --api.dashboard=true
- --providers.docker=true
- --providers.file.filename=/etc/traefik/dynamic.yaml
- --serversTransport.insecureSkipVerify=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.http.redirections.entryPoint.to=websecure
- --certificatesresolvers.domainresolver.acme.dnschallenge=true
- --certificatesresolvers.domainresolver.acme.dnschallenge.provider=ovh
- --[email protected]
- --certificatesresolvers.domainresolver.acme.storage=/letsencrypt/acme_domain.json
ports:
- 80:80
- 443:443
environment:
- OVH_ENDPOINT=ovh-eu
- OVH_APPLICATION_KEY=${OVH_APPLICATION_KEY}
- OVH_APPLICATION_SECRET=${OVH_APPLICATION_SECRET}
- OVH_CONSUMER_KEY=${OVH_CONSUMER_KEY}
- CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
volumes:
- /mnt/pool1/docker/volumes/traefik/letsencrypt:/letsencrypt
- /mnt/pool1/docker/volumes/traefik/config/dynamic.yaml:/etc/traefik/dynamic.yaml
- /var/run/docker.sock:/var/run/docker.sock:ro
Explanations:
- labels: they are used to create an https endpoint with ssl certificate for the traefik dashboard which is defined with –api.dashboard=true
- command:
- –providers.file.filename=/etc/traefik/dynamic.yaml This argument specifies the file that Traefik will use for dynamic processing. At the beginning of the post I mentionned that I like Traefik because it doesn’t require a config file and you can use container labels for configuration. Well, in this case we will need a config file to create the rules. It is required because we will create a rule for the TrueNAS GUI (more explanation below)
- –serversTransport.insecureSkipVerify=true This is required if your service already has its own self-signed certificate and you cannot get rid of it. This is useful in our case when TrueNAS GUI has a self-signed certificate.
- –entrypoints.web.address=:80 && –entrypoints.websecure.address=:443 These defined the ports we will use to handle requests. 80 for HTTP and 443 for HTTPS
- –entrypoints.web.http.redirections.entryPoint.to=websecure This will redirect all HTTP traffic to HTTPS automatically
- certificatesresolvers These are the configurations for generating certificates. In my case, I have the following domain: domain.ovh (ovh)
- environment: for my OVH resolver, I need to provide 4 ENV and for my Cloudflare resolver, I need to provide 1 ENV. You can check what values are required in the Traefik docs.
- volumes: You need 1 volumes for the certificates, 1 volume containing the dynamic file (see below) and one volume for the docker socket
The Dynamic file contains information on how the traffic should be handled. This file needs to be created before running Traefik according to the compose file (volumes)
In the following file, I made a rule to redirect traffic for truenas.domain.ovh to go to the TrueNAS GUI. You will need to update the value with your own IP address. I also added Plex as an example where you have a plex container running.
You first need to create a router, then a service then associate the router and the service. You define which resolver to use with the certresolver property.
http:
routers:
truenasgui:
rule: Host(`truenas.domain.ovh`)
service: truenasgui
entryPoints:
- websecure
tls:
certresolver: domainresolver
plex:
rule: Host(`plex.domain.ovh`)
service: plex
entryPoints:
- websecure
tls:
certresolver: domainresolver
services:
truenasgui:
loadBalancer:
servers:
- url: https://192.168.1.x:444
plex:
loadBalancer:
servers:
- url: http://plex:32400
Before testing, you need to make sure that the name record for truenas.domain.ovh is set with TrueNAS IP.
When Traefik is up and running, if you try going to https://truenas.domain.ovh you will be redirected to the TrueNAS GUI !.