nginx: uses same ACME host to reduce the number of certs and avoid rate

limits
This commit is contained in:
Tigor Hutasuhut 2024-11-24 21:31:04 +07:00
parent 437fd67d9b
commit d85d2eeaf2
28 changed files with 154 additions and 66 deletions

View file

@ -138,7 +138,7 @@
};
services.nginx.virtualHosts."public.tigor.web.id" = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
root = "/nas/public";
@ -149,6 +149,8 @@
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ "public.tigor.web.id" ];
systemd.tmpfiles.settings = {
"100-nas-public-dir" = {
"/nas/public" = {

22
secrets/nginx.yaml Normal file
View file

@ -0,0 +1,22 @@
nginx:
htpasswd: ENC[AES256_GCM,data:IYNlj5G3lvBZIPjMpHxKuX+iaSAVgCQk1tszlx5eMqAPk/h4wT2IVlcZsw==,iv:En3YkQ8N5GFKKMMo2mrl0gb5DQfrdnktmhOL1xN1Up4=,tag:tlX4bomr5iQJdKCJ0FeIdw==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1kruum2varzua7w5n6n52vhwyek2arc685rhcwt0u7k2jf5mecsjslkl9ll
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZVThIbU01SXpLTFo5dUd3
WFdwT1ZhMmRXYWNLNFJnTnhnbDFydytwNFY0ClBjck1rVzNKRHVKNk02UnMxYmdF
S2pHMDdiVFI1NUdHTUhxbm02Y0V4b3MKLS0tIG91TGlvZmJlTURVU2hyYVNQekhW
MmJRbUxNelZqbDZNTDE1M01wbnRwcVEKQYyDt02jJLXDjelL3JjgFjCDj3KR19ZO
VAIinh7lUCG6QWu85Eak0ytrXsmVk/Rucnb3unBqnFYmUNp+rYXgMA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-11-24T14:24:45Z"
mac: ENC[AES256_GCM,data:nQok/IpaHozjeDFCOEq7wuEqp5+CBjdbsClIk9IfeK2Dz01jAnmgtwPMmZSnlbSQxBb69mw/KEj2mjYpt4vL9xe/0Dl4df6uJl6chgBRfm/JvXNbcGOag1MSarN1Oppyz9Rjqz48Ves0VtegR2NCIHaNuh5oagP9KJfgss6XibU=,iv:KvwA1S+rRPyJyseUnvalxlYQOKJ4RuAhn4nZA1sZA7M=,tag:lzjqf07wd69gDS8OmkOuEA==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.1

View file

@ -18,11 +18,13 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/".proxyPass = "http://${ip}:5230";
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${rootVolume}
chown ${uid}:${gid} ${rootVolume}

View file

@ -17,11 +17,13 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/".proxyPass = "http://${ip}:8080";
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
virtualisation.oci-containers.containers.${name} = {
inherit image;
hostname = name;

View file

@ -7,6 +7,7 @@ let
ip = "10.88.1.1";
image = "docker.io/pihole/pihole:latest";
piholeDNSIPBind = "192.168.100.5";
domain = "${name}.tigor.web.id";
in
{
config = mkIf (podman.enable && pihole.enable) {
@ -16,8 +17,8 @@ in
reverse_proxy ${ip}:80
'';
services.nginx.virtualHosts."pihole.tigor.web.id" = {
enableACME = true;
services.nginx.virtualHosts.${domain} = {
useACMEHost = "tigor.web.id";
forceSSL = true;
locations = {
"= /" = {
@ -29,6 +30,8 @@ in
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
sops.secrets."pihole/env" = {
sopsFile = ../../secrets/pihole.yaml;
};

View file

@ -25,13 +25,15 @@ lib.mkMerge [
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:8080";
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${volume}/{config,downloads,progress,watch}
chown ${uid}:${gid} ${volume} ${volume}/{config,downloads,progress,watch}

View file

@ -18,13 +18,15 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:8080";
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${rootVolume}/db
mkdir -p ${rootVolume}/images

View file

@ -25,13 +25,15 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:8080";
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${rootVolume}/db
mkdir -p ${rootVolume}/images

View file

@ -21,13 +21,15 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:6767";
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${configVolume}
chown ${uid}:${gid} ${mediaVolume} ${configVolume}

View file

@ -23,13 +23,15 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:9696";
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${configVolume}
chown ${uid}:${gid} ${configVolume}

View file

@ -21,7 +21,7 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:8080";
@ -29,6 +29,8 @@ in
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${configVolume} ${mediaVolume}
chown ${uid}:${gid} ${mediaVolume} ${configVolume}

View file

@ -21,7 +21,7 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:7878";
@ -29,6 +29,8 @@ in
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${configVolume} ${mediaVolume}
chown ${uid}:${gid} ${mediaVolume} ${configVolume}

View file

@ -21,7 +21,7 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:6500";
@ -29,6 +29,8 @@ in
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${volumeConfig} ${mediaVolume}
chown ${uid}:${gid} ${volumeConfig} ${mediaVolume}

View file

@ -22,7 +22,7 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:5000";
@ -30,6 +30,8 @@ in
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${configVolume} ${mediaVolume} ${watchVolume}
chown ${uid}:${gid} ${configVolume} ${mediaVolume} ${watchVolume}

View file

@ -25,7 +25,7 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:8989";
@ -33,12 +33,17 @@ in
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [
domain
domain-anime
];
services.caddy.virtualHosts.${domain-anime}.extraConfig = ''
reverse_proxy ${ip-anime}:8989
'';
services.nginx.virtualHosts.${domain-anime} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:8989";

View file

@ -19,25 +19,20 @@ let
in
{
config = mkIf (podman.enable && podman.${name}.enable) {
services.caddy.virtualHosts.${domain}.extraConfig = ''
@require_auth not remote_ip private_ranges
basic_auth @require_auth {
{$AUTH_USERNAME} {$AUTH_PASSWORD}
}
reverse_proxy ${ip}:6080
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:6080";
proxyWebsockets = true;
extraConfig = ''
auth_basic $auth_ip;
'';
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${rootVolume}/{config,downloads,incomplete}
chown ${uid}:${gid} ${rootVolume} ${rootVolume}/{config,downloads,incomplete}

View file

@ -22,13 +22,15 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:4567";
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
system.activationScripts."podman-${name}" = ''
mkdir -p ${volume}
chown ${uid}:${gid} ${volume}

View file

@ -64,8 +64,7 @@ in
lib.mkMerge [
(mkIf podman.${name}.enable {
services.nginx.virtualHosts.${domain} = {
enableACME = true;
# useACMEHost = "ytptube.tigor.web.id";
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${ip}:8081";
@ -73,6 +72,10 @@ lib.mkMerge [
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [
domain
];
services.caddy.virtualHosts.${domain}.extraConfig = ''
@require_auth not remote_ip private_ranges

View file

@ -15,7 +15,7 @@ in
];
services.nginx.virtualHosts."cockpit.tigor.web.id" = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://0.0.0.0:9090";
@ -23,6 +23,8 @@ in
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ "cockpit.tigor.web.id" ];
services.caddy.virtualHosts."cockpit.tigor.web.id".extraConfig = # caddyfile
''
@denied not remote_ip private_ranges

View file

@ -11,7 +11,7 @@ in
{
config = mkIf cfg.enable {
services.nginx.virtualHosts."git.tigor.web.id" = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations = {
"= /" = {
@ -30,6 +30,8 @@ in
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ "git.tigor.web.id" ];
services.caddy.virtualHosts."git.tigor.web.id".extraConfig = ''
@home_not_login {
not header_regexp Cookie gitea_incredible

View file

@ -17,7 +17,7 @@ in
'';
services.nginx.virtualHosts."${domain}" = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations = {
"= /metrics" = {
@ -30,7 +30,12 @@ in
};
};
services.caddy.virtualHosts.${domain}.extraConfig = ''
security.acme.certs."tigor.web.id".extraDomainNames = [
domain
domain-jellyseerr
];
services.caddy.virtualHosts."${domain}".extraConfig = ''
@public not remote_ip private_ranges
handle_path /metrics {
@ -53,14 +58,14 @@ in
reverse_proxy 0.0.0.0:8096
}
'';
services.caddy.virtualHosts.${domain-jellyseerr} = mkIf cfg.jellyseerr.enable {
services.caddy.virtualHosts."${domain-jellyseerr}" = mkIf cfg.jellyseerr.enable {
extraConfig = ''
reverse_proxy 0.0.0.0:5055
'';
};
services.nginx.virtualHosts.${domain-jellyseerr} = mkIf cfg.jellyseerr.enable {
enableACME = true;
services.nginx.virtualHosts."${domain-jellyseerr}" = mkIf cfg.jellyseerr.enable {
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://0.0.0.0:5055";

View file

@ -25,7 +25,7 @@ in
'';
services.nginx.virtualHosts."kavita.tigor.web.id" = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations = {
"/" = {
@ -34,6 +34,8 @@ in
};
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ "kavita.tigor.web.id" ];
services.kavita = {
enable = true;
tokenKeyFile = config.sops.secrets."kavita/token".path;

View file

@ -11,7 +11,7 @@ in
'';
services.nginx.virtualHosts."navidrome.tigor.web.id" = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations = {
"/" = {
@ -21,6 +21,8 @@ in
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ "navidrome.tigor.web.id" ];
users.groups.navidrome.members = [ user.name ];
users.groups.${user.name}.members = [ "navidrome" ];

View file

@ -83,6 +83,7 @@ in
};
services.nginx.virtualHosts."tigor.web.id" = {
# Enable ACME implies security.acme.certs."tigor.web.id" to be created.
enableACME = true;
forceSSL = true;
locations."/" = {
@ -91,38 +92,39 @@ in
};
};
sops.secrets."nginx/htpasswd" = {
sopsFile = ../../secrets/nginx.yaml;
owner = "nginx";
};
# Enable Real IP from Cloudflare
services.nginx.commonHttpConfig =
let
realIpsFromList = lib.strings.concatMapStringsSep "\n" (x: "set_real_ip_from ${x};");
fileToList = x: lib.strings.splitString "\n" (builtins.readFile x);
cfipv4 = fileToList (
pkgs.fetchurl {
url = "https://www.cloudflare.com/ips-v4";
sha256 = "0ywy9sg7spafi3gm9q5wb59lbiq0swvf0q3iazl0maq1pj1nsb7h";
}
);
cfipv6 = fileToList (
pkgs.fetchurl {
url = "https://www.cloudflare.com/ips-v6";
sha256 = "1ad09hijignj6zlqvdjxv7rjj8567z357zfavv201b9vx3ikk7cy";
}
);
in
# let
# realIpsFromList = lib.strings.concatMapStringsSep "\n" (x: "set_real_ip_from ${x};");
# fileToList = x: lib.strings.splitString "\n" (builtins.readFile x);
# cfipv4 = fileToList (
# pkgs.fetchurl {
# url = "https://www.cloudflare.com/ips-v4";
# sha256 = "0ywy9sg7spafi3gm9q5wb59lbiq0swvf0q3iazl0maq1pj1nsb7h";
# }
# );
# cfipv6 = fileToList (
# pkgs.fetchurl {
# url = "https://www.cloudflare.com/ips-v6";
# sha256 = "1ad09hijignj6zlqvdjxv7rjj8567z357zfavv201b9vx3ikk7cy";
# }
# );
# in
#nginx
''
geo $auth_ip {
default "Password required";
10.0.0.0/8 "off";
172.16.0.0/12 "off";
192.168.0.0/16 "off";
10.0.0.0/8 off;
172.16.0.0/12 off;
192.168.0.0/16 off;
}
auth_pam_service_name "nginx";
${realIpsFromList cfipv4}
${realIpsFromList cfipv6}
real_ip_header CF-Connecting-IP;
auth_basic_user_file ${config.sops.secrets."nginx/htpasswd".path};
'';
# This is needed for nginx to be able to read other processes

View file

@ -19,7 +19,7 @@ lib.mkMerge [
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations = {
"/" = {
@ -29,6 +29,8 @@ lib.mkMerge [
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
services.ntfy-sh = {
enable = true;
settings =

View file

@ -22,7 +22,7 @@ in
'';
services.nginx.virtualHosts.${domain} = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations = {
"/" = {
@ -32,6 +32,8 @@ in
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ domain ];
sops.secrets."photoprism/admin_password" = {
sopsFile = ../../secrets/photoprism.yaml;
};

View file

@ -18,7 +18,7 @@ in
'';
services.nginx.virtualHosts."syncthing.tigor.web.id" = {
enableACME = true;
useACMEHost = "tigor.web.id";
forceSSL = true;
locations = {
"/" = {
@ -27,6 +27,8 @@ in
};
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [ "syncthing.tigor.web.id" ];
sops.secrets =
let
opts = {

View file

@ -29,6 +29,19 @@ in
reverse_proxy ${config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port}
'';
services.nginx.virtualHosts.${grafanaDomain} = {
useACMEHost = "tigor.web.id";
forceSSL = true;
locations."/" = {
proxyPass = "http://${config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port}";
proxyWebsockets = true;
};
};
security.acme.certs."tigor.web.id".extraDomainNames = [
grafanaDomain
];
services.grafana = {
enable = true;
package = pkgs.grafana;