feat: add initial oauth2-proxy and freshrss oidc

This commit is contained in:
Leon Schwarzäugl 2025-06-09 21:20:40 +02:00
parent 9d10005e35
commit 7e11641fe7
Signed by: swarsel
GPG key ID: 26A54C31F2A4FD84
5 changed files with 1166 additions and 556 deletions

View file

@ -7518,7 +7518,7 @@ Here we just define some aliases for rebuilding the system, and we allow some in
}
#+end_src
**** paperless
**** paperless (tika, gotenberg)
:PROPERTIES:
:CUSTOM_ID: h:89638fb5-0593-4420-9567-f85f0223e341
:END:
@ -8254,6 +8254,8 @@ FreshRSS is a more 'classical' RSS aggregator that I can just host as a distinct
It serves both a Greader API at https://signpost.swarsel.win/api/greader.php, as well as a Fever API at https://signpost.swarsel.win/api/fever.php.
I am using this with CapyReader on my phone, set it up as a FreshRSS account with Server URL =https://signpost.swarsel.win/api/greader.php
#+begin_src nix :tangle modules/nixos/server/freshrss.nix
{ lib, config, ... }:
{
@ -8268,24 +8270,91 @@ It serves both a Greader API at https://signpost.swarsel.win/api/greader.php, as
users.groups.freshrss = { };
sops.secrets.fresh = { owner = "freshrss"; };
sops = {
secrets = {
fresh = { owner = "freshrss"; };
"kanidm-freshrss-client" = { owner = "freshrss"; group = "freshrss"; mode = "0440"; };
"oidc-crypto-key" = { owner = "freshrss"; group = "freshrss"; mode = "0440"; };
};
# templates = {
# "freshrss-env" = {
# content = ''
# DATA_PATH=${config.services.freshrss.dataDir}
# OIDC_ENABLED=1
# OIDC_PROVIDER_METADATA_URL=https://sso.swarsel.win/.well-known/openid-configuration
# OIDC_CLIENT_ID=freshrss
# OIDC_CLIENT_SECRET=${config.sops.placeholder.kanidm-freshrss-client}
# OIDC_CLIENT_CRYPTO_KEY=${config.sops.placeholder.oidc-crypto-key}
# OIDC_REMOTE_USER_CLAIM=preferred_username
# OIDC_SCOPES=openid groups email profile
# OIDC_X_FORWARDED_HEADERS=X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto
# '';
# owner = "freshrss";
# group = "freshrss";
# mode = "0440";
# };
# };
};
services.freshrss = {
enable = true;
virtualHost = "signpost.swarsel.win";
baseUrl = "https://signpost.swarsel.win";
# authType = "none";
authType = "none";
dataDir = "/Vault/data/tt-rss";
defaultUser = "Swarsel";
passwordFile = config.sops.secrets.fresh.path;
};
# systemd.services.freshrss-config.serviceConfig.EnvironmentFile = [
# config.sops.templates.freshrss-env.path
# ];
services.nginx = {
virtualHosts = {
"signpost.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
extraConfig = ''
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# pass information via X-User and X-Email headers to backend,
# requires running with --set-xauthrequest flag (done by NixOS)
auth_request_set $user $upstream_http_x_auth_request_preferred_username;
# Set the email to our own domain in case user change their mail
auth_request_set $email "''${upstream_http_x_auth_request_preferred_username}@swarsel.win";
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
# if you enabled --cookie-refresh, this is needed for it to work with auth_request
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
'';
};
"/oauth2/" = {
proxyPass = "http://oauth2-proxy";
extraConfig = ''
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
'';
};
"= /oauth2/auth" = {
proxyPass = "http://oauth2-proxy/oauth2/auth";
extraConfig = ''
internal;
proxy_set_header X-Scheme $scheme;
# nginx auth_request includes headers but not body
proxy_set_header Content-Length "";
proxy_pass_request_body off;
'';
};
};
};
};
};
@ -8495,7 +8564,7 @@ It serves both a Greader API at https://signpost.swarsel.win/api/greader.php, as
}
#+end_src
**** kanidm
**** IDM (kanidm + oauth2-proxy)
The forgejo configuration is a little broken and will show a 500 error when signing in through kanidm. However, when pressing back and refreshing the page, I am logged in. Currently I cannot be bothered to fix this.
@ -8509,7 +8578,9 @@ To get other URLs (token, etc.), use https://<kanidmDomain>/oauth2/openid/<clien
let
certsSopsFile = self + /secrets/certs/secrets.yaml;
kanidmDomain = "sso.swarsel.win";
oauth2ProxyDomain = "soauth.swarsel.win";
kanidmPort = 8300;
oauth2ProxyPort = 3004;
in
{
options.swarselsystems.modules.server.kanidm = lib.mkEnableOption "enable kanidm on server";
@ -8522,7 +8593,9 @@ To get other URLs (token, etc.), use https://<kanidmDomain>/oauth2/openid/<clien
users.groups.kanidm = { };
sops.secrets = {
sops = {
secrets = {
"oauth2-cookie-secret" = { owner = "oauth2-proxy"; group = "oauth2-proxy"; mode = "0440"; };
"kanidm-self-signed-crt" = { sopsFile = certsSopsFile; owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-self-signed-key" = { sopsFile = certsSopsFile; owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-admin-pw" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
@ -8532,9 +8605,26 @@ To get other URLs (token, etc.), use https://<kanidmDomain>/oauth2/openid/<clien
"kanidm-forgejo" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-grafana" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-nextcloud" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-freshrss" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-oauth2-proxy" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-oauth2-proxy-client" = { owner = "oauth2-proxy"; group = "oauth2-proxy"; mode = "0440"; };
};
services.kanidm = {
templates = {
"kanidm-oauth2-proxy-client-env" = {
content = ''
OAUTH2_PROXY_CLIENT_SECRET="${config.sops.placeholder.kanidm-oauth2-proxy-client}"
OAUTH2_PROXY_COOKIE_SECRET=${config.sops.placeholder.oauth2-cookie-secret}
'';
owner = "oauth2-proxy";
group = "oauth2-proxy";
mode = "0440";
};
};
};
services = {
kanidm = {
package = pkgs.kanidmWithSecretProvisioning;
enableServer = true;
serverSettings = {
@ -8566,6 +8656,8 @@ To get other URLs (token, etc.), use https://<kanidmDomain>/oauth2/openid/<clien
"grafana.server-admins" = { };
"nextcloud.access" = { };
"nextcloud.admins" = { };
"navidrome.access" = { };
"freshrss.access" = { };
};
persons = {
swarsel = {
@ -8578,6 +8670,8 @@ To get other URLs (token, etc.), use https://<kanidmDomain>/oauth2/openid/<clien
"grafana.access"
"forgejo.access"
"nextcloud.access"
"freshrss.access"
"navidrome.access"
];
displayName = "Swarsel";
};
@ -8672,14 +8766,107 @@ To get other URLs (token, etc.), use https://<kanidmDomain>/oauth2/openid/<clien
};
};
};
# freshrss = {
# displayName = "FreshRSS";
# originUrl = "https://signpost.swarsel.win/apps/sociallogin/custom_oidc/kanidm";
# originLanding = "https://signpost.swarsel.win/";
# basicSecretFile = config.sops.secrets.kanidm-freshrss.path;
# allowInsecureClientDisablePkce = true;
# scopeMaps."freshrss.access" = [
# "openid"
# "email"
# "profile"
# ];
# preferShortUsername = true;
# };
oauth2-proxy = {
displayName = "Oauth2-Proxy";
originUrl = "https://${oauth2ProxyDomain}/oauth2/callback";
originLanding = "https://${oauth2ProxyDomain}/";
basicSecretFile = config.sops.secrets.kanidm-oauth2-proxy.path;
scopeMaps."freshrss.access" = [
"openid"
"email"
"profile"
];
scopeMaps."navidrome.access" = [
"openid"
"email"
"profile"
];
preferShortUsername = true;
claimMaps.groups = {
joinType = "array";
valuesByGroup."freshrss.access" = [ "ttrss_access" ];
valuesByGroup."navidrome.access" = [ "navidrome_access" ];
};
};
};
};
};
};
oauth2-proxy = {
enable = true;
cookie = {
domain = ".swarsel.win";
secure = true;
expire = "900m";
secret = null; # set by service EnvironmentFile
};
clientSecret = null; # set by service EnvironmentFile
reverseProxy = true;
httpAddress = "0.0.0.0:${builtins.toString oauth2ProxyPort}";
redirectURL = "https://${oauth2ProxyDomain}/oauth2/callback";
setXauthrequest = true;
extraConfig = {
code-challenge-method = "S256";
whitelist-domain = ".swarsel.win";
set-authorization-header = true;
pass-access-token = true;
skip-jwt-bearer-tokens = true;
upstream = "static://202";
oidc-issuer-url = "https://${kanidmDomain}/oauth2/openid/oauth2-proxy";
provider-display-name = "Kanidm";
};
provider = "oidc";
scope = "openid email";
loginURL = "https://${kanidmDomain}/ui/oauth2";
redeemURL = "https://${kanidmDomain}/oauth2/token";
validateURL = "https://${kanidmDomain}/oauth2/openid/oauth2-proxy/userinfo";
clientID = "oauth2-proxy";
email.domains = [ "*" ];
};
};
systemd.services.kanidm.serviceConfig.RestartSec = "30";
systemd.services = {
kanidm.serviceConfig.RestartSec = "30";
oauth2-proxy = {
after = [ "kanidm.service" ];
serviceConfig = {
RuntimeDirectory = "oauth2-proxy";
RuntimeDirectoryMode = "0750";
UMask = "007"; # TODO remove once https://github.com/oauth2-proxy/oauth2-proxy/issues/2141 is fixed
RestartSec = "60"; # Retry every minute
EnvironmentFile = [
config.sops.templates.kanidm-oauth2-proxy-client-env.path
];
};
};
};
services.nginx = {
upstreams = {
kanidm = {
servers = {
"192.168.1.2:${builtins.toString kanidmPort}" = { };
};
};
oauth2-proxy = {
servers = {
"192.168.1.2:${builtins.toString oauth2ProxyPort}" = { };
};
};
};
virtualHosts = {
"${kanidmDomain}" = {
enableACME = true;
@ -8687,13 +8874,27 @@ To get other URLs (token, etc.), use https://<kanidmDomain>/oauth2/openid/<clien
acmeRoot = null;
locations = {
"/" = {
proxyPass = "https://localhost:${toString kanidmPort}";
proxyPass = "https://kanidm";
};
};
extraConfig = ''
proxy_ssl_verify off;
'';
};
"${oauth2ProxyDomain}" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://oauth2-proxy";
};
};
extraConfig = ''
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
'';
};
};
};
};

View file

@ -3,7 +3,7 @@
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2025-06-09 Mo 19:11 -->
<!-- 2025-06-10 Di 00:09 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>SwarselSystems: NixOS + Emacs Configuration</title>
@ -263,9 +263,9 @@
<li><a href="#h:7056b9a0-f38b-4bca-b2ba-ab34e2d73493">3.1.4.3. Home-manager only (default non-NixOS)</a></li>
<li><a href="#h:e1498bef-ec67-483d-bf02-76264e30be8e">3.1.4.4. ChaosTheatre (Demo Physical/VM)</a>
<ul>
<li><a href="#orgb2b8cf0">3.1.4.4.1. Main configuration</a></li>
<li><a href="#org68ec049">3.1.4.4.2. NixOS dummy options configuration</a></li>
<li><a href="#org993be50">3.1.4.4.3. home-manager dummy options configuration</a></li>
<li><a href="#org8856bb9">3.1.4.4.1. Main configuration</a></li>
<li><a href="#orga7b81ea">3.1.4.4.2. NixOS dummy options configuration</a></li>
<li><a href="#orga117e22">3.1.4.4.3. home-manager dummy options configuration</a></li>
</ul>
</li>
</ul>
@ -305,7 +305,7 @@
<li><a href="#h:36d6c17c-6d91-4297-b76d-9d7feab6c1a0">3.2.1.27. fhs</a></li>
<li><a href="#h:814d5e7f-4b95-412d-b246-33f888514ec6">3.2.1.28. swarsel-displaypower</a></li>
<li><a href="#h:799579f3-ddd3-4f76-928a-a8c665980476">3.2.1.29. swarsel-mgba</a></li>
<li><a href="#org22d3ae9">3.2.1.30. sshrm</a></li>
<li><a href="#org32a7d1b">3.2.1.30. sshrm</a></li>
</ul>
</li>
<li><a href="#h:5e3e21e0-57af-4dad-b32f-6400af9b7aab">3.2.2. Overlays (additions, overrides, nixpkgs-stable)</a></li>
@ -313,28 +313,28 @@
<ul>
<li><a href="#h:14e68518-8ec7-48ec-b208-0e3d6d49954d">3.2.3.1. NixOS</a>
<ul>
<li><a href="#orgb76e417">3.2.3.1.1. Personal</a></li>
<li><a href="#orgeebc200">3.2.3.1.2. Chaostheatre</a></li>
<li><a href="#org3a2d170">3.2.3.1.3. toto</a></li>
<li><a href="#orgd20da99">3.2.3.1.4. Work</a></li>
<li><a href="#orgd4434b7">3.2.3.1.5. Framework</a></li>
<li><a href="#org6eab996">3.2.3.1.6. AMD CPU</a></li>
<li><a href="#orgbf1e084">3.2.3.1.7. AMD GPU</a></li>
<li><a href="#org0f3b68a">3.2.3.1.8. Hibernation</a></li>
<li><a href="#org33fa56c">3.2.3.1.9. BTRFS</a></li>
<li><a href="#org3ce30da">3.2.3.1.10. Local Server</a></li>
<li><a href="#org7998cbb">3.2.3.1.11. OCI Sync Server</a></li>
<li><a href="#org5dddcad">3.2.3.1.1. Personal</a></li>
<li><a href="#org6d64461">3.2.3.1.2. Chaostheatre</a></li>
<li><a href="#orgc13e5da">3.2.3.1.3. toto</a></li>
<li><a href="#org012ee73">3.2.3.1.4. Work</a></li>
<li><a href="#org06d9d82">3.2.3.1.5. Framework</a></li>
<li><a href="#orgca62b3f">3.2.3.1.6. AMD CPU</a></li>
<li><a href="#org8c9b483">3.2.3.1.7. AMD GPU</a></li>
<li><a href="#org4f2e856">3.2.3.1.8. Hibernation</a></li>
<li><a href="#org5fb39b7">3.2.3.1.9. BTRFS</a></li>
<li><a href="#org71ec228">3.2.3.1.10. Local Server</a></li>
<li><a href="#orga1d079d">3.2.3.1.11. OCI Sync Server</a></li>
</ul>
</li>
<li><a href="#h:ced5841f-c088-4d88-b3a1-7d62aad8837b">3.2.3.2. home-manager</a>
<ul>
<li><a href="#org3b47a07">3.2.3.2.1. Personal</a></li>
<li><a href="#orgb69bb17">3.2.3.2.2. Chaostheatre</a></li>
<li><a href="#org4e5683b">3.2.3.2.3. toto</a></li>
<li><a href="#org514d330">3.2.3.2.4. Work</a></li>
<li><a href="#orgf448b84">3.2.3.2.5. Framework</a></li>
<li><a href="#org093c33e">3.2.3.2.6. Darwin</a></li>
<li><a href="#org7978a81">3.2.3.2.7. Local Server</a></li>
<li><a href="#org774bfc8">3.2.3.2.1. Personal</a></li>
<li><a href="#orgc18f467">3.2.3.2.2. Chaostheatre</a></li>
<li><a href="#orgc7430a9">3.2.3.2.3. toto</a></li>
<li><a href="#orgd753a03">3.2.3.2.4. Work</a></li>
<li><a href="#org8147a26">3.2.3.2.5. Framework</a></li>
<li><a href="#org0e9f70a">3.2.3.2.6. Darwin</a></li>
<li><a href="#orgeaaa568">3.2.3.2.7. Local Server</a></li>
</ul>
</li>
</ul>
@ -379,7 +379,7 @@
<li><a href="#h:f101daa2-604d-4553-99e2-f64b9c207f51">3.3.1.22.3. enable GVfs</a></li>
<li><a href="#h:08d213d5-a9f4-4309-8635-ba557b01dc7d">3.3.1.22.4. interception-tools: Make CAPS work as ESC/CTRL</a></li>
<li><a href="#h:82fbba41-3a46-4db7-aade-49e4c23fc475">3.3.1.22.5. power-profiles-daemon</a></li>
<li><a href="#org19e1c87">3.3.1.22.6. SwayOSD</a></li>
<li><a href="#org9689642">3.3.1.22.6. SwayOSD</a></li>
</ul>
</li>
<li><a href="#h:7a89b5e3-b700-4167-8b14-2b8172f33936">3.3.1.23. Hardware compatibility settings (Yubikey, Ledger, Keyboards) - udev rules</a>
@ -421,7 +421,7 @@
<li><a href="#h:1e68d84a-8f99-422f-89ac-78f664ac0013">3.3.2.14. matrix</a></li>
<li><a href="#h:d11ad8d5-25d7-4691-b319-61c16ccef715">3.3.2.15. nextcloud</a></li>
<li><a href="#h:33bad8ad-b362-4bf1-8a49-b9df92329aed">3.3.2.16. immich</a></li>
<li><a href="#h:89638fb5-0593-4420-9567-f85f0223e341">3.3.2.17. paperless</a></li>
<li><a href="#h:89638fb5-0593-4420-9567-f85f0223e341">3.3.2.17. paperless (tika, gotenberg)</a></li>
<li><a href="#h:5afeb311-ab86-4029-be53-2160f6d836c3">3.3.2.18. transmission</a></li>
<li><a href="#h:ad2787a2-7b1c-4326-aeff-9d8d6c3f591d">3.3.2.19. syncthing</a></li>
<li><a href="#h:b73ac8bf-b721-4563-9eff-973925c99a39">3.3.2.20. restic</a></li>
@ -431,7 +431,7 @@
<li><a href="#h:9da3df74-6fc5-4ee1-a345-23ab4e8a613d">3.3.2.24. FreshRSS</a></li>
<li><a href="#h:a9965660-4358-4b9a-8c46-d55f28598344">3.3.2.25. forgejo (git server)</a></li>
<li><a href="#h:cb3f6552-7751-4f9a-b4c7-8d8ba5b255c4">3.3.2.26. Anki Sync Server</a></li>
<li><a href="#org9187e63">3.3.2.27. kanidm</a></li>
<li><a href="#org6b2e178">3.3.2.27. IDM (kanidm + oauth2-proxy)</a></li>
</ul>
</li>
<li><a href="#h:ac0cd8b3-06cf-4dca-ba73-6100c8fedb47">3.3.3. Darwin</a>
@ -446,11 +446,11 @@
<li><a href="#h:34db28fb-62f7-4597-a9ff-0de2991a8415">3.3.4.3. VmWare</a></li>
<li><a href="#h:fa8d9ec4-3e22-458a-9239-859cffe7f55c">3.3.4.4. Auto-login</a></li>
<li><a href="#h:5c41c4ee-22ca-405b-9e4f-cc4051634edd">3.3.4.5. nswitch-rcm</a></li>
<li><a href="#org5a82981">3.3.4.6. Framework</a></li>
<li><a href="#orga8a179d">3.3.4.7. AMD CPU</a></li>
<li><a href="#org00ce247">3.3.4.8. AMD GPU</a></li>
<li><a href="#orgf108079">3.3.4.9. Hibernation</a></li>
<li><a href="#org5c280d6">3.3.4.10. BTRFS</a></li>
<li><a href="#orge3ac9e1">3.3.4.6. Framework</a></li>
<li><a href="#org5532d9d">3.3.4.7. AMD CPU</a></li>
<li><a href="#org0dda67c">3.3.4.8. AMD GPU</a></li>
<li><a href="#orge0bde26">3.3.4.9. Hibernation</a></li>
<li><a href="#orgd71adf6">3.3.4.10. BTRFS</a></li>
<li><a href="#h:bbf2ecb6-c8ff-4462-b5d5-d45b28604ddf">3.3.4.11. work</a></li>
<li><a href="#h:3fc1d301-7bae-4678-9085-d12c23eed8ac">3.3.4.12. Minimal Install</a></li>
</ul>
@ -499,7 +499,7 @@
<li><a href="#h:cb812c8a-247c-4ce5-a00c-59332c2f5fb9">3.4.1.29.1. gnome-keyring</a></li>
<li><a href="#h:be6afd89-9e1e-40b6-8542-5c07a0ab780d">3.4.1.29.2. KDE Connect</a></li>
<li><a href="#h:99d05729-df35-4958-9940-3319d6a41359">3.4.1.29.3. Mako</a></li>
<li><a href="#orgdcc7202">3.4.1.29.4. SwayOSD</a></li>
<li><a href="#org87b0218">3.4.1.29.4. SwayOSD</a></li>
<li><a href="#h:1598c90b-f195-41a0-9132-94612edf3586">3.4.1.29.5. yubikey-touch-detector</a></li>
</ul>
</li>
@ -524,7 +524,7 @@
<ul>
<li><a href="#h:84fd7029-ecb6-4131-9333-289982f24ffa">3.4.4.1. Gaming</a></li>
<li><a href="#h:f0b2ea93-94c8-48d8-8d47-6fe58f58e0e6">3.4.4.2. Work</a></li>
<li><a href="#org1fd635e">3.4.4.3. Framework</a></li>
<li><a href="#org3b5d2ad">3.4.4.3. Framework</a></li>
</ul>
</li>
</ul>
@ -702,7 +702,7 @@
<ul>
<li><a href="#h:c1e53aed-fb47-4aff-930c-dc52f3c5dcb8">6.1. Server Emacs config</a></li>
<li><a href="#h:fc64f42f-e7cf-4829-89f6-2d0d58e04f51">6.2. tridactylrc</a></li>
<li><a href="#orgd553dac">6.3. tridactyl theme</a></li>
<li><a href="#org1d84ef9">6.3. tridactyl theme</a></li>
<li><a href="#h:77b1c523-5074-4610-b320-90af95e6134d">6.4. Waybar style.css</a></li>
<li><a href="#h:788937cf-8816-466b-8e57-1b695cb50f52">6.5. justfile</a></li>
</ul>
@ -711,7 +711,7 @@
</div>
</div>
<p>
<b>This file has 64380 words spanning 16957 lines and was last revised on 2025-06-09 19:11:36 +0200.</b>
<b>This file has 65085 words spanning 17158 lines and was last revised on 2025-06-10 00:08:59 +0200.</b>
</p>
<p>
@ -764,7 +764,7 @@ This section defines my Emacs configuration. For a while, I considered to use ry
</p>
<p>
My emacs is built using the emacs-overlay nix flake, which builds a bleeding edge emacs on wayland (pgtk) with utilities like treesitter support. By executing the below source block, the current build setting can be updated at any time, and you can see my most up-to-date build options (last updated: 2025-06-09 19:11:36 +0200)
My emacs is built using the emacs-overlay nix flake, which builds a bleeding edge emacs on wayland (pgtk) with utilities like treesitter support. By executing the below source block, the current build setting can be updated at any time, and you can see my most up-to-date build options (last updated: 2025-06-10 00:08:59 +0200)
</p></li>
</ul>
@ -2885,8 +2885,8 @@ This is just a demo host. It applies all the configuration found in the common p
I also set the <code>WLR_RENDERER_ALLOW_SOFTWARE=1</code> to allow this configuration to run in a virtualized environment. I also enable <code>qemuGuest</code> for a smoother experience when testing on QEMU.
</p>
</div>
<div id="outline-container-orgb2b8cf0" class="outline-6">
<h6 id="orgb2b8cf0"><span class="section-number-6">3.1.4.4.1.</span> Main configuration</h6>
<div id="outline-container-org8856bb9" class="outline-6">
<h6 id="org8856bb9"><span class="section-number-6">3.1.4.4.1.</span> Main configuration</h6>
<div class="outline-text-6" id="text-3-1-4-4-1">
<div class="org-src-container">
<pre class="src src-nix">{ self, inputs, config, pkgs, lib, primaryUser, ... }:
@ -2965,8 +2965,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org68ec049" class="outline-6">
<h6 id="org68ec049"><span class="section-number-6">3.1.4.4.2.</span> NixOS dummy options configuration</h6>
<div id="outline-container-orga7b81ea" class="outline-6">
<h6 id="orga7b81ea"><span class="section-number-6">3.1.4.4.2.</span> NixOS dummy options configuration</h6>
<div class="outline-text-6" id="text-3-1-4-4-2">
<div class="org-src-container">
<pre class="src src-nix">_:
@ -2976,8 +2976,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org993be50" class="outline-6">
<h6 id="org993be50"><span class="section-number-6">3.1.4.4.3.</span> home-manager dummy options configuration</h6>
<div id="outline-container-orga117e22" class="outline-6">
<h6 id="orga117e22"><span class="section-number-6">3.1.4.4.3.</span> home-manager dummy options configuration</h6>
<div class="outline-text-6" id="text-3-1-4-4-3">
<div class="org-src-container">
<pre class="src src-nix">_:
@ -4758,8 +4758,8 @@ appimageTools.wrapType2 {
</div>
</div>
</div>
<div id="outline-container-org22d3ae9" class="outline-5">
<h5 id="org22d3ae9"><span class="section-number-5">3.2.1.30.</span> sshrm</h5>
<div id="outline-container-org32a7d1b" class="outline-5">
<h5 id="org32a7d1b"><span class="section-number-5">3.2.1.30.</span> sshrm</h5>
<div class="outline-text-5" id="text-3-2-1-30">
<p>
This programs simply runs ssh-keygen on the last host that I tried to ssh into. I need this frequently when working with cloud-init usually.
@ -4916,8 +4916,8 @@ in
</pre>
</div>
</div>
<div id="outline-container-orgb76e417" class="outline-6">
<h6 id="orgb76e417"><span class="section-number-6">3.2.3.1.1.</span> Personal</h6>
<div id="outline-container-org5dddcad" class="outline-6">
<h6 id="org5dddcad"><span class="section-number-6">3.2.3.1.1.</span> Personal</h6>
<div class="outline-text-6" id="text-3-2-3-1-1">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -4984,8 +4984,8 @@ in
</div>
</div>
</div>
<div id="outline-container-orgeebc200" class="outline-6">
<h6 id="orgeebc200"><span class="section-number-6">3.2.3.1.2.</span> Chaostheatre</h6>
<div id="outline-container-org6d64461" class="outline-6">
<h6 id="org6d64461"><span class="section-number-6">3.2.3.1.2.</span> Chaostheatre</h6>
<div class="outline-text-6" id="text-3-2-3-1-2">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5049,8 +5049,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org3a2d170" class="outline-6">
<h6 id="org3a2d170"><span class="section-number-6">3.2.3.1.3.</span> toto</h6>
<div id="outline-container-orgc13e5da" class="outline-6">
<h6 id="orgc13e5da"><span class="section-number-6">3.2.3.1.3.</span> toto</h6>
<div class="outline-text-6" id="text-3-2-3-1-3">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5082,8 +5082,8 @@ in
</div>
</div>
</div>
<div id="outline-container-orgd20da99" class="outline-6">
<h6 id="orgd20da99"><span class="section-number-6">3.2.3.1.4.</span> Work</h6>
<div id="outline-container-org012ee73" class="outline-6">
<h6 id="org012ee73"><span class="section-number-6">3.2.3.1.4.</span> Work</h6>
<div class="outline-text-6" id="text-3-2-3-1-4">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5104,8 +5104,8 @@ in
</div>
</div>
</div>
<div id="outline-container-orgd4434b7" class="outline-6">
<h6 id="orgd4434b7"><span class="section-number-6">3.2.3.1.5.</span> Framework</h6>
<div id="outline-container-org06d9d82" class="outline-6">
<h6 id="org06d9d82"><span class="section-number-6">3.2.3.1.5.</span> Framework</h6>
<div class="outline-text-6" id="text-3-2-3-1-5">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5126,8 +5126,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org6eab996" class="outline-6">
<h6 id="org6eab996"><span class="section-number-6">3.2.3.1.6.</span> AMD CPU</h6>
<div id="outline-container-orgca62b3f" class="outline-6">
<h6 id="orgca62b3f"><span class="section-number-6">3.2.3.1.6.</span> AMD CPU</h6>
<div class="outline-text-6" id="text-3-2-3-1-6">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5148,8 +5148,8 @@ in
</div>
</div>
</div>
<div id="outline-container-orgbf1e084" class="outline-6">
<h6 id="orgbf1e084"><span class="section-number-6">3.2.3.1.7.</span> AMD GPU</h6>
<div id="outline-container-org8c9b483" class="outline-6">
<h6 id="org8c9b483"><span class="section-number-6">3.2.3.1.7.</span> AMD GPU</h6>
<div class="outline-text-6" id="text-3-2-3-1-7">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5170,8 +5170,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org0f3b68a" class="outline-6">
<h6 id="org0f3b68a"><span class="section-number-6">3.2.3.1.8.</span> Hibernation</h6>
<div id="outline-container-org4f2e856" class="outline-6">
<h6 id="org4f2e856"><span class="section-number-6">3.2.3.1.8.</span> Hibernation</h6>
<div class="outline-text-6" id="text-3-2-3-1-8">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5192,8 +5192,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org33fa56c" class="outline-6">
<h6 id="org33fa56c"><span class="section-number-6">3.2.3.1.9.</span> BTRFS</h6>
<div id="outline-container-org5fb39b7" class="outline-6">
<h6 id="org5fb39b7"><span class="section-number-6">3.2.3.1.9.</span> BTRFS</h6>
<div class="outline-text-6" id="text-3-2-3-1-9">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5214,8 +5214,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org3ce30da" class="outline-6">
<h6 id="org3ce30da"><span class="section-number-6">3.2.3.1.10.</span> Local Server</h6>
<div id="outline-container-org71ec228" class="outline-6">
<h6 id="org71ec228"><span class="section-number-6">3.2.3.1.10.</span> Local Server</h6>
<div class="outline-text-6" id="text-3-2-3-1-10">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5268,8 +5268,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org7998cbb" class="outline-6">
<h6 id="org7998cbb"><span class="section-number-6">3.2.3.1.11.</span> OCI Sync Server</h6>
<div id="outline-container-orga1d079d" class="outline-6">
<h6 id="orga1d079d"><span class="section-number-6">3.2.3.1.11.</span> OCI Sync Server</h6>
<div class="outline-text-6" id="text-3-2-3-1-11">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5326,8 +5326,8 @@ in
</pre>
</div>
</div>
<div id="outline-container-org3b47a07" class="outline-6">
<h6 id="org3b47a07"><span class="section-number-6">3.2.3.2.1.</span> Personal</h6>
<div id="outline-container-org774bfc8" class="outline-6">
<h6 id="org774bfc8"><span class="section-number-6">3.2.3.2.1.</span> Personal</h6>
<div class="outline-text-6" id="text-3-2-3-2-1">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5384,8 +5384,8 @@ in
</div>
</div>
</div>
<div id="outline-container-orgb69bb17" class="outline-6">
<h6 id="orgb69bb17"><span class="section-number-6">3.2.3.2.2.</span> Chaostheatre</h6>
<div id="outline-container-orgc18f467" class="outline-6">
<h6 id="orgc18f467"><span class="section-number-6">3.2.3.2.2.</span> Chaostheatre</h6>
<div class="outline-text-6" id="text-3-2-3-2-2">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5437,8 +5437,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org4e5683b" class="outline-6">
<h6 id="org4e5683b"><span class="section-number-6">3.2.3.2.3.</span> toto</h6>
<div id="outline-container-orgc7430a9" class="outline-6">
<h6 id="orgc7430a9"><span class="section-number-6">3.2.3.2.3.</span> toto</h6>
<div class="outline-text-6" id="text-3-2-3-2-3">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5458,8 +5458,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org514d330" class="outline-6">
<h6 id="org514d330"><span class="section-number-6">3.2.3.2.4.</span> Work</h6>
<div id="outline-container-orgd753a03" class="outline-6">
<h6 id="orgd753a03"><span class="section-number-6">3.2.3.2.4.</span> Work</h6>
<div class="outline-text-6" id="text-3-2-3-2-4">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5479,8 +5479,8 @@ in
</div>
</div>
</div>
<div id="outline-container-orgf448b84" class="outline-6">
<h6 id="orgf448b84"><span class="section-number-6">3.2.3.2.5.</span> Framework</h6>
<div id="outline-container-org8147a26" class="outline-6">
<h6 id="org8147a26"><span class="section-number-6">3.2.3.2.5.</span> Framework</h6>
<div class="outline-text-6" id="text-3-2-3-2-5">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5501,8 +5501,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org093c33e" class="outline-6">
<h6 id="org093c33e"><span class="section-number-6">3.2.3.2.6.</span> Darwin</h6>
<div id="outline-container-org0e9f70a" class="outline-6">
<h6 id="org0e9f70a"><span class="section-number-6">3.2.3.2.6.</span> Darwin</h6>
<div class="outline-text-6" id="text-3-2-3-2-6">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -5520,8 +5520,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org7978a81" class="outline-6">
<h6 id="org7978a81"><span class="section-number-6">3.2.3.2.7.</span> Local Server</h6>
<div id="outline-container-orgeaaa568" class="outline-6">
<h6 id="orgeaaa568"><span class="section-number-6">3.2.3.2.7.</span> Local Server</h6>
<div class="outline-text-6" id="text-3-2-3-2-7">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -7054,8 +7054,8 @@ Most of the time I am using <code>power-saver</code>, however, it is good to be
</div>
</div>
</div>
<div id="outline-container-org19e1c87" class="outline-6">
<h6 id="org19e1c87"><span class="section-number-6">3.3.1.22.6.</span> SwayOSD</h6>
<div id="outline-container-org9689642" class="outline-6">
<h6 id="org9689642"><span class="section-number-6">3.3.1.22.6.</span> SwayOSD</h6>
<div class="outline-text-6" id="text-3-3-1-22-6">
<div class="org-src-container">
<pre class="src src-nix">{ lib, pkgs, config, ... }:
@ -8812,7 +8812,7 @@ in
</div>
</div>
<div id="outline-container-h:89638fb5-0593-4420-9567-f85f0223e341" class="outline-5">
<h5 id="h:89638fb5-0593-4420-9567-f85f0223e341"><span class="section-number-5">3.3.2.17.</span> paperless</h5>
<h5 id="h:89638fb5-0593-4420-9567-f85f0223e341"><span class="section-number-5">3.3.2.17.</span> paperless (tika, gotenberg)</h5>
<div class="outline-text-5" id="text-h:89638fb5-0593-4420-9567-f85f0223e341">
<p>
This is my personal document management system. It automatically pulls documents from several sources, the only manual step for physical documents is to put them in my scanner and use email delivery.
@ -9561,6 +9561,10 @@ FreshRSS is a more 'classical' RSS aggregator that I can just host as a distinct
It serves both a Greader API at <a href="https://signpost.swarsel.win/api/greader.php">https://signpost.swarsel.win/api/greader.php</a>, as well as a Fever API at <a href="https://signpost.swarsel.win/api/fever.php">https://signpost.swarsel.win/api/fever.php</a>.
</p>
<p>
I am using this with CapyReader on my phone, set it up as a FreshRSS account with Server URL =<a href="https://signpost.swarsel.win/api/greader.php">https://signpost.swarsel.win/api/greader.php</a>
</p>
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
{
@ -9575,24 +9579,91 @@ It serves both a Greader API at <a href="https://signpost.swarsel.win/api/greade
users.groups.freshrss = { };
sops.secrets.fresh = { owner = "freshrss"; };
sops = {
secrets = {
fresh = { owner = "freshrss"; };
"kanidm-freshrss-client" = { owner = "freshrss"; group = "freshrss"; mode = "0440"; };
"oidc-crypto-key" = { owner = "freshrss"; group = "freshrss"; mode = "0440"; };
};
# templates = {
# "freshrss-env" = {
# content = ''
# DATA_PATH=${config.services.freshrss.dataDir}
# OIDC_ENABLED=1
# OIDC_PROVIDER_METADATA_URL=https://sso.swarsel.win/.well-known/openid-configuration
# OIDC_CLIENT_ID=freshrss
# OIDC_CLIENT_SECRET=${config.sops.placeholder.kanidm-freshrss-client}
# OIDC_CLIENT_CRYPTO_KEY=${config.sops.placeholder.oidc-crypto-key}
# OIDC_REMOTE_USER_CLAIM=preferred_username
# OIDC_SCOPES=openid groups email profile
# OIDC_X_FORWARDED_HEADERS=X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto
# '';
# owner = "freshrss";
# group = "freshrss";
# mode = "0440";
# };
# };
};
services.freshrss = {
enable = true;
virtualHost = "signpost.swarsel.win";
baseUrl = "https://signpost.swarsel.win";
# authType = "none";
authType = "none";
dataDir = "/Vault/data/tt-rss";
defaultUser = "Swarsel";
passwordFile = config.sops.secrets.fresh.path;
};
# systemd.services.freshrss-config.serviceConfig.EnvironmentFile = [
# config.sops.templates.freshrss-env.path
# ];
services.nginx = {
virtualHosts = {
"signpost.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
extraConfig = ''
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# pass information via X-User and X-Email headers to backend,
# requires running with --set-xauthrequest flag (done by NixOS)
auth_request_set $user $upstream_http_x_auth_request_preferred_username;
# Set the email to our own domain in case user change their mail
auth_request_set $email "''${upstream_http_x_auth_request_preferred_username}@swarsel.win";
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
# if you enabled --cookie-refresh, this is needed for it to work with auth_request
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
'';
};
"/oauth2/" = {
proxyPass = "http://oauth2-proxy";
extraConfig = ''
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
'';
};
"= /oauth2/auth" = {
proxyPass = "http://oauth2-proxy/oauth2/auth";
extraConfig = ''
internal;
proxy_set_header X-Scheme $scheme;
# nginx auth_request includes headers but not body
proxy_set_header Content-Length "";
proxy_pass_request_body off;
'';
};
};
};
};
};
@ -9804,8 +9875,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org9187e63" class="outline-5">
<h5 id="org9187e63"><span class="section-number-5">3.3.2.27.</span> kanidm</h5>
<div id="outline-container-org6b2e178" class="outline-5">
<h5 id="org6b2e178"><span class="section-number-5">3.3.2.27.</span> IDM (kanidm + oauth2-proxy)</h5>
<div class="outline-text-5" id="text-3-3-2-27">
<p>
The forgejo configuration is a little broken and will show a 500 error when signing in through kanidm. However, when pressing back and refreshing the page, I am logged in. Currently I cannot be bothered to fix this.
@ -9825,7 +9896,9 @@ To get other URLs (token, etc.), use <a href="https://&lt;kanidmdomain&gt;/oauth
let
certsSopsFile = self + /secrets/certs/secrets.yaml;
kanidmDomain = "sso.swarsel.win";
oauth2ProxyDomain = "soauth.swarsel.win";
kanidmPort = 8300;
oauth2ProxyPort = 3004;
in
{
options.swarselsystems.modules.server.kanidm = lib.mkEnableOption "enable kanidm on server";
@ -9838,7 +9911,9 @@ in
users.groups.kanidm = { };
sops.secrets = {
sops = {
secrets = {
"oauth2-cookie-secret" = { owner = "oauth2-proxy"; group = "oauth2-proxy"; mode = "0440"; };
"kanidm-self-signed-crt" = { sopsFile = certsSopsFile; owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-self-signed-key" = { sopsFile = certsSopsFile; owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-admin-pw" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
@ -9848,9 +9923,26 @@ in
"kanidm-forgejo" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-grafana" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-nextcloud" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-freshrss" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-oauth2-proxy" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-oauth2-proxy-client" = { owner = "oauth2-proxy"; group = "oauth2-proxy"; mode = "0440"; };
};
services.kanidm = {
templates = {
"kanidm-oauth2-proxy-client-env" = {
content = ''
OAUTH2_PROXY_CLIENT_SECRET="${config.sops.placeholder.kanidm-oauth2-proxy-client}"
OAUTH2_PROXY_COOKIE_SECRET=${config.sops.placeholder.oauth2-cookie-secret}
'';
owner = "oauth2-proxy";
group = "oauth2-proxy";
mode = "0440";
};
};
};
services = {
kanidm = {
package = pkgs.kanidmWithSecretProvisioning;
enableServer = true;
serverSettings = {
@ -9882,6 +9974,8 @@ in
"grafana.server-admins" = { };
"nextcloud.access" = { };
"nextcloud.admins" = { };
"navidrome.access" = { };
"freshrss.access" = { };
};
persons = {
swarsel = {
@ -9894,6 +9988,8 @@ in
"grafana.access"
"forgejo.access"
"nextcloud.access"
"freshrss.access"
"navidrome.access"
];
displayName = "Swarsel";
};
@ -9988,14 +10084,107 @@ in
};
};
};
# freshrss = {
# displayName = "FreshRSS";
# originUrl = "https://signpost.swarsel.win/apps/sociallogin/custom_oidc/kanidm";
# originLanding = "https://signpost.swarsel.win/";
# basicSecretFile = config.sops.secrets.kanidm-freshrss.path;
# allowInsecureClientDisablePkce = true;
# scopeMaps."freshrss.access" = [
# "openid"
# "email"
# "profile"
# ];
# preferShortUsername = true;
# };
oauth2-proxy = {
displayName = "Oauth2-Proxy";
originUrl = "https://${oauth2ProxyDomain}/oauth2/callback";
originLanding = "https://${oauth2ProxyDomain}/";
basicSecretFile = config.sops.secrets.kanidm-oauth2-proxy.path;
scopeMaps."freshrss.access" = [
"openid"
"email"
"profile"
];
scopeMaps."navidrome.access" = [
"openid"
"email"
"profile"
];
preferShortUsername = true;
claimMaps.groups = {
joinType = "array";
valuesByGroup."freshrss.access" = [ "ttrss_access" ];
valuesByGroup."navidrome.access" = [ "navidrome_access" ];
};
};
};
};
};
};
oauth2-proxy = {
enable = true;
cookie = {
domain = ".swarsel.win";
secure = true;
expire = "900m";
secret = null; # set by service EnvironmentFile
};
clientSecret = null; # set by service EnvironmentFile
reverseProxy = true;
httpAddress = "0.0.0.0:${builtins.toString oauth2ProxyPort}";
redirectURL = "https://${oauth2ProxyDomain}/oauth2/callback";
setXauthrequest = true;
extraConfig = {
code-challenge-method = "S256";
whitelist-domain = ".swarsel.win";
set-authorization-header = true;
pass-access-token = true;
skip-jwt-bearer-tokens = true;
upstream = "static://202";
oidc-issuer-url = "https://${kanidmDomain}/oauth2/openid/oauth2-proxy";
provider-display-name = "Kanidm";
};
provider = "oidc";
scope = "openid email";
loginURL = "https://${kanidmDomain}/ui/oauth2";
redeemURL = "https://${kanidmDomain}/oauth2/token";
validateURL = "https://${kanidmDomain}/oauth2/openid/oauth2-proxy/userinfo";
clientID = "oauth2-proxy";
email.domains = [ "*" ];
};
};
systemd.services.kanidm.serviceConfig.RestartSec = "30";
systemd.services = {
kanidm.serviceConfig.RestartSec = "30";
oauth2-proxy = {
after = [ "kanidm.service" ];
serviceConfig = {
RuntimeDirectory = "oauth2-proxy";
RuntimeDirectoryMode = "0750";
UMask = "007"; # TODO remove once https://github.com/oauth2-proxy/oauth2-proxy/issues/2141 is fixed
RestartSec = "60"; # Retry every minute
EnvironmentFile = [
config.sops.templates.kanidm-oauth2-proxy-client-env.path
];
};
};
};
services.nginx = {
upstreams = {
kanidm = {
servers = {
"192.168.1.2:${builtins.toString kanidmPort}" = { };
};
};
oauth2-proxy = {
servers = {
"192.168.1.2:${builtins.toString oauth2ProxyPort}" = { };
};
};
};
virtualHosts = {
"${kanidmDomain}" = {
enableACME = true;
@ -10003,13 +10192,27 @@ in
acmeRoot = null;
locations = {
"/" = {
proxyPass = "https://localhost:${toString kanidmPort}";
proxyPass = "https://kanidm";
};
};
extraConfig = ''
proxy_ssl_verify off;
'';
};
"${oauth2ProxyDomain}" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://oauth2-proxy";
};
};
extraConfig = ''
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
'';
};
};
};
};
@ -10230,8 +10433,8 @@ This smashes Atmosphere 1.3.2 on the switch, which is what I am currenty using.
</div>
</div>
</div>
<div id="outline-container-org5a82981" class="outline-5">
<h5 id="org5a82981"><span class="section-number-5">3.3.4.6.</span> Framework</h5>
<div id="outline-container-orge3ac9e1" class="outline-5">
<h5 id="orge3ac9e1"><span class="section-number-5">3.3.4.6.</span> Framework</h5>
<div class="outline-text-5" id="text-3-3-4-6">
<p>
This holds configuration that is specific to framework laptops.
@ -10269,8 +10472,8 @@ This holds configuration that is specific to framework laptops.
</div>
</div>
</div>
<div id="outline-container-orga8a179d" class="outline-5">
<h5 id="orga8a179d"><span class="section-number-5">3.3.4.7.</span> AMD CPU</h5>
<div id="outline-container-org5532d9d" class="outline-5">
<h5 id="org5532d9d"><span class="section-number-5">3.3.4.7.</span> AMD CPU</h5>
<div class="outline-text-5" id="text-3-3-4-7">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -10286,8 +10489,8 @@ This holds configuration that is specific to framework laptops.
</div>
</div>
</div>
<div id="outline-container-org00ce247" class="outline-5">
<h5 id="org00ce247"><span class="section-number-5">3.3.4.8.</span> AMD GPU</h5>
<div id="outline-container-org0dda67c" class="outline-5">
<h5 id="org0dda67c"><span class="section-number-5">3.3.4.8.</span> AMD GPU</h5>
<div class="outline-text-5" id="text-3-3-4-8">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -10309,8 +10512,8 @@ This holds configuration that is specific to framework laptops.
</div>
</div>
</div>
<div id="outline-container-orgf108079" class="outline-5">
<h5 id="orgf108079"><span class="section-number-5">3.3.4.9.</span> Hibernation</h5>
<div id="outline-container-orge0bde26" class="outline-5">
<h5 id="orge0bde26"><span class="section-number-5">3.3.4.9.</span> Hibernation</h5>
<div class="outline-text-5" id="text-3-3-4-9">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -10341,8 +10544,8 @@ This holds configuration that is specific to framework laptops.
</div>
</div>
</div>
<div id="outline-container-org5c280d6" class="outline-5">
<h5 id="org5c280d6"><span class="section-number-5">3.3.4.10.</span> BTRFS</h5>
<div id="outline-container-orgd71adf6" class="outline-5">
<h5 id="orgd71adf6"><span class="section-number-5">3.3.4.10.</span> BTRFS</h5>
<div class="outline-text-5" id="text-3-3-4-10">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -13290,8 +13493,8 @@ The `extraConfig` section here CANNOT be reindented. This has something to do wi
</div>
</div>
</div>
<div id="outline-container-orgdcc7202" class="outline-6">
<h6 id="orgdcc7202"><span class="section-number-6">3.4.1.29.4.</span> SwayOSD</h6>
<div id="outline-container-org87b0218" class="outline-6">
<h6 id="org87b0218"><span class="section-number-6">3.4.1.29.4.</span> SwayOSD</h6>
<div class="outline-text-6" id="text-3-4-1-29-4">
<div class="org-src-container">
<pre class="src src-nix">{ lib, config, ... }:
@ -14540,8 +14743,8 @@ in
</div>
</div>
</div>
<div id="outline-container-org1fd635e" class="outline-5">
<h5 id="org1fd635e"><span class="section-number-5">3.4.4.3.</span> Framework</h5>
<div id="outline-container-org3b5d2ad" class="outline-5">
<h5 id="org3b5d2ad"><span class="section-number-5">3.4.4.3.</span> Framework</h5>
<div class="outline-text-5" id="text-3-4-4-3">
<p>
This holds configuration that is specific to framework laptops.
@ -18381,8 +18584,8 @@ autocmd DocStart vc-impimba-1.m.imp.ac.at/ui/webconsole mode ignore
</div>
</div>
</div>
<div id="outline-container-orgd553dac" class="outline-3">
<h3 id="orgd553dac"><span class="section-number-3">6.3.</span> tridactyl theme</h3>
<div id="outline-container-org1d84ef9" class="outline-3">
<h3 id="org1d84ef9"><span class="section-number-3">6.3.</span> tridactyl theme</h3>
<div class="outline-text-3" id="text-6-3">
<div class="org-src-container">
<pre class="src src-config">
@ -18879,7 +19082,7 @@ sync USER HOST:
</div>
<div id="postamble" class="status">
<p class="author">Author: Leon Schwarzäugl</p>
<p class="date">Created: 2025-06-09 Mo 19:11</p>
<p class="date">Created: 2025-06-10 Di 00:09</p>
<p class="validation"><a href="https://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>

View file

@ -11,24 +11,91 @@
users.groups.freshrss = { };
sops.secrets.fresh = { owner = "freshrss"; };
sops = {
secrets = {
fresh = { owner = "freshrss"; };
"kanidm-freshrss-client" = { owner = "freshrss"; group = "freshrss"; mode = "0440"; };
"oidc-crypto-key" = { owner = "freshrss"; group = "freshrss"; mode = "0440"; };
};
# templates = {
# "freshrss-env" = {
# content = ''
# DATA_PATH=${config.services.freshrss.dataDir}
# OIDC_ENABLED=1
# OIDC_PROVIDER_METADATA_URL=https://sso.swarsel.win/.well-known/openid-configuration
# OIDC_CLIENT_ID=freshrss
# OIDC_CLIENT_SECRET=${config.sops.placeholder.kanidm-freshrss-client}
# OIDC_CLIENT_CRYPTO_KEY=${config.sops.placeholder.oidc-crypto-key}
# OIDC_REMOTE_USER_CLAIM=preferred_username
# OIDC_SCOPES=openid groups email profile
# OIDC_X_FORWARDED_HEADERS=X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto
# '';
# owner = "freshrss";
# group = "freshrss";
# mode = "0440";
# };
# };
};
services.freshrss = {
enable = true;
virtualHost = "signpost.swarsel.win";
baseUrl = "https://signpost.swarsel.win";
# authType = "none";
authType = "none";
dataDir = "/Vault/data/tt-rss";
defaultUser = "Swarsel";
passwordFile = config.sops.secrets.fresh.path;
};
# systemd.services.freshrss-config.serviceConfig.EnvironmentFile = [
# config.sops.templates.freshrss-env.path
# ];
services.nginx = {
virtualHosts = {
"signpost.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
extraConfig = ''
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# pass information via X-User and X-Email headers to backend,
# requires running with --set-xauthrequest flag (done by NixOS)
auth_request_set $user $upstream_http_x_auth_request_preferred_username;
# Set the email to our own domain in case user change their mail
auth_request_set $email "''${upstream_http_x_auth_request_preferred_username}@swarsel.win";
proxy_set_header X-User $user;
proxy_set_header X-Email $email;
# if you enabled --cookie-refresh, this is needed for it to work with auth_request
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
'';
};
"/oauth2/" = {
proxyPass = "http://oauth2-proxy";
extraConfig = ''
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
'';
};
"= /oauth2/auth" = {
proxyPass = "http://oauth2-proxy/oauth2/auth";
extraConfig = ''
internal;
proxy_set_header X-Scheme $scheme;
# nginx auth_request includes headers but not body
proxy_set_header Content-Length "";
proxy_pass_request_body off;
'';
};
};
};
};
};

View file

@ -2,7 +2,9 @@
let
certsSopsFile = self + /secrets/certs/secrets.yaml;
kanidmDomain = "sso.swarsel.win";
oauth2ProxyDomain = "soauth.swarsel.win";
kanidmPort = 8300;
oauth2ProxyPort = 3004;
in
{
options.swarselsystems.modules.server.kanidm = lib.mkEnableOption "enable kanidm on server";
@ -15,7 +17,9 @@ in
users.groups.kanidm = { };
sops.secrets = {
sops = {
secrets = {
"oauth2-cookie-secret" = { owner = "oauth2-proxy"; group = "oauth2-proxy"; mode = "0440"; };
"kanidm-self-signed-crt" = { sopsFile = certsSopsFile; owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-self-signed-key" = { sopsFile = certsSopsFile; owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-admin-pw" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
@ -25,9 +29,26 @@ in
"kanidm-forgejo" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-grafana" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-nextcloud" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-freshrss" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-oauth2-proxy" = { owner = "kanidm"; group = "kanidm"; mode = "0440"; };
"kanidm-oauth2-proxy-client" = { owner = "oauth2-proxy"; group = "oauth2-proxy"; mode = "0440"; };
};
services.kanidm = {
templates = {
"kanidm-oauth2-proxy-client-env" = {
content = ''
OAUTH2_PROXY_CLIENT_SECRET="${config.sops.placeholder.kanidm-oauth2-proxy-client}"
OAUTH2_PROXY_COOKIE_SECRET=${config.sops.placeholder.oauth2-cookie-secret}
'';
owner = "oauth2-proxy";
group = "oauth2-proxy";
mode = "0440";
};
};
};
services = {
kanidm = {
package = pkgs.kanidmWithSecretProvisioning;
enableServer = true;
serverSettings = {
@ -59,6 +80,8 @@ in
"grafana.server-admins" = { };
"nextcloud.access" = { };
"nextcloud.admins" = { };
"navidrome.access" = { };
"freshrss.access" = { };
};
persons = {
swarsel = {
@ -71,6 +94,8 @@ in
"grafana.access"
"forgejo.access"
"nextcloud.access"
"freshrss.access"
"navidrome.access"
];
displayName = "Swarsel";
};
@ -165,14 +190,107 @@ in
};
};
};
# freshrss = {
# displayName = "FreshRSS";
# originUrl = "https://signpost.swarsel.win/apps/sociallogin/custom_oidc/kanidm";
# originLanding = "https://signpost.swarsel.win/";
# basicSecretFile = config.sops.secrets.kanidm-freshrss.path;
# allowInsecureClientDisablePkce = true;
# scopeMaps."freshrss.access" = [
# "openid"
# "email"
# "profile"
# ];
# preferShortUsername = true;
# };
oauth2-proxy = {
displayName = "Oauth2-Proxy";
originUrl = "https://${oauth2ProxyDomain}/oauth2/callback";
originLanding = "https://${oauth2ProxyDomain}/";
basicSecretFile = config.sops.secrets.kanidm-oauth2-proxy.path;
scopeMaps."freshrss.access" = [
"openid"
"email"
"profile"
];
scopeMaps."navidrome.access" = [
"openid"
"email"
"profile"
];
preferShortUsername = true;
claimMaps.groups = {
joinType = "array";
valuesByGroup."freshrss.access" = [ "ttrss_access" ];
valuesByGroup."navidrome.access" = [ "navidrome_access" ];
};
};
};
};
};
};
oauth2-proxy = {
enable = true;
cookie = {
domain = ".swarsel.win";
secure = true;
expire = "900m";
secret = null; # set by service EnvironmentFile
};
clientSecret = null; # set by service EnvironmentFile
reverseProxy = true;
httpAddress = "0.0.0.0:${builtins.toString oauth2ProxyPort}";
redirectURL = "https://${oauth2ProxyDomain}/oauth2/callback";
setXauthrequest = true;
extraConfig = {
code-challenge-method = "S256";
whitelist-domain = ".swarsel.win";
set-authorization-header = true;
pass-access-token = true;
skip-jwt-bearer-tokens = true;
upstream = "static://202";
oidc-issuer-url = "https://${kanidmDomain}/oauth2/openid/oauth2-proxy";
provider-display-name = "Kanidm";
};
provider = "oidc";
scope = "openid email";
loginURL = "https://${kanidmDomain}/ui/oauth2";
redeemURL = "https://${kanidmDomain}/oauth2/token";
validateURL = "https://${kanidmDomain}/oauth2/openid/oauth2-proxy/userinfo";
clientID = "oauth2-proxy";
email.domains = [ "*" ];
};
};
systemd.services.kanidm.serviceConfig.RestartSec = "30";
systemd.services = {
kanidm.serviceConfig.RestartSec = "30";
oauth2-proxy = {
after = [ "kanidm.service" ];
serviceConfig = {
RuntimeDirectory = "oauth2-proxy";
RuntimeDirectoryMode = "0750";
UMask = "007"; # TODO remove once https://github.com/oauth2-proxy/oauth2-proxy/issues/2141 is fixed
RestartSec = "60"; # Retry every minute
EnvironmentFile = [
config.sops.templates.kanidm-oauth2-proxy-client-env.path
];
};
};
};
services.nginx = {
upstreams = {
kanidm = {
servers = {
"192.168.1.2:${builtins.toString kanidmPort}" = { };
};
};
oauth2-proxy = {
servers = {
"192.168.1.2:${builtins.toString oauth2ProxyPort}" = { };
};
};
};
virtualHosts = {
"${kanidmDomain}" = {
enableACME = true;
@ -180,13 +298,27 @@ in
acmeRoot = null;
locations = {
"/" = {
proxyPass = "https://localhost:${toString kanidmPort}";
proxyPass = "https://kanidm";
};
};
extraConfig = ''
proxy_ssl_verify off;
'';
};
"${oauth2ProxyDomain}" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://oauth2-proxy";
};
};
extraConfig = ''
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
'';
};
};
};
};

View file

@ -42,6 +42,8 @@ kanidm-grafana-client: ENC[AES256_GCM,data:tV25k0XoFZ9wLF0UWvAabgigayowr3wo0g==,
prometheusadminpass: ENC[AES256_GCM,data:NYUbSnAl0f3FUtvCjvJHFr2wMRsVsbVIeg==,iv:TP4NMwJsft8aEixxJBJCX/0I6BJVBnltFYJDKuXq1hM=,tag:yMY+KZsRjbn8ItgKgjzqSA==,type:str]
#ENC[AES256_GCM,data:QnIF/xhWguX5tw==,iv:yTUBtPaZk6BXi+SC1P/OOtnc2x9UZ/jXirD5oaxhyQY=,tag:c33L5r5BaPZN6zkwduBCwQ==,type:comment]
fresh: ENC[AES256_GCM,data:aPF8D96BvgDXhcc=,iv:Ubq3/sUmBipRanLgkAXXeAfXAz51AuR+NojMifsy8S0=,tag:mHf0YYYxulLXAIByqmnOsA==,type:str]
kanidm-freshrss-client: ENC[AES256_GCM,data:jBplXWOX/mRTQf6cKmP3C5PZJoBAmb3mhg==,iv:5hcLNGuEQ0T9FiczznGKMul38Ftv8PmG3q0Vaao10oI=,tag:tpx+EDvA31HCnG1/XJOBWg==,type:str]
oidc-crypto-key: ENC[AES256_GCM,data:O48Va8j2L/GDdTZRQEtVsoy1jsZSCLx0IxFYnCBGhoGRwDW+t0LKPw==,iv:DLCeGhRqRp/JfFaY3vva86OzMwGlcXxiBbQ4Tayjyq4=,tag:We5W8cIntW3D/5vdC/t8IA==,type:str]
#ENC[AES256_GCM,data:+lbLElpVOYo=,iv:DaVuudlnW+vy2PZOs9eiwZhOyILnqEX9KUehFlX2gWE=,tag:lvM6r0JM0DZir4y7iVTeKg==,type:comment]
kanidm-forgejo-client: ENC[AES256_GCM,data:pitJ6re5xm2w1MSs5Ul7Tl1/H1KSR7Ps7w==,iv:4k8/cxpLqWxCgJuk/y9K3OAMCkzu8gb8CDxY+gUuOvg=,tag:OocTFS54teDUfHaHAHZiHw==,type:str]
#ENC[AES256_GCM,data:Ur0/rfBv5g==,iv:eH+KbbkmtBWbobqAIUFF0jIrGhbHnk9g8hLZoxE3swI=,tag:3dnoA+O5GXW5Dvxcx4jiTw==,type:comment]
@ -56,6 +58,11 @@ kanidm-paperless: ENC[AES256_GCM,data:bJJC20q8aJVzmIMXAHWvOoH652lSCFXDNg==,iv:0c
kanidm-forgejo: ENC[AES256_GCM,data:zw0LcfNJw4q28l1E9q58D9bTKtl/CjGA3w==,iv:fYRGasFiM7PXeP5sWW6whj10CUKIqCfhIYQCNZjxQGo=,tag:sxQJa+ItPA+L3keWZ34SJA==,type:str]
kanidm-grafana: ENC[AES256_GCM,data:61PEA1fBcaRy8+x0dn9WrH9P0D+NOkbeZw==,iv:kbR3JWzHsmsef+VlFGciZmyforxJCdvzHijvGFvFwpk=,tag:K+6baLIKy0L37KrJEQUgPg==,type:str]
kanidm-nextcloud: ENC[AES256_GCM,data:9FjsOzBos18ouHBeuzrzHIpCDowFt0Aktw==,iv:iqUQUsWsO5N+KZqHyqNxMxSija/yPrrrAqvz4b1NG1M=,tag:/WC3wg/eYXV3hLJPRVWLog==,type:str]
kanidm-oauth2-proxy: ENC[AES256_GCM,data:DQ5tj7N+P1b8vFnF+MGhaUBvbVQoE4sVhQ==,iv:Xy4bdi8fSFuFHsQKgZ3PswFFYsqtiAeqeSRam1k/H0E=,tag:9W4LRPPYtDOrSpxRDK/7sg==,type:str]
kanidm-freshrss: ENC[AES256_GCM,data:4y0X3sSOfs5pKNCmZGJhxlAKH7GD1UACdw==,iv:LuQQCfOpsTqglwQvohHMFpNGaOjoZ8PKDgG50qBP02k=,tag:Z5mVYP/9nToerQ1qui1eWQ==,type:str]
#ENC[AES256_GCM,data:8eDo+FQoBEKMTRY2,iv:ZSrV+Z+1S5AoW+jq49LBFzSwd/NJl3aZYHe7oUvGriU=,tag:3cw3hUigrPViQ+XsuMiksg==,type:comment]
oauth2-cookie-secret: ENC[AES256_GCM,data:l8BPYA7t9NG9MPFs/LDlFHqwbnwsvie7FM5v613358E+jLf2wD+tipyUb6c=,iv:1kZ6G6Z0cSQS53kc/hygh/1Ke491agWDlYHR9Yq0jT0=,tag:mi7Un2JBnrq1dnP3jZX4ng==,type:str]
kanidm-oauth2-proxy-client: ENC[AES256_GCM,data:+mcA/sz3AZuw+I44iIdOEfDmtjEVdxi2fg==,iv:m4NpieUicS7xsR+F5AgPqkcUFRF+CGOA8IK6GeS9tgM=,tag:1wypxpiHPdQBD8Td/PSdMw==,type:str]
sops:
age:
- recipient: age1h72072slm2pthn9m2qwjsyy2dsazc6hz97kpzh4gksvv0r2jqecqul8w63
@ -67,8 +74,8 @@ sops:
MEZ1UWw3alF1WnJZMFZvMFBpbDFJZlUKGRnoEEgjgJ9SSblmldtY6d8MdAy01yxl
qkvEIoXbL+ky2ira7EgjD0legThzCnmlXUlcSn3SpwbkAGgcfd2kWA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-06-09T16:04:54Z"
mac: ENC[AES256_GCM,data:ggq/mHOw4kaIalgVNI9YASGewzOwR8+DxhvuuOLo3L4Qnn71/HtXkYnKPMm+Ip58AJi7yH5adNOP2q7MZ/wlG/Ygg95PiM/dBso7l79suycrBo+Zz2bGwUjnT6d35Sz2lqsAIDZgpSwk2M51FjivVXD+Un0aWlt/dj5XOwBhlnU=,iv:WRuIlZ1zc+ITNC4R4Zn2ORy7G2hRFnlEBvnjts4n+RE=,tag:wduo+u6Kjm3LyvkLO8OG+w==,type:str]
lastmodified: "2025-06-09T19:50:17Z"
mac: ENC[AES256_GCM,data:Cx7bI5HRkVVmZTcs/Q3uPtLZaaGd28ZqUsyPRcqd8yEaRxNN0JU6EcQ2ZjU5Zi9jLRLDiR/PxuWsWcmDWH8vW0UZGh6ao75Cw3UO7QhKZHfM5cHqnleo/RIIl5d/Q0hnS9EQmcEPA3qKLQUIrOa+MAgMCkti50ZuNcZnkywLn54=,iv:QPDj4K22G6Go6RDE5ZGbCntmC+mn/5mMyH6ohyQYNuY=,tag:NJ3mjmo2LRmJRXKrYIJZKg==,type:str]
pgp:
- created_at: "2024-12-17T16:24:32Z"
enc: |-