feat: add Let's Encrypt SSL certificates and Tailscale instructions
This commit is contained in:
parent
02d3208c51
commit
3e1e94817a
@ -7,3 +7,8 @@ PIA_LOCATION=ca
|
||||
PIA_USER=
|
||||
PIA_PASS=
|
||||
PIA_LOCAL_NETWORK="192.168.0.0/16"
|
||||
HOSTNAME=
|
||||
LETS_ENCRYPT_EMAIL=
|
||||
CLOUDFLARE_EMAIL=
|
||||
CLOUDFLARE_DNS_API_TOKEN=
|
||||
CLOUDFLARE_ZONE_API_TOKEN=
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -14,3 +14,5 @@
|
||||
!/pia/.gitkeep
|
||||
/pia-shared
|
||||
!/pia-shared/.gitkeep
|
||||
/letsencrypt
|
||||
!/letsencrypt/.gitkeep
|
@ -69,7 +69,7 @@ place in the VPN container, the hostname for qBittorrent is the hostname of the
|
||||
|
||||
The indexers are configured through Prowlarr. They synchronize automatically to Radarr and Sonarr.
|
||||
|
||||
Radarr and Sonarr may then be added via Settongs > Apps. The Prowlarr server is `http://prowlarr:9696/prowlarr`, the Radarr server
|
||||
Radarr and Sonarr may then be added via Settings > Apps. The Prowlarr server is `http://prowlarr:9696/prowlarr`, the Radarr server
|
||||
is `http://radarr:7878/radarr` and Sonarr `http://sonarr:8989/sonarr`:
|
||||
|
||||
![](https://cdn.poupa.net/uploads/2022/03/sonarr.png)
|
||||
@ -100,3 +100,60 @@ Applications can be added in Items > Add. The URLs should be the static IP, ie:
|
||||
for example.
|
||||
|
||||
![](https://cdn.poupa.net/uploads/2022/03/homepage.png)
|
||||
|
||||
## Traefik and SSL Certificates
|
||||
|
||||
While you can use the private IP to access your NAS, how cool would it be for it to be accessible through a subdomain
|
||||
with a valid SSL certificate?
|
||||
|
||||
Traefik makes this trivial by using Let's Encrypt and one of its
|
||||
[supported ACME challenge providers](https://doc.traefik.io/traefik/https/acme/).
|
||||
|
||||
Let's assume we are using `nas.domain.com` as custom subdomain.
|
||||
|
||||
The idea is to create an A record pointing to the private IP of the NAS, `192.168.0.10` for example:
|
||||
```
|
||||
nas.domain.com. 1 IN A 192.168.0.10
|
||||
```
|
||||
|
||||
The record will be publicly exposed but not resolve given this is a private IP.
|
||||
|
||||
Given the NAS is not accessible from the internet, we need to do a dnsChallenge.
|
||||
Here we will be using CloudFlare, but the mechanism will be the same for all DNS providers
|
||||
baring environment variable changes, see the Traefik documentation above and [Lego's documentation](https://go-acme.github.io/lego/dns/).
|
||||
|
||||
Then, we need to fill the `.env` entries:
|
||||
|
||||
- `HOSTNAME`: the subdomain used, `nas.domain.com` for example
|
||||
- `LETS_ENCRYPT_EMAIL`: e-mail address used to send expiration notifications
|
||||
- `CLOUDFLARE_EMAIL`: Account email
|
||||
- `CLOUDFLARE_DNS_API_TOKEN`: API token with DNS:Edit permission
|
||||
- `CLOUDFLARE_ZONE_API_TOKEN`: API token with Zone:Read permission
|
||||
|
||||
If you want to test your configuration first, use the Let's Encrypt staging server by uncommenting this:
|
||||
```
|
||||
#- --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
|
||||
```
|
||||
|
||||
If it worked, you will see the staging certificate at https://nas.domain.com.
|
||||
You may remove the `./letsencrypt/acme.json` file and restart the services to issue the real certificate.
|
||||
|
||||
### Accessing from the outside
|
||||
|
||||
If we want to make it reachable from outside the network without opening ports or exposing it to the internet, I found
|
||||
[Tailscale](https://tailscale.com/) to be a great solution: create a network, run the client on both the NAS and the device
|
||||
you are connecting from, and they will see each other.
|
||||
|
||||
In this case, the A record should point to the IP Tailscale assigned to the NAS, eg `100.xxx.xxx.xxx`:
|
||||
```
|
||||
nas.domain.com. 1 IN A 100.xxx.xxx.xxx
|
||||
```
|
||||
|
||||
See [here](https://tailscale.com/kb/installation/) for installation instructions.
|
||||
|
||||
However, this means you will always need to be connected to Tailscale to access your NAS, even locally.
|
||||
This can be remedied by overriding the DNS entry for the NAS domain like `192.168.0.10 nas.domain.com`
|
||||
in your local DNS resolver such as Pi-Hole.
|
||||
|
||||
This way, when connected to the local network, the NAS is accessible directly from the private IP,
|
||||
and from the outside you need to connect to Tailscale first, then the NAS domain will be accessible.
|
@ -3,6 +3,7 @@
|
||||
After searching for the perfect NAS solution, I realized what I wanted could be achieved
|
||||
with some Docker containers on a vanilla Linux box. The result is an opinionated Docker Compose configuration capable of
|
||||
browsing indexers to retrieve media resources and downloading them through a Wireguard VPN with port forwarding.
|
||||
SSL certificates and remote access through Tailscale are supported.
|
||||
|
||||
## Applications
|
||||
|
||||
@ -54,6 +55,5 @@ for some indexers in Prowlarr
|
||||
- [Jackett](https://github.com/Jackett/Jackett): API Support for your favorite torrent trackers, as a Prowlarr replacement
|
||||
- [Plex](https://www.plex.tv/): Plex Media Server
|
||||
- [Pi-hole](https://pi-hole.net/): DNS that blocks ads
|
||||
- Use a domain name and Let's Encrypt certificate to get SSL
|
||||
- Expose services with CloudFlare Tunnel
|
||||
- Expose services with CloudFlare Tunnel if Tailscale is not enough
|
||||
- you tell me!
|
||||
|
@ -4,6 +4,11 @@ services:
|
||||
image: traefik:v2.9
|
||||
container_name: traefik
|
||||
restart: always
|
||||
environment:
|
||||
- CLOUDFLARE_EMAIL=${CLOUDFLARE_EMAIL}
|
||||
- CLOUDFLARE_DNS_API_TOKEN=${CLOUDFLARE_DNS_API_TOKEN}
|
||||
- CLOUDFLARE_ZONE_API_TOKEN=${CLOUDFLARE_ZONE_API_TOKEN}
|
||||
- LETS_ENCRYPT_EMAIL=${LETS_ENCRYPT_EMAIL}
|
||||
command:
|
||||
- --providers.docker=true
|
||||
- --providers.docker.exposedbydefault=false
|
||||
@ -12,10 +17,17 @@ services:
|
||||
- --entrypoints.web.http.redirections.entryPoint.to=web-secure
|
||||
- --entrypoints.web.http.redirections.entryPoint.scheme=https
|
||||
- --entrypoints.web.http.redirections.entrypoint.permanent=true
|
||||
- --certificatesresolvers.myresolver.acme.dnschallenge=true
|
||||
- --certificatesresolvers.myresolver.acme.dnschallenge.provider=cloudflare
|
||||
# Uncomment to test your configuration by using Let's Encrypt staging certificates
|
||||
#- --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
|
||||
- --certificatesresolvers.myresolver.acme.email=${LETS_ENCRYPT_EMAIL}
|
||||
- --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./letsencrypt:/letsencrypt
|
||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
sonarr:
|
||||
image: lscr.io/linuxserver/sonarr
|
||||
@ -29,9 +41,10 @@ services:
|
||||
restart: always
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.sonarr.rule=PathPrefix(`/sonarr`)
|
||||
- traefik.http.services.sonarr.loadbalancer.server.port=8989
|
||||
- traefik.http.routers.sonarr.rule=(Host(`${HOSTNAME}`) && PathPrefix(`/sonarr`) || PathPrefix(`/sonarr`))
|
||||
- traefik.http.routers.sonarr.tls=true
|
||||
- traefik.http.routers.sonarr.tls.certresolver=myresolver
|
||||
- traefik.http.services.sonarr.loadbalancer.server.port=8989
|
||||
radarr:
|
||||
image: lscr.io/linuxserver/radarr
|
||||
container_name: radarr
|
||||
@ -44,8 +57,9 @@ services:
|
||||
restart: always
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.radarr.rule=PathPrefix(`/radarr`)
|
||||
- traefik.http.routers.radarr.rule=(Host(`${HOSTNAME}`) && PathPrefix(`/radarr`) || PathPrefix(`/radarr`))
|
||||
- traefik.http.routers.radarr.tls=true
|
||||
- traefik.http.routers.radarr.tls.certresolver=myresolver
|
||||
- traefik.http.services.radarr.loadbalancer.server.port=7878
|
||||
prowlarr:
|
||||
image: lscr.io/linuxserver/prowlarr:develop
|
||||
@ -58,8 +72,9 @@ services:
|
||||
restart: always
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.prowlarr.rule=PathPrefix(`/prowlarr`)
|
||||
- traefik.http.routers.prowlarr.rule=(Host(`${HOSTNAME}`) && PathPrefix(`/prowlarr`) || PathPrefix(`/prowlarr`))
|
||||
- traefik.http.routers.prowlarr.tls=true
|
||||
- traefik.http.routers.prowlarr.tls.certresolver=myresolver
|
||||
- traefik.http.services.prowlarr.loadbalancer.server.port=9696
|
||||
qbittorrent:
|
||||
image: lscr.io/linuxserver/qbittorrent:4.5.0-libtorrentv1
|
||||
@ -78,8 +93,9 @@ services:
|
||||
- vpn
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.qbittorrent.rule=PathPrefix(`/qbittorrent`)
|
||||
- traefik.http.routers.qbittorrent.rule=(Host(`${HOSTNAME}`) && PathPrefix(`/qbittorrent`) || PathPrefix(`/qbittorrent`))
|
||||
- traefik.http.routers.qbittorrent.tls=true
|
||||
- traefik.http.routers.qbittorrent.tls.certresolver=myresolver
|
||||
- traefik.http.services.qbittorrent.loadbalancer.server.port=8080
|
||||
- traefik.http.routers.qbittorrent.middlewares=qbittorrent-strip-slash,qbittorrent-stripprefix
|
||||
# https://github.com/qbittorrent/qBittorrent/issues/5693#issuecomment-552146296
|
||||
@ -130,9 +146,10 @@ services:
|
||||
restart: always
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.heimdall.rule=PathPrefix(`/`)
|
||||
- traefik.http.services.heimdall.loadbalancer.server.port=80
|
||||
- traefik.http.routers.heimdall.rule=(Host(`${HOSTNAME}`) && PathPrefix(`/`) || PathPrefix(`/`))
|
||||
- traefik.http.routers.heimdall.tls=true
|
||||
- traefik.http.routers.heimdall.tls.certresolver=myresolver
|
||||
- traefik.http.services.heimdall.loadbalancer.server.port=80
|
||||
watchtower:
|
||||
image: containrrr/watchtower
|
||||
container_name: watchtower
|
||||
|
0
letsencrypt/.gitkeep
Normal file
0
letsencrypt/.gitkeep
Normal file
Loading…
Reference in New Issue
Block a user