at 25.11-pre 3.5 kB view raw
1{ config, lib, ... }: 2 3let 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; 15in 16{ 17 imports = [ 18 (mkAliasOptionModule 19 [ "services" "nginx" "tailscaleAuth" "package" ] 20 [ "services" "tailscaleAuth" "package" ] 21 ) 22 (mkAliasOptionModule 23 [ "services" "nginx" "tailscaleAuth" "user" ] 24 [ "services" "tailscaleAuth" "user" ] 25 ) 26 (mkAliasOptionModule 27 [ "services" "nginx" "tailscaleAuth" "group" ] 28 [ "services" "tailscaleAuth" "group" ] 29 ) 30 (mkAliasOptionModule 31 [ "services" "nginx" "tailscaleAuth" "socketPath" ] 32 [ "services" "tailscaleAuth" "socketPath" ] 33 ) 34 ]; 35 36 options.services.nginx.tailscaleAuth = { 37 enable = mkEnableOption "tailscale.nginx-auth, to authenticate nginx users via tailscale"; 38 39 expectedTailnet = mkOption { 40 default = ""; 41 type = types.nullOr types.str; 42 example = "tailnet012345.ts.net"; 43 description = '' 44 If you want to prevent node sharing from allowing users to access services 45 across tailnets, declare your expected tailnets domain here. 46 ''; 47 }; 48 49 virtualHosts = mkOption { 50 type = types.listOf types.str; 51 default = [ ]; 52 description = '' 53 A list of nginx virtual hosts to put behind tailscale.nginx-auth 54 ''; 55 }; 56 }; 57 58 config = mkIf cfg.enable { 59 services.tailscaleAuth.enable = true; 60 services.nginx.enable = true; 61 62 users.users.${config.services.nginx.user}.extraGroups = [ cfgAuth.group ]; 63 64 systemd.services.tailscale-nginx-auth = { 65 after = [ "nginx.service" ]; 66 wants = [ "nginx.service" ]; 67 }; 68 69 services.nginx.virtualHosts = genAttrs cfg.virtualHosts (vhost: { 70 locations."/auth" = { 71 extraConfig = '' 72 internal; 73 74 proxy_pass http://unix:${cfgAuth.socketPath}; 75 proxy_pass_request_body off; 76 77 # Upstream uses $http_host here, but we are using gixy to check nginx configurations 78 # gixy wants us to use $host: https://github.com/yandex/gixy/blob/master/docs/en/plugins/hostspoofing.md 79 proxy_set_header Host $host; 80 proxy_set_header Remote-Addr $remote_addr; 81 proxy_set_header Remote-Port $remote_port; 82 proxy_set_header Original-URI $request_uri; 83 proxy_set_header X-Scheme $scheme; 84 proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; 85 ''; 86 }; 87 locations."/".extraConfig = '' 88 auth_request /auth; 89 auth_request_set $auth_user $upstream_http_tailscale_user; 90 auth_request_set $auth_name $upstream_http_tailscale_name; 91 auth_request_set $auth_login $upstream_http_tailscale_login; 92 auth_request_set $auth_tailnet $upstream_http_tailscale_tailnet; 93 auth_request_set $auth_profile_picture $upstream_http_tailscale_profile_picture; 94 95 proxy_set_header X-Webauth-User "$auth_user"; 96 proxy_set_header X-Webauth-Name "$auth_name"; 97 proxy_set_header X-Webauth-Login "$auth_login"; 98 proxy_set_header X-Webauth-Tailnet "$auth_tailnet"; 99 proxy_set_header X-Webauth-Profile-Picture "$auth_profile_picture"; 100 101 ${lib.optionalString ( 102 cfg.expectedTailnet != "" 103 ) ''proxy_set_header Expected-Tailnet "${cfg.expectedTailnet}";''} 104 ''; 105 }); 106 }; 107 108 meta.maintainers = with maintainers; [ phaer ]; 109 110}