diff --git a/machines/gerd.nix b/machines/gerd.nix index 0ca28bf..0794a8b 100644 --- a/machines/gerd.nix +++ b/machines/gerd.nix @@ -7,9 +7,9 @@ ./../shared/applications/state/ssh.nix ./gerd/services/lldap.nix - # ./gerd/services/authelia.nix + ./gerd/services/authelia.nix ./gerd/services/fricloud-website.nix - ./gerd/services/forgejo.nix + ./gerd/services/forgejo ./gerd/services/teeworlds.nix ./gerd/services/murmur.nix ./gerd/services/hedgedoc.nix diff --git a/machines/gerd/services/authelia.nix b/machines/gerd/services/authelia.nix index be6f010..f88244a 100644 --- a/machines/gerd/services/authelia.nix +++ b/machines/gerd/services/authelia.nix @@ -8,7 +8,7 @@ in { services.authelia.instances.main = { enable = true; - environmentVariables.AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = config.age.secrets.authelia-lldap-bind-user-pass.path; + environmentVariables.AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = config.age.secrets.lldap-bind-user-pass.path; secrets = { jwtSecretFile = config.age.secrets.authelia-jwt.path; storageEncryptionKeyFile = config.age.secrets.authelia-storage.path; @@ -17,9 +17,13 @@ in { }; settings = { - access_control.default_policy = "one_factor"; session.domain = config.mine.settings.domain; + # totp - disable for now, as it requires email server + access_control.default_policy = "one_factor"; + default_2fa_method = "totp"; + totp.issuer = "auth.fricloud.dk"; + storage.local.path = "${autheliaStateDir}/authelia.sqlite3"; notifier.filesystem.filename = "${autheliaStateDir}/authelia_notifier.txt"; @@ -53,29 +57,6 @@ in { }; }; - # example configuration for forgejo. Should live in forgejo.nix if needed - # services.authelia.instances.main.settings.identity_providers.oidc.clients = [{ - # id = "forgejo"; - # description = "Forgejo"; - - # # authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986 - # secret = "$pbkdf2-sha512$310000$cOGtLwMHyfugAJCIiUUjfQ$ao7zC8QB1m8aTGNf1dxYbRAPivZ0G1eaJ4bNFVfJiTFZX06U5baBjT0emvoaeFHXMFbYHzorb2/8vxnY/D0b5Q"; - - # public = false; - # authorization_policy = "one_factor"; - # redirect_uris = [ "https://git.fricloud.dk/user/oauth2/authelia/callback" ]; - # scopes = [ - # "openid" - # "email" - # "profile" - # ]; - - # userinfo_signing_algorithm = "none"; - # # userinfo_signed_response_alg = "none"; - # # token_endpoint_auth_method = "client_secret_basic"; - # }]; - - services.nginx.virtualHosts."${svc_domain}" = { forceSSL = true; enableACME = true; @@ -96,4 +77,7 @@ in { }; users.groups."${config.age.secrets.lldap-bind-user-pass.group}".members = [ config.users.users.authelia-main.name ]; + + # settings + mine.settings.authelia.domain = svc_domain; } diff --git a/machines/gerd/services/forgejo.nix b/machines/gerd/services/forgejo.nix deleted file mode 100644 index 3b91f8b..0000000 --- a/machines/gerd/services/forgejo.nix +++ /dev/null @@ -1,91 +0,0 @@ -{ config, lib, pkgs, ... }: - -let - svc_domain = "git.${config.mine.settings.domain}"; - - scriptAddLDAPAuth = pkgs.writeShellScript "forgejo-add-update-ldap-auth.sh" '' - #!/usr/bin/env sh - FORGEJO_WORK_PATH="${config.services.forgejo.stateDir}" - FORGEJO_AUTH_LDAP_NAME="lldap" - - # get lldap id if any - FORGEJO_AUTH_ID=$(gitea --work-path "$FORGEJO_WORK_PATH" admin auth list | grep "$FORGEJO_AUTH_LDAP_NAME" | cut -d$'\t' -f1) - - ACTION="" - EXTRA_ARG="" - if [ -n "''${FORGEJO_AUTH_ID}" ]; then - echo "PRERUN-LDAP: Authentication source exists, updating..." - ACTION="update-ldap" - EXTRA_ARG="--id $FORGEJO_AUTH_ID" - else - echo "PRERUN-LDAP: Authentication source does not exists, adding..." - ACTION="add-ldap" - fi - - BIND_USERPASS="$(cat $CREDENTIALS_DIRECTORY/lldap-bind-user-pass)" - - gitea \ - --work-path /srv/forgejo/ \ - admin auth "$ACTION" $EXTRA_ARG \ - --name "$FORGEJO_AUTH_LDAP_NAME" \ - --active \ - --security-protocol unencrypted \ - --skip-tls-verify \ - --host ${config.mine.settings.ldap.host} \ - --port ${builtins.toString config.mine.settings.ldap.port} \ - --bind-dn "${config.mine.settings.ldap.bind_dn}" \ - --bind-password "$BIND_USERPASS" \ - --user-filter '(&${config.mine.settings.ldap.user_filter}(|(${config.mine.settings.ldap.attr.uid}=%[1]s)(${config.mine.settings.ldap.attr.email}=%[1]s)))' \ - --admin-filter '${config.mine.settings.ldap.admin_filter}' \ - --username-attribute ${config.mine.settings.ldap.attr.uid} \ - --firstname-attribute ${config.mine.settings.ldap.attr.firstname} \ - --surname-attribute ${config.mine.settings.ldap.attr.lastname} \ - --email-attribute ${config.mine.settings.ldap.attr.email} \ - --avatar-attribute ${config.mine.settings.ldap.attr.avatar} \ - --synchronize-users \ - --user-search-base '${config.mine.settings.ldap.search_base}' \ - - echo "PRERUN-LDAP: Finished adding/updating..." - ''; - -in { - services.forgejo = { - enable = true; - - stateDir = config.mine.zfsMounts."rpool/safe/svcs/forgejo"; - - settings = { - server = { - DOMAIN = svc_domain; - ROOT_URL = "https://${svc_domain}"; - HTTPPORT = 3000; - }; - - # sync ldap and forgejo - "cron.sync_external_users" = { - RUN_AT_START = true; - SCHEDULE = "@every 15m"; - UPDATE_EXISTING = true; - }; - - service.DISABLE_REGISTRATION = true; - }; - }; - - # add script to add/update ldap source (+ place credential into the service) - systemd.services.forgejo.preStart = lib.mkAfter (builtins.toString scriptAddLDAPAuth); - systemd.services.forgejo.serviceConfig.LoadCredential = "lldap-bind-user-pass:${config.age.secrets.lldap-bind-user-pass.path}"; - - # TODO(eyJhb): remove after our ban expires (and nginx config) - # already issued for this exact set of domains in the last 168 hours: git.fricloud.dk, retry after 2024-08-10T01:34:44Z - security.acme.certs."git.fricloud.dk".extraDomainNames = [ "git2.fricloud.dk" ]; - - services.nginx.virtualHosts."${svc_domain}" = { - forceSSL = true; - enableACME = true; - extraConfig = '' - client_max_body_size 512M; - ''; - locations."/".proxyPass = "http://localhost:${builtins.toString config.services.forgejo.settings.server.HTTPPORT}"; - }; -} diff --git a/machines/gerd/services/forgejo/auth_sources.nix b/machines/gerd/services/forgejo/auth_sources.nix new file mode 100644 index 0000000..9bcdb94 --- /dev/null +++ b/machines/gerd/services/forgejo/auth_sources.nix @@ -0,0 +1,119 @@ +{ config, lib, pkgs, ... }: + +let + AUTHELIA_AUTH_NAME = "authelia"; + + scriptAddLDAPAuth = pkgs.writeShellScript "forgejo-add-update-ldap-auth.sh" '' + #!/usr/bin/env sh + FORGEJO_WORK_PATH="${config.services.forgejo.stateDir}" + FORGEJO_AUTH_NAME="lldap" + + # get auth id if any + FORGEJO_AUTH_ID=$(gitea --work-path "$FORGEJO_WORK_PATH" admin auth list | grep "$FORGEJO_AUTH_NAME" | cut -d$'\t' -f1) + + ACTION="" + EXTRA_ARG="" + if [ -n "''${FORGEJO_AUTH_ID}" ]; then + echo "PRERUN-LDAP: Authentication source exists, updating..." + ACTION="update-ldap" + EXTRA_ARG="--id $FORGEJO_AUTH_ID" + else + echo "PRERUN-LDAP: Authentication source does not exists, adding..." + ACTION="add-ldap" + fi + + BIND_USERPASS="$(cat $CREDENTIALS_DIRECTORY/lldap-bind-user-pass)" + + ${pkgs.forgejo}/bin/gitea \ + --work-path '${config.mine.zfsMounts."rpool/safe/svcs/forgejo"}' \ + admin auth "$ACTION" $EXTRA_ARG \ + --name "$FORGEJO_AUTH_NAME" \ + --active \ + --security-protocol unencrypted \ + --skip-tls-verify \ + --host ${config.mine.settings.ldap.host} \ + --port ${builtins.toString config.mine.settings.ldap.port} \ + --bind-dn "${config.mine.settings.ldap.bind_dn}" \ + --bind-password "$BIND_USERPASS" \ + --user-filter '(&${config.mine.settings.ldap.user_filter}(|(${config.mine.settings.ldap.attr.uid}=%[1]s)(${config.mine.settings.ldap.attr.email}=%[1]s)))' \ + --admin-filter '${config.mine.settings.ldap.admin_filter}' \ + --username-attribute ${config.mine.settings.ldap.attr.uid} \ + --firstname-attribute ${config.mine.settings.ldap.attr.firstname} \ + --surname-attribute ${config.mine.settings.ldap.attr.lastname} \ + --email-attribute ${config.mine.settings.ldap.attr.email} \ + --avatar-attribute ${config.mine.settings.ldap.attr.avatar} \ + --synchronize-users \ + --user-search-base '${config.mine.settings.ldap.search_base}' \ + + echo "PRERUN-LDAP: Finished adding/updating..." + ''; + + + scriptAddOAuth = pkgs.writeShellScript "forgejo-add-update-oauth.sh" '' + #!/usr/bin/env sh + FORGEJO_WORK_PATH="${config.services.forgejo.stateDir}" + FORGEJO_AUTH_NAME="${AUTHELIA_AUTH_NAME}" + + # get auth id if any + FORGEJO_AUTH_ID=$(gitea --work-path "$FORGEJO_WORK_PATH" admin auth list | grep "$FORGEJO_AUTH_NAME" | cut -d$'\t' -f1) + + ACTION="" + EXTRA_ARG="" + if [ -n "''${FORGEJO_AUTH_ID}" ]; then + echo "PRERUN-AUTH: Authentication source exists, updating..." + ACTION="update-oauth" + EXTRA_ARG="--id $FORGEJO_AUTH_ID" + else + echo "PRERUN-AUTH: Authentication source does not exists, adding..." + ACTION="add-oauth" + fi + + SECRET="$(cat $CREDENTIALS_DIRECTORY/authelia-secret)" + + ${pkgs.forgejo}/bin/gitea \ + --work-path '${config.mine.zfsMounts."rpool/safe/svcs/forgejo"}' \ + admin auth "$ACTION" $EXTRA_ARG \ + --name "$FORGEJO_AUTH_NAME" \ + --provider openidConnect \ + --key forgejo \ + --secret "$SECRET" \ + --auto-discover-url "https://${config.mine.settings.authelia.domain}/.well-known/openid-configuration" \ + --skip-local-2fa true \ + --scopes "email" \ + --scopes "profile" \ + + echo "PRERUN-AUTH: Finished adding/updating..." + ''; +in { + + systemd.services.forgejo.preStart = lib.mkAfter '' + ${scriptAddLDAPAuth} + ${scriptAddOAuth} + ''; + + systemd.services.forgejo.serviceConfig.LoadCredential = [ + "authelia-secret:${config.age.secrets.forgejo-authelia-secret.path}" + "lldap-bind-user-pass:${config.age.secrets.lldap-bind-user-pass.path}" + ]; + + + # example configuration for forgejo. Should live in forgejo.nix if needed + services.authelia.instances.main.settings.identity_providers.oidc.clients = [{ + id = "forgejo"; + description = "Forgejo"; + + # authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986 + secret = "$pbkdf2-sha512$310000$cOGtLwMHyfugAJCIiUUjfQ$ao7zC8QB1m8aTGNf1dxYbRAPivZ0G1eaJ4bNFVfJiTFZX06U5baBjT0emvoaeFHXMFbYHzorb2/8vxnY/D0b5Q"; + + public = false; + # authorization_policy = "one_factor"; + redirect_uris = [ "https://${config.mine.settings.forgejo.domain}/user/oauth2/${AUTHELIA_AUTH_NAME}/callback" ]; + scopes = [ + "openid" + "email" + "profile" + ]; + + userinfo_signing_algorithm = "none"; + }]; +} diff --git a/machines/gerd/services/forgejo/default.nix b/machines/gerd/services/forgejo/default.nix new file mode 100644 index 0000000..8374682 --- /dev/null +++ b/machines/gerd/services/forgejo/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./forgejo.nix + ./auth_sources.nix + ]; +} diff --git a/machines/gerd/services/forgejo/forgejo.nix b/machines/gerd/services/forgejo/forgejo.nix new file mode 100644 index 0000000..3cb78f1 --- /dev/null +++ b/machines/gerd/services/forgejo/forgejo.nix @@ -0,0 +1,53 @@ +{ config, lib, pkgs, ... }: + +let + svc_domain = "git.${config.mine.settings.domain}"; + +in { + services.forgejo = { + enable = true; + + package = pkgs.forgejo.overrideAttrs (old: { + patches = old.patches ++ [ + ./patches/signin-template.patch + ./patches/link-accounts-template.patch + ]; + }); + + stateDir = config.mine.zfsMounts."rpool/safe/svcs/forgejo"; + + settings = { + server = { + DOMAIN = svc_domain; + ROOT_URL = "https://${svc_domain}"; + HTTPPORT = 3000; + }; + + # sync ldap and forgejo + "cron.sync_external_users" = { + RUN_AT_START = true; + SCHEDULE = "@every 15m"; + UPDATE_EXISTING = true; + }; + + # disable registration, only account linking is possible + service.DISABLE_REGISTRATION = true; + }; + }; + + # TODO(eyJhb): remove after our ban expires (and nginx config) + # already issued for this exact set of domains in the last 168 hours: git.fricloud.dk, retry after 2024-08-10T01:34:44Z + security.acme.certs."git.fricloud.dk".extraDomainNames = [ "git2.fricloud.dk" ]; + + services.nginx.virtualHosts."${svc_domain}" = { + forceSSL = true; + enableACME = true; + extraConfig = '' + client_max_body_size 512M; + ''; + locations."/".proxyPass = "http://localhost:${builtins.toString config.services.forgejo.settings.server.HTTPPORT}"; + }; + + # settings + mine.settings.forgejo.domain = svc_domain; +} diff --git a/machines/gerd/services/forgejo/patches/link-accounts-template.patch b/machines/gerd/services/forgejo/patches/link-accounts-template.patch new file mode 100644 index 0000000..4e56395 --- /dev/null +++ b/machines/gerd/services/forgejo/patches/link-accounts-template.patch @@ -0,0 +1,18 @@ +diff --git a/templates/user/auth/link_account.tmpl b/templates/user/auth/link_account.tmpl +index 8dd49ccd60..8cdce5e1ad 100644 +--- a/templates/user/auth/link_account.tmpl ++++ b/templates/user/auth/link_account.tmpl +@@ -17,11 +17,11 @@ + +