authelia: household group; guildhall invite links
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
791a3bdf34
commit
782a1c96a6
6 changed files with 502 additions and 8 deletions
|
|
@ -1,8 +1,28 @@
|
|||
# services/authelia.nix — Native Authelia SSO
|
||||
# Secrets live in /var/secrets/authelia (root:authelia-main, 640) — see readme.
|
||||
#
|
||||
# Users live in /var/lib/authelia-users so guildhall-join (services/
|
||||
# guildhall-join.nix) can add invited players; Authelia only reads it and
|
||||
# reloads on change. Groups decide reach: `household` gets the shared home
|
||||
# sites, `guildhall` gets the game and nothing else.
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
admin = [ "user:fred" ];
|
||||
household = [ "group:household" ];
|
||||
usersDir = "/var/lib/authelia-users";
|
||||
usersFile = "${usersDir}/users_database.yml";
|
||||
|
||||
# One-time move out of Authelia's private state dir, then the same
|
||||
# ownership on every start: guildhall-join writes, authelia-users reads.
|
||||
prepareUsers = pkgs.writeShellScript "authelia-users-prepare" ''
|
||||
set -eu
|
||||
${pkgs.coreutils}/bin/install -d -m 0750 -o guildhall-join -g authelia-users ${usersDir}
|
||||
if [ ! -e ${usersFile} ]; then
|
||||
${pkgs.coreutils}/bin/cp /var/lib/authelia-main/users_database.yml ${usersFile}
|
||||
fi
|
||||
${pkgs.coreutils}/bin/chown guildhall-join:authelia-users ${usersFile}
|
||||
${pkgs.coreutils}/bin/chmod 0640 ${usersFile}
|
||||
'';
|
||||
in
|
||||
{
|
||||
config = lib.mkIf (config.networking.hostName == "FredOS-Mediaserver") {
|
||||
|
|
@ -25,15 +45,18 @@ in
|
|||
format = "text";
|
||||
};
|
||||
|
||||
authentication_backend.file.path = "/var/lib/authelia-main/users_database.yml";
|
||||
authentication_backend.file = {
|
||||
path = usersFile;
|
||||
watch = true;
|
||||
};
|
||||
|
||||
access_control = {
|
||||
default_policy = "deny";
|
||||
# Admin tools are fred-only (`admin`); any other account, i.e. kayla,
|
||||
# only reaches the shared household sites.
|
||||
# Admin tools are fred-only (`admin`), the shared home sites need
|
||||
# the household group, and invited players only reach the game.
|
||||
rules = [
|
||||
{ domain = "frigate.nordhammer.it"; policy = "one_factor"; }
|
||||
{ domain = "camera.nordhammer.it"; policy = "one_factor"; }
|
||||
{ domain = "frigate.nordhammer.it"; policy = "one_factor"; subject = household; }
|
||||
{ domain = "camera.nordhammer.it"; policy = "one_factor"; subject = household; }
|
||||
# { domain = "7dtd.nordhammer.it"; policy = "one_factor"; } # 7DTD disabled
|
||||
{ domain = "adguard.nordhammer.it"; policy = "one_factor"; subject = admin; }
|
||||
{ domain = "router.nordhammer.it"; policy = "one_factor"; subject = admin; }
|
||||
|
|
@ -46,9 +69,9 @@ in
|
|||
{ domain = "shelfarr.nordhammer.it"; policy = "one_factor"; subject = admin; }
|
||||
{ domain = "sabnzbd.nordhammer.it"; policy = "one_factor"; subject = admin; }
|
||||
{ domain = "code.nordhammer.it"; policy = "one_factor"; subject = admin; }
|
||||
{ domain = "reddit.nordhammer.it"; policy = "one_factor"; }
|
||||
{ domain = "reddit.nordhammer.it"; policy = "one_factor"; subject = household; }
|
||||
{ domain = "panel.nordhammer.it"; policy = "one_factor"; subject = admin; }
|
||||
{ domain = "stardew.nordhammer.it"; policy = "one_factor"; }
|
||||
{ domain = "stardew.nordhammer.it"; policy = "one_factor"; subject = household; }
|
||||
{ domain = "guildhall.nordhammer.it"; policy = "one_factor"; }
|
||||
# Health data: only the two people the app knows about.
|
||||
{ domain = "flowtrack.nordhammer.it"; policy = "one_factor"; subject = [ "user:kayla" "user:fred" ]; }
|
||||
|
|
@ -70,5 +93,8 @@ in
|
|||
notifier.filesystem.filename = "/var/lib/authelia-main/notification.txt";
|
||||
};
|
||||
};
|
||||
|
||||
# First, before the module's validate-config pre-start.
|
||||
systemd.services.authelia-main.serviceConfig.ExecStartPre = lib.mkBefore [ "+${prepareUsers}" ];
|
||||
};
|
||||
}
|
||||
|
|
|
|||
77
services/guildhall-join.nix
Normal file
77
services/guildhall-join.nix
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# services/guildhall-join.nix — invite links that create Guildhall accounts.
|
||||
#
|
||||
# guildhall-invite [note] print a one-time link, valid for a week
|
||||
# guildhall-invite list open, used and expired invites
|
||||
# guildhall-invite revoke ID cancel one
|
||||
#
|
||||
# The link opens guildhall.nordhammer.it/join/<token>, the one path nginx
|
||||
# serves without Authelia. The page appends the new user, in the `guildhall`
|
||||
# group only, to Authelia's users file (see services/authelia.nix), which
|
||||
# Authelia reloads on change. The service shares a dedicated authelia-users
|
||||
# group with Authelia rather than authelia-main, which would also open
|
||||
# Authelia's secrets.
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
port = 8099;
|
||||
stateDir = "/var/lib/guildhall-join";
|
||||
pythonEnv = pkgs.python3.withPackages (ps: [ ps.pyyaml ps.argon2-cffi ]);
|
||||
script = ../scripts/guildhall-join.py;
|
||||
environment = {
|
||||
GUILDHALL_JOIN_STATE = stateDir;
|
||||
GUILDHALL_JOIN_USERS = "/var/lib/authelia-users/users_database.yml";
|
||||
GUILDHALL_JOIN_SITE = "https://guildhall.nordhammer.it";
|
||||
GUILDHALL_JOIN_PORT = toString port;
|
||||
};
|
||||
|
||||
invite = pkgs.writeShellScriptBin "guildhall-invite" ''
|
||||
case "''${1:-}" in
|
||||
list|revoke) ;;
|
||||
*) set -- invite "$@" ;;
|
||||
esac
|
||||
exec /run/wrappers/bin/sudo -u guildhall-join ${pkgs.coreutils}/bin/env \
|
||||
${lib.concatStringsSep " " (lib.mapAttrsToList (k: v: "${k}=${lib.escapeShellArg v}") environment)} \
|
||||
${pythonEnv}/bin/python3 ${script} "$@"
|
||||
'';
|
||||
in
|
||||
{
|
||||
config = lib.mkIf (config.networking.hostName == "FredOS-Mediaserver") {
|
||||
users.groups.authelia-users = { };
|
||||
users.groups.guildhall-join = { };
|
||||
users.users.guildhall-join = {
|
||||
isSystemUser = true;
|
||||
group = "guildhall-join";
|
||||
extraGroups = [ "authelia-users" ];
|
||||
description = "Guildhall invite page";
|
||||
};
|
||||
users.users.authelia-main.extraGroups = [ "authelia-users" ];
|
||||
|
||||
systemd.tmpfiles.rules = [ "d ${stateDir} 0700 guildhall-join guildhall-join -" ];
|
||||
|
||||
systemd.services.guildhall-join = {
|
||||
description = "Guildhall invite page";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" "authelia-main.service" ];
|
||||
inherit environment;
|
||||
serviceConfig = {
|
||||
ExecStart = "${pythonEnv}/bin/python3 ${script} serve";
|
||||
User = "guildhall-join";
|
||||
Group = "guildhall-join";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 3;
|
||||
UMask = "0077";
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
|
||||
ReadWritePaths = [ stateDir "/var/lib/authelia-users" ];
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [ invite ];
|
||||
};
|
||||
}
|
||||
|
|
@ -211,11 +211,13 @@ in
|
|||
'';
|
||||
};
|
||||
# Co-op idle game. Players are keyed on Remote-User, so nginx must
|
||||
# always overwrite it with the Authelia identity.
|
||||
# always overwrite it with the Authelia identity. /join/ is the one
|
||||
# public path: invite links that create accounts (guildhall-join.nix).
|
||||
"guildhall.nordhammer.it" = lib.recursiveUpdate (protectedProxy 8098) {
|
||||
locations."/".extraConfig = autheliaAuthConfig + ''
|
||||
proxy_set_header Remote-User $user;
|
||||
'';
|
||||
locations."/join/".proxyPass = "http://127.0.0.1:8099";
|
||||
};
|
||||
|
||||
# Pelican game panel. Can't turn off its own login (no such option
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue