{ description = "A simple OIDC SSO service"; outputs = { self, nixpkgs, systems, }: let inherit (nixpkgs) lib; eachSystem = f: lib.genAttrs (import systems) (system: f { inherit system; pkgs = nixpkgs.legacyPackages.${system}; ownPkgs = self.packages.${system}; }); in { devShells = eachSystem ({pkgs, ...}: { default = pkgs.beam.packages.erlang_26.callPackage ./shell.nix {}; }); packages = eachSystem ({pkgs, ...}: { default = pkgs.beam.packages.erlang_26.callPackage ./default.nix { inherit self; }; }); nixosModules = { default = { lib, pkgs, config, ... }: let sso-bsn = self.packages.${pkgs.system}.default; gen-secret = pkgs.writeShellScript "gen-secret" '' mkdir -p $1 (umask 077; [ -f $1/$2 ] || ${pkgs.coreutils}/bin/head -c 128 /dev/urandom | ${pkgs.coreutils}/bin/base64 -w0 > $1/$2) ''; secret = var: dir: file: '' ${gen-secret} "${dir}" "${file}" ${var}=$(${pkgs.coreutils}/bin/cat "${dir}/${file}") ''; script = pkgs.writeShellScript "sso-bsn" '' ${secret "RELEASE_COOKIE" "/run/sso-bsn" "cookie"} ${lib.getExe sso-bsn} "$@" ''; cfg = config.services.bluepython508.sso-bsn; in { options.services.bluepython508.sso-bsn = { enable = lib.mkEnableOption "sso-bsn"; host = lib.mkOption { type = lib.types.string; }; session-domain = lib.mkOption { type = with lib.types; nullOr string; }; }; options.services.nginx.virtualHosts = lib.mkOption { type = lib.types.attrsOf (lib.types.submodule ({ config }: { options.sso.enable = lib.mkEnableOption "SSO BSN"; config.extraConfig = lib.mkIf config.sso.enable '' auth_request /__auth_sso_validate; proxy_set_header X-Auth-Username $auth_resp_username; location = /__auth_sso_validate { internal; proxy_pass https://${cfg.host}/whoami; proxy_pass_request_body off; # no need to send the POST body proxy_set_header Content-Length ""; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; auth_request_set $auth_resp_username $upstream_http_x_auth_username; } error_page 401 = @error401; location @error401 { return 302 url=https://${cfg.host}/user/log_in?next=$http_host$request_uri; } ''; })); }; config.environment.systemPackages = lib.mkIf cfg.enable [ script ]; config.systemd.services.sso-bsn = lib.mkIf cfg.enable { description = "sso-bsn"; environment = { SERVER = "true"; DATABASE_PATH = "/var/lib/sso-bsn/db.sqlite"; BIND_UNIX = "/run/sso-bsn/sock"; SSO_BSN_HOST = cfg.host; SESSION_DOMAIN = cfg.session-domain; }; script = '' ${secret "SECRET_KEY_BASE" "/var/lib/sso-bsn" "secret-key-base"} SECRET_KEY_BASE="$SECRET_KEY_BASE" ${script} start ''; wantedBy = [ "multi-user.target" ]; serviceConfig = { DynamicUser = true; ProtectHome = true; PrivateUsers = true; StateDirectory = "sso-bsn"; }; }; config.services.nginx.virtualHosts = lib.mkIf cfg.enable { ${cfg.host} = { forceSSL = true; enableACME = true; locations."/" = { proxyPass = "http://unix:/run/sso-bsn/sock:/"; recommendedProxySettings = true; proxyWebsockets = true; }; }; }; }; }; }; }