about summary refs log tree commit diff
path: root/modules/services/traefik/default.nix
blob: d6a8c8cc227aab24e0cfe514a8306a61b47f4dc0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
{ pkgs, inputs, config, lib, ... }:

with lib;

let
  cfg = config.my.services.traefik;
  domainPublic = "fcuny.net";
  domainPrivate = "fcuny.xyz";
  mkServiceConfig = name: url: domain: certResolver: {
    http.routers."${name}.${domain}" = {
      rule = "Host(`${name}.${domain}`)";
      service = "${name}.${domain}";
      tls.certResolver = certResolver;
    };
    http.services."${name}.${domain}" = {
      loadBalancer.servers = [{ url = url; }];
    };
  };
in {
  options.my.services.traefik = with lib; {
    enable = mkEnableOption "traefik router";
  };

  config = lib.mkIf cfg.enable {
    age.secrets.traefik_gcp_sa = {
      file = ../../../secrets/traefik/gcp_service_account.json.age;
      owner = "traefik";
    };

    services.traefik = {
      enable = true;

      staticConfigOptions = {
        metrics.prometheus = {
          addEntryPointsLabels = true;
          addRoutersLabels = true;
          addServicesLabels = true;
        };

        global = {
          checkNewVersion = false;
          sendAnonymousUsage = false;
        };

        accessLog.format = "json";
        log.level = "warn";

        entryPoints.http.http.redirections = {
          entryPoint.to = "https";
          entryPoint.scheme = "https";
          entryPoint.permanent = true;
        };

        entryPoints.http.address = ":80";
        entryPoints.https.address = ":443";
        # the default is 8080, which conflict with unifi
        entryPoints.traefik.address = ":8090";

        api = {
          dashboard = true;
          insecure = true;
        };

        # The unifi controller runs on HTTPS with a self-signed
        # certificate, as a result we need to accept insecure
        # certificates.
        serversTransport.insecureSkipVerify = true;

        certificatesResolvers = {
          le-http.acme = {
            email = "franck@fcuny.net";
            storage = "/var/lib/traefik/cert.json";
            httpChallenge = { entryPoint = "http"; };
          };
          le-dns.acme = {
            email = "franck@fcuny.net";
            storage = "/var/lib/traefik/cert.json";
            dnsChallenge = {
              provider = "gcloud";
              delayBeforeCheck = 0;
            };
          };
        };
      };
    };

    services.traefik.dynamicConfigOptions = mkMerge [
      (mkServiceConfig "dash" "http://127.0.0.1:3000/" domainPrivate "le-dns")
      (mkServiceConfig "bt" "http://127.0.0.1:9091/" domainPrivate "le-dns")
      (mkServiceConfig "unifi" "https://127.0.0.1:8443/" domainPrivate "le-dns")
      (mkServiceConfig "music" "http://127.0.0.1:4533/" domainPrivate "le-dns")
      (mkServiceConfig "git" "http://127.0.0.1:8002/" domainPrivate "le-dns")
      (mkServiceConfig "git" "http://127.0.0.1:8002/" domainPublic "le-http")
    ];

    systemd.services.traefik.environment.GCE_SERVICE_ACCOUNT_FILE =
      config.age.secrets.traefik_gcp_sa.path;
    systemd.services.traefik.environment.GCE_PROJECT = "fcuny-homelab";

    networking.firewall.allowedTCPPorts = [ 80 443 ];
    networking.firewall.allowedUDPPorts = [ 443 ]; # QUIC
  };
}