-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support for ACME provisioned certificates, age-secured CF token…
… secret, Tailnet certificate generation, and Plex media server
- Loading branch information
Showing
8 changed files
with
160 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
_: { | ||
users.groups.media-server = { | ||
# Media management group, think Plex or Jellyfin | ||
gid = 1300; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
{ lib, pkgs, config, ... }: | ||
let | ||
domain = "media.int.carrio.me"; | ||
in | ||
{ | ||
# Securely mount Age secret for Cloudflare DNS verification config | ||
age.secrets.cloudflare-dns-verification = { | ||
file = ../../../secrets/services/acme/cloudflare.age; | ||
owner = "root"; | ||
group = "root"; | ||
mode = "400"; | ||
}; | ||
|
||
# Various media services are granted necessary access to volumes via 'media-server' group | ||
services.plex.group = "media-server"; | ||
|
||
# ACME NixOS Docs: https://wiki.nixos.org/wiki/ACME | ||
security.acme = { | ||
acceptTerms = true; | ||
defaults.email = "[email protected]"; | ||
certs = { | ||
"${domain}" = { | ||
inherit domain; | ||
group = "nginx"; | ||
dnsProvider = "cloudflare"; | ||
|
||
# https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#EnvironmentFile= | ||
environmentFile = config.age.secrets.cloudflare-dns-verification.path; | ||
}; | ||
}; | ||
}; | ||
|
||
systemd.services."provision-tailnet-certificate" = { | ||
wants = [ "tailscale.service" ]; | ||
path = with pkgs; [ tailscale dnsutils coreutils ]; | ||
script = '' | ||
ts_domain="$(${pkgs.dnsutils}/bin/dig @100.100.100.100 +noall +answer +short -x $(${pkgs.tailscale}/bin/tailscale ip -1) | ${pkgs.coreutils}/bin/sed -E 's/\.$//')" | ||
mkdir -p /var/lib/tailscale/certs/ | ||
${pkgs.tailscale}/bin/tailscale cert \ | ||
--cert-file=/var/lib/tailscale/certs/cert.pem \ | ||
--key-file=/var/lib/tailscale/certs/key.pem \ | ||
--min-validity=48h \ | ||
$ts_domain | ||
''; | ||
}; | ||
|
||
systemd.timers."provision-tailnet-certificate-cron" = { | ||
wantedBy = [ "timers.target" ]; | ||
timerConfig = { | ||
OnBootSec = "1m"; | ||
OnUnitActiveSec = "12h"; | ||
Unit = "provision-tailnet-certificate.service"; | ||
}; | ||
}; | ||
|
||
# Plex NixOS Docs: https://nixos.wiki/wiki/Plex | ||
services.nginx = { | ||
enable = true; | ||
# give a name to the virtual host. It also becomes the server name. | ||
virtualHosts."${domain}" = { | ||
# Since we want a secure connection, we force SSL | ||
forceSSL = true; | ||
|
||
# http2 can more performant for streaming: https://blog.cloudflare.com/introducing-http2/ | ||
http2 = true; | ||
|
||
# Provide the ssl cert and key for the vhost | ||
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem"; | ||
sslCertificateKey = "/var/lib/acme/${domain}/key.pem"; | ||
|
||
extraConfig = '' | ||
#Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause | ||
send_timeout 100m; | ||
# Why this is important: https://blog.cloudflare.com/ocsp-stapling-how-cloudflare-just-made-ssl-30/ | ||
ssl_stapling on; | ||
ssl_stapling_verify on; | ||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; | ||
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 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; | ||
# Forward real ip and host to Plex | ||
proxy_set_header X-Real-IP $remote_addr; | ||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | ||
proxy_set_header X-Forwarded-Proto $scheme; | ||
proxy_set_header Host $server_addr; | ||
proxy_set_header Referer $server_addr; | ||
proxy_set_header Origin $server_addr; | ||
# Plex has A LOT of javascript, xml and html. This helps a lot, but if it causes playback issues with devices turn it off. | ||
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; | ||
# 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; | ||
# 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; | ||
''; | ||
locations."/" = { | ||
proxyPass = "http://127.0.0.1:32400/"; | ||
}; | ||
}; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ in | |
] | ||
++ ifExists [ | ||
"docker" | ||
"media-server" | ||
"podman" | ||
"nordvpn" | ||
]; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.