gerd.forgejo: now uses authelia for authentication + patches for signin
This commit is contained in:
parent
d459fa895e
commit
5d94967c48
11 changed files with 243 additions and 118 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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}";
|
||||
};
|
||||
}
|
119
machines/gerd/services/forgejo/auth_sources.nix
Normal file
119
machines/gerd/services/forgejo/auth_sources.nix
Normal file
|
@ -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";
|
||||
}];
|
||||
}
|
6
machines/gerd/services/forgejo/default.nix
Normal file
6
machines/gerd/services/forgejo/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./forgejo.nix
|
||||
./auth_sources.nix
|
||||
];
|
||||
}
|
53
machines/gerd/services/forgejo/forgejo.nix
Normal file
53
machines/gerd/services/forgejo/forgejo.nix
Normal file
|
@ -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;
|
||||
}
|
|
@ -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 @@
|
||||
</overflow-menu>
|
||||
<div class="ui middle very relaxed page grid">
|
||||
<div class="column">
|
||||
- <div class="ui tab {{if not .user_exists}}active{{end}}"
|
||||
+ <div class="ui tab"
|
||||
data-tab="auth-link-signup-tab">
|
||||
{{template "user/auth/signup_inner" .}}
|
||||
</div>
|
||||
- <div class="ui tab {{if .user_exists}}active{{end}}"
|
||||
+ <div class="ui tab active"
|
||||
data-tab="auth-link-signin-tab">
|
||||
<div class="ui user signin container icon">
|
||||
{{template "user/auth/signin_inner" .}}
|
20
machines/gerd/services/forgejo/patches/signin-template.patch
Normal file
20
machines/gerd/services/forgejo/patches/signin-template.patch
Normal file
|
@ -0,0 +1,20 @@
|
|||
diff --git a/templates/user/auth/signin_inner.tmpl b/templates/user/auth/signin_inner.tmpl
|
||||
index 9872096fbc..1076f90326 100644
|
||||
--- a/templates/user/auth/signin_inner.tmpl
|
||||
+++ b/templates/user/auth/signin_inner.tmpl
|
||||
@@ -10,6 +10,7 @@
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
<form class="ui form tw-max-w-2xl tw-m-auto" action="{{.SignInLink}}" method="post">
|
||||
+ <div {{if not .LinkAccountMode}}style="display:none;"{{end}}>
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="required field {{if and (.Err_UserName) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}">
|
||||
<label for="user_name">{{ctx.Locale.Tr "home.uname_holder"}}</label>
|
||||
@@ -53,6 +54,7 @@
|
||||
<div class="divider divider-text">
|
||||
{{ctx.Locale.Tr "sign_in_or"}}
|
||||
</div>
|
||||
+ </div>
|
||||
<div id="oauth2-login-navigator" class="tw-py-1">
|
||||
<div class="tw-flex tw-flex-col tw-justify-center">
|
||||
<div id="oauth2-login-navigator-inner" class="tw-flex tw-flex-col tw-flex-wrap tw-items-center tw-gap-2">
|
|
@ -21,6 +21,9 @@
|
|||
# mumble
|
||||
murmur-env.file = ./murmur/env.age;
|
||||
murmur-superpassword.file = ./murmur/superpassword.age;
|
||||
|
||||
# forgejo
|
||||
forgejo-authelia-secret.file = ./forgejo/authelia-secret.age;
|
||||
};
|
||||
|
||||
users.groups.secrets-lldap-bind-user-pass = {};
|
||||
|
|
10
secrets/forgejo/authelia-secret.age
Normal file
10
secrets/forgejo/authelia-secret.age
Normal file
|
@ -0,0 +1,10 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 QSDXqg 6QDsf2ACEhUdb2IUxDaILcvoPLPdpXupn7DDTQCREWA
|
||||
8VYqwj6UoIee6DHG+bF3lHnY+NxLP8KkjjxynSiEUEk
|
||||
-> ssh-ed25519 n8n9DQ wAIhE1M0sMi+0tdc2fZDFzLJLlaZkhZOXIEkB2lm3UE
|
||||
iG5tvWLkYfv/klmc0LjUn+96RuYTRUrLbMpPicpVchc
|
||||
-> ssh-ed25519 BTp6UA GSOxjXyCvjwg/jS3pG3gegh9jcYbVHy3y4v/dUM7plQ
|
||||
ItU5OQJswLZ3nCpfUcLMhkdEVF6Iu+lPP0qGj9MU7h0
|
||||
--- ONOkuJRp+quOeMUJ6kf+j4Bweks4FAGurAE3xgk3wIw
|
||||
ðà7‡h#p€<>·ŒØ˜ÿ,ŒÙîúà‹SV|^8"‰)¢š§†‡è]ýbiàڡܶġTWêi Aÿ
|
||||
¹\›ò¾%X¨v
«
4Fè”9{<7B>FY’<59>"‹Ä5`wZ¬¼¸MÓ$eý='€a
|
|
@ -25,4 +25,7 @@ in
|
|||
# mumble
|
||||
"murmur/env.age".publicKeys = defaultAccess;
|
||||
"murmur/superpassword.age".publicKeys = defaultAccess;
|
||||
|
||||
# forgejo
|
||||
"forgejo/authelia-secret.age".publicKeys = defaultAccess;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue