at 24.11-pre 5.6 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8let 9 inherit (lib) 10 boolToString 11 concatStringsSep 12 hasAttr 13 isBool 14 mapAttrs 15 mkDefault 16 mkEnableOption 17 mkIf 18 mkOption 19 mkPackageOption 20 ; 21 22 inherit (lib.types) 23 attrsOf 24 bool 25 either 26 package 27 str 28 submodule 29 ; 30 31 toStringEnv = value: if isBool value then boolToString value else toString value; 32 33 cfg = config.services.netbird.server.dashboard; 34in 35 36{ 37 options.services.netbird.server.dashboard = { 38 enable = mkEnableOption "the static netbird dashboard frontend"; 39 40 package = mkPackageOption pkgs "netbird-dashboard" { }; 41 42 enableNginx = mkEnableOption "Nginx reverse-proxy to serve the dashboard."; 43 44 domain = mkOption { 45 type = str; 46 default = "localhost"; 47 description = "The domain under which the dashboard runs."; 48 }; 49 50 managementServer = mkOption { 51 type = str; 52 description = "The address of the management server, used for the API endpoints."; 53 }; 54 55 settings = mkOption { 56 type = submodule { freeformType = attrsOf (either str bool); }; 57 58 defaultText = '' 59 { 60 AUTH_AUDIENCE = "netbird"; 61 AUTH_CLIENT_ID = "netbird"; 62 AUTH_SUPPORTED_SCOPES = "openid profile email"; 63 NETBIRD_TOKEN_SOURCE = "idToken"; 64 USE_AUTH0 = false; 65 } 66 ''; 67 68 description = '' 69 An attribute set that will be used to substitute variables when building the dashboard. 70 Any values set here will be templated into the frontend and be public for anyone that can reach your website. 71 The exact values sadly aren't documented anywhere. 72 A starting point when searching for valid values is this [script](https://github.com/netbirdio/dashboard/blob/main/docker/init_react_envs.sh) 73 The only mandatory value is 'AUTH_AUTHORITY' as we cannot set a default value here. 74 ''; 75 }; 76 77 finalDrv = mkOption { 78 readOnly = true; 79 type = package; 80 description = '' 81 The derivation containing the final templated dashboard. 82 ''; 83 }; 84 }; 85 86 config = mkIf cfg.enable { 87 assertions = [ 88 { 89 assertion = hasAttr "AUTH_AUTHORITY" cfg.settings; 90 message = "The setting AUTH_AUTHORITY is required for the dasboard to function."; 91 } 92 ]; 93 94 services.netbird.server.dashboard = { 95 settings = 96 { 97 # Due to how the backend and frontend work this secret will be templated into the backend 98 # and then served statically from your website 99 # This enables you to login without the normally needed indirection through the backend 100 # but this also means anyone that can reach your website can 101 # fetch this secret, which is why there is no real need to put it into 102 # special options as its public anyway 103 # As far as I know leaking this secret is just 104 # an information leak as one can fetch some basic app 105 # informations from the IDP 106 # To actually do something one still needs to have login 107 # data and this secret so this being public will not 108 # suffice for anything just decreasing security 109 AUTH_CLIENT_SECRET = ""; 110 111 NETBIRD_MGMT_API_ENDPOINT = cfg.managementServer; 112 NETBIRD_MGMT_GRPC_API_ENDPOINT = cfg.managementServer; 113 } 114 // (mapAttrs (_: mkDefault) { 115 # Those values have to be easily overridable 116 AUTH_AUDIENCE = "netbird"; # must be set for your devices to be able to log in 117 AUTH_CLIENT_ID = "netbird"; 118 AUTH_SUPPORTED_SCOPES = "openid profile email"; 119 NETBIRD_TOKEN_SOURCE = "idToken"; 120 USE_AUTH0 = false; 121 }); 122 123 # The derivation containing the templated dashboard 124 finalDrv = 125 pkgs.runCommand "netbird-dashboard" 126 { 127 nativeBuildInputs = [ pkgs.gettext ]; 128 env = { 129 ENV_STR = concatStringsSep " " [ 130 "$AUTH_AUDIENCE" 131 "$AUTH_AUTHORITY" 132 "$AUTH_CLIENT_ID" 133 "$AUTH_CLIENT_SECRET" 134 "$AUTH_REDIRECT_URI" 135 "$AUTH_SILENT_REDIRECT_URI" 136 "$AUTH_SUPPORTED_SCOPES" 137 "$NETBIRD_DRAG_QUERY_PARAMS" 138 "$NETBIRD_GOOGLE_ANALYTICS_ID" 139 "$NETBIRD_HOTJAR_TRACK_ID" 140 "$NETBIRD_MGMT_API_ENDPOINT" 141 "$NETBIRD_MGMT_GRPC_API_ENDPOINT" 142 "$NETBIRD_TOKEN_SOURCE" 143 "$USE_AUTH0" 144 ]; 145 } // (mapAttrs (_: toStringEnv) cfg.settings); 146 } 147 '' 148 cp -R ${cfg.package} build 149 150 find build -type d -exec chmod 755 {} \; 151 OIDC_TRUSTED_DOMAINS="build/OidcTrustedDomains.js" 152 153 envsubst "$ENV_STR" < "$OIDC_TRUSTED_DOMAINS.tmpl" > "$OIDC_TRUSTED_DOMAINS" 154 155 for f in $(grep -R -l AUTH_SUPPORTED_SCOPES build/); do 156 mv "$f" "$f.copy" 157 envsubst "$ENV_STR" < "$f.copy" > "$f" 158 rm "$f.copy" 159 done 160 161 cp -R build $out 162 ''; 163 }; 164 165 services.nginx = mkIf cfg.enableNginx { 166 enable = true; 167 168 virtualHosts.${cfg.domain} = { 169 locations = { 170 "/" = { 171 root = cfg.finalDrv; 172 tryFiles = "$uri $uri.html $uri/ =404"; 173 }; 174 175 "/404.html".extraConfig = '' 176 internal; 177 ''; 178 }; 179 180 extraConfig = '' 181 error_page 404 /404.html; 182 ''; 183 }; 184 }; 185 }; 186}