grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / web-servers / nginx / tailscale-auth.nix
blobde1d708cbb423f9113616795533abadd1db1e169
1 { config, lib, ... }:
3 let
4   inherit (lib)
5     genAttrs
6     maintainers
7     mkAliasOptionModule
8     mkEnableOption
9     mkIf
10     mkOption
11     types
12     ;
13   cfg = config.services.nginx.tailscaleAuth;
14   cfgAuth = config.services.tailscaleAuth;
17   imports = [
18     (mkAliasOptionModule [ "services" "nginx" "tailscaleAuth" "package" ] [ "services" "tailscaleAuth" "package" ])
19     (mkAliasOptionModule [ "services" "nginx" "tailscaleAuth" "user" ] [ "services" "tailscaleAuth" "user" ])
20     (mkAliasOptionModule [ "services" "nginx" "tailscaleAuth" "group" ] [ "services" "tailscaleAuth" "group" ])
21     (mkAliasOptionModule [ "services" "nginx" "tailscaleAuth" "socketPath" ] [ "services" "tailscaleAuth" "socketPath" ])
22   ];
24   options.services.nginx.tailscaleAuth = {
25     enable = mkEnableOption "tailscale.nginx-auth, to authenticate nginx users via tailscale";
27     expectedTailnet = mkOption {
28       default = "";
29       type = types.nullOr types.str;
30       example = "tailnet012345.ts.net";
31       description = ''
32         If you want to prevent node sharing from allowing users to access services
33         across tailnets, declare your expected tailnets domain here.
34       '';
35     };
37     virtualHosts = mkOption {
38       type = types.listOf types.str;
39       default = [];
40       description = ''
41         A list of nginx virtual hosts to put behind tailscale.nginx-auth
42       '';
43     };
44   };
46   config = mkIf cfg.enable {
47     services.tailscaleAuth.enable = true;
48     services.nginx.enable = true;
50     users.users.${config.services.nginx.user}.extraGroups = [ cfgAuth.group ];
52     systemd.services.tailscale-nginx-auth = {
53       after = [ "nginx.service" ];
54       wants = [ "nginx.service" ];
55     };
57     services.nginx.virtualHosts = genAttrs
58       cfg.virtualHosts
59       (vhost: {
60         locations."/auth" = {
61           extraConfig = ''
62             internal;
64             proxy_pass http://unix:${cfgAuth.socketPath};
65             proxy_pass_request_body off;
67             # Upstream uses $http_host here, but we are using gixy to check nginx configurations
68             # gixy wants us to use $host: https://github.com/yandex/gixy/blob/master/docs/en/plugins/hostspoofing.md
69             proxy_set_header Host $host;
70             proxy_set_header Remote-Addr $remote_addr;
71             proxy_set_header Remote-Port $remote_port;
72             proxy_set_header Original-URI $request_uri;
73             proxy_set_header X-Scheme                $scheme;
74             proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
75           '';
76         };
77         locations."/".extraConfig = ''
78           auth_request /auth;
79           auth_request_set $auth_user $upstream_http_tailscale_user;
80           auth_request_set $auth_name $upstream_http_tailscale_name;
81           auth_request_set $auth_login $upstream_http_tailscale_login;
82           auth_request_set $auth_tailnet $upstream_http_tailscale_tailnet;
83           auth_request_set $auth_profile_picture $upstream_http_tailscale_profile_picture;
85           proxy_set_header X-Webauth-User "$auth_user";
86           proxy_set_header X-Webauth-Name "$auth_name";
87           proxy_set_header X-Webauth-Login "$auth_login";
88           proxy_set_header X-Webauth-Tailnet "$auth_tailnet";
89           proxy_set_header X-Webauth-Profile-Picture "$auth_profile_picture";
91           ${lib.optionalString (cfg.expectedTailnet != "") ''proxy_set_header Expected-Tailnet "${cfg.expectedTailnet}";''}
92         '';
93       });
94   };
96   meta.maintainers = with maintainers; [ phaer ];