summaryrefslogtreecommitdiff
path: root/os/srv/authelia.nix
blob: 2c42b0a4bb79c46222c185b0ae1de0e9b0ad48bc (plain)
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
{
  config,
  lib,
  masterDomain,
  securityTemplates,
  ...
}:
let
  cfg = config.os.srv.authelia;
  computedBaseDN = lib.concatStringsSep "," (
    map (domainPart: "dc=${domainPart}") (lib.splitString "." masterDomain)
  );
in
{
  options.os.srv.authelia.enable =
    lib.mkEnableOption "enables authelia authentication gateway instance";

  config = lib.mkIf cfg.enable {
    assertions = [
      {
        assertion = config.os.srv.sops.enable;
        message = "sops must be enabled for secure cryptographic token storage";
      }
      {
        assertion = config.os.core.network.enableFirewall;
        message = "Requires firewall";
      }
    ];

    sops.secrets = {
      "authelia/jwt_secret" = {
        owner = "authelia-main";
        group = "authelia-main";
        restartUnits = [ "authelia-main.service" ];
      };
      "authelia/session_secret" = {
        owner = "authelia-main";
        group = "authelia-main";
        restartUnits = [ "authelia-main.service" ];
      };
      "authelia/encryption_key" = {
        owner = "authelia-main";
        group = "authelia-main";
        restartUnits = [ "authelia-main.service" ];
      };

      "authelia/oidc_hmac" = {
        owner = "authelia-main";
        group = "authelia-main";
        restartUnits = [ "authelia-main.service" ];
      };
      "authelia/oidc_private_key" = {
        owner = "authelia-main";
        group = "authelia-main";
        restartUnits = [ "authelia-main.service" ];
      };

      "postgres/authelia_password" = {
        owner = "authelia-main";
        group = "authelia-main";
        restartUnits = [ "authelia-main.service" ];
      };
      "redis/password" = {
        owner = "authelia-main";
        group = "authelia-main";
        restartUnits = [ "authelia-main.service" ];
      };
    };

    services.authelia.instances.main = {
      enable = true;

      secrets = {
        jwtSecretFile = config.sops.secrets."authelia/jwt_secret".path;
        sessionSecretFile = config.sops.secrets."authelia/session_secret".path;
        storageEncryptionKeyFile = config.sops.secrets."authelia/encryption_key".path;

        oidcHmacSecretFile = config.sops.secrets."authelia/oidc_hmac".path;
        oidcIssuerPrivateKeyFile = config.sops.secrets."authelia/oidc_private_key".path;
      };

      settings = {
        theme = "dark";
        default_2fa_method = "totp";

        log = {
          level = "info";
          format = "json";
          path = "/var/log/authelia/authelia.log";
          keep_stdout = true;
        };

        server.address = "tcp://127.0.0.1:9091";

        telemetry.metrics = {
          enabled = true;
          address = "tcp://127.0.0.1:9959";
        };

        storage = {
          postgres = {
            host = config.os.core.network.ips.database-vm;
            port = 5432;
            database = "authelia";
            username = "authelia";
            timeout = "5s";
            schema = "public";
          };
        };

        session = {
          name = "authelia_session";
          expiration = "1h";
          inactivity = "15m";
          remember_me = "1M";
          provider = {
            redis = {
              host = config.os.core.network.ips.database-vm;
              port = 6379;
              database = 0;
              timeout = "5s";
            };
          };
        };

        authentication_backend = {
          ldap = {
            address = "ldap://${config.os.core.network.ips.gateway-vm}:3890";
            implementation = "lldap";
            base_dn = computedBaseDN;
            user = "uid=authelia,ou=people,${computedBaseDN}";
          };
        };

        identity_providers = {
          oidc = {
            cors.allowed_origins = map (domain: "https://${domain}") (
              builtins.attrNames config.os.cluster.nginxProxies
            );

            clients = config.os.cluster.oidcClients;
          };
        };

        access_control = {
          default_policy = "deny";
          rules = [
            {
              domain = "auth.${masterDomain}";
              policy = "bypass";
            }
          ]
          ++ config.os.cluster.autheliaRules;
        };

        session.domain = masterDomain;
      };

      environmentVariables = {
        AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = config.sops.secrets."lldap/password".path;
        AUTHELIA_SESSION_REDIS_PASSWORD_FILE = config.sops.secrets."redis/password".path;
        AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE = config.sops.secrets."postreg/authelia_password".path;
      };
    };

    os.cluster.nginxProxies."auth.${masterDomain}" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://${config.os.core.network.ips.gateway-vm}:9091";
        extraConfig = securityTemplates.restrictToInternal;
      };
    };

    networking.firewall.extraInputRules = ''
      ip saddr ${config.os.core.network.ips.monitor-vm} tcp dport 9959 accept
    '';
  };
}