From 582faec35932f605809ea30b06427da86b5672f2 Mon Sep 17 00:00:00 2001 From: Jory Severijnse Date: Tue, 14 Jul 2026 13:50:59 +0200 Subject: [PATCH] feat(auth): streamline SOPS authentication and network configuration - Replace age-based key decryption with automatic SSH host key support - Simplify SSH configuration with consolidated host entries and enhanced security settings - Upgrade home-manager to himmelblau for Microsoft Entra ID authentication - Remove legacy agenix inputs and consolidate secrets to essential services only - Add Cisco Secure Client overlay for enterprise VPN capabilities - Update secrets.yaml to minimal configuration with gitea/github/hetzner services - Expand system packages with tun module for VPN connectivity - Add work directory setup for user development environment --- flake.lock | 67 +++----------- flake.nix | 15 ++-- home/terminal/software/ssh.nix | 46 +++++++--- hosts/aesthetic/default.nix | 33 ++----- hosts/default.nix | 2 + pkgs/cisco-secure-client/default.nix | 126 +++++++++++++++++++++++++++ secrets/age.key | 3 - secrets/aur.age | Bin 624 -> 0 bytes secrets/gitea_laptop.age | Bin 612 -> 0 bytes secrets/github_key.age | Bin 624 -> 0 bytes secrets/hetzner_server.age | 6 -- secrets/secrets.nix | 22 ----- secrets/secrets.yaml | 33 +++---- secrets/sporestack_server.age | Bin 624 -> 0 bytes secrets/ssh_config.age | Bin 919 -> 0 bytes work/cisco.nix | 92 +++++++++++++++++++ work/default.nix | 12 +++ work/himmelblau.nix | 47 ++++++++++ work/overlay.nix | 9 ++ 19 files changed, 359 insertions(+), 154 deletions(-) create mode 100644 pkgs/cisco-secure-client/default.nix delete mode 100644 secrets/age.key delete mode 100644 secrets/aur.age delete mode 100644 secrets/gitea_laptop.age delete mode 100644 secrets/github_key.age delete mode 100644 secrets/hetzner_server.age delete mode 100644 secrets/secrets.nix delete mode 100644 secrets/sporestack_server.age delete mode 100644 secrets/ssh_config.age create mode 100644 work/cisco.nix create mode 100644 work/default.nix create mode 100644 work/himmelblau.nix create mode 100644 work/overlay.nix diff --git a/flake.lock b/flake.lock index 3863740..9b00845 100644 --- a/flake.lock +++ b/flake.lock @@ -1,52 +1,5 @@ { "nodes": { - "agenix": { - "inputs": { - "darwin": "darwin", - "home-manager": "home-manager", - "nixpkgs": [ - "nixpkgs" - ], - "systems": [ - "systems" - ] - }, - "locked": { - "lastModified": 1770165109, - "narHash": "sha256-9VnK6Oqai65puVJ4WYtCTvlJeXxMzAp/69HhQuTdl/I=", - "owner": "ryantm", - "repo": "agenix", - "rev": "b027ee29d959fda4b60b57566d64c98a202e0feb", - "type": "github" - }, - "original": { - "owner": "ryantm", - "repo": "agenix", - "type": "github" - } - }, - "darwin": { - "inputs": { - "nixpkgs": [ - "agenix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1744478979, - "narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=", - "owner": "lnl7", - "repo": "nix-darwin", - "rev": "43975d782b418ebf4969e9ccba82466728c2851b", - "type": "github" - }, - "original": { - "owner": "lnl7", - "ref": "master", - "repo": "nix-darwin", - "type": "github" - } - }, "disko": { "inputs": { "nixpkgs": [ @@ -181,24 +134,24 @@ "type": "github" } }, - "home-manager": { + "himmelblau": { "inputs": { "nixpkgs": [ - "agenix", "nixpkgs" ] }, "locked": { - "lastModified": 1745494811, - "narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=", - "owner": "nix-community", - "repo": "home-manager", - "rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be", + "lastModified": 1783966245, + "narHash": "sha256-yFLScy0bxU6GLf4ZUoYCzZiyh5AGTT85evjw6xpG++g=", + "owner": "himmelblau-idm", + "repo": "himmelblau", + "rev": "00b27a924c2a42d54320b9ebc012c22d8dd95e28", "type": "github" }, "original": { - "owner": "nix-community", - "repo": "home-manager", + "owner": "himmelblau-idm", + "ref": "main", + "repo": "himmelblau", "type": "github" } }, @@ -303,13 +256,13 @@ }, "root": { "inputs": { - "agenix": "agenix", "disko": "disko", "flake-compat": "flake-compat", "flake-parts": "flake-parts", "flake-utils": "flake-utils", "git-hooks-nix": "git-hooks-nix", "helium": "helium", + "himmelblau": "himmelblau", "import-tree": "import-tree", "nix-index-db": "nix-index-db", "nixos-24-05": "nixos-24-05", diff --git a/flake.nix b/flake.nix index 2d37711..aba08a2 100644 --- a/flake.nix +++ b/flake.nix @@ -82,14 +82,6 @@ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; # rest of inputs, alphabetical order - agenix = { - url = "github:ryantm/agenix"; - inputs = { - nixpkgs.follows = "nixpkgs"; - systems.follows = "systems"; - }; - }; - import-tree.url = "github:vic/import-tree"; zen-browser = { @@ -102,6 +94,11 @@ inputs.nixpkgs.follows = "nixpkgs"; }; + himmelblau = { + url = "github:himmelblau-idm/himmelblau/main"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + nix-index-db = { url = "github:Mic92/nix-index-database"; inputs.nixpkgs.follows = "nixpkgs"; @@ -127,4 +124,4 @@ inputs.nixpkgs.follows = "nixos-24-05"; }; }; -} +} \ No newline at end of file diff --git a/home/terminal/software/ssh.nix b/home/terminal/software/ssh.nix index 962b2a8..faa2a5b 100644 --- a/home/terminal/software/ssh.nix +++ b/home/terminal/software/ssh.nix @@ -1,25 +1,47 @@ { - config, pkgs, + config, ... }: { users.users.someone.packages = with pkgs; [ openssh ]; - xdg.configFile."ssh/config" = { - source = config.sops.secrets.ssh_config.path; - }; + home.file.".ssh/config".text = '' + AddKeysToAgent yes + CheckHostIP yes + Compression no + ControlMaster no + ControlPath ~/.ssh/master-%r@%n:%p + ControlPersist no + HashKnownHosts yes + IdentitiesOnly yes + PasswordAuthentication no + ForwardAgent no + ForwardX11 no + ForwardX11Trusted no + ServerAliveInterval 60 + ServerAliveCountMax 3 + UserKnownHostsFile ~/.ssh/known_hosts - home.file.".ssh/config" = { - source = config.xdg.configHome + "/ssh/config"; - mutable = false; - }; + Host git.severijnse.eu + HostName git.severijnse.eu + Port 222 + User git + IdentityFile /run/secrets/gitea_laptop - environment.sessionVariables = { - SSH_AUTH_SOCK = "${config.xdg.runtimeDir}/gnupg/S.gpg-agent.ssh"; - SSH_CONFIG = "${config.xdg.configHome}/ssh/config"; - }; + Host hetzner + HostName severijnse.eu + User admin + IdentityFile /run/secrets/hetzner_server + + Host github.com + HostName github.com + User git + IdentityFile /run/secrets/github_laptop + + Include ~/.ssh/config.d/* + ''; systemd.user.services.ssh-agent = { description = "SSH agent service"; diff --git a/hosts/aesthetic/default.nix b/hosts/aesthetic/default.nix index dddc456..be48dc2 100644 --- a/hosts/aesthetic/default.nix +++ b/hosts/aesthetic/default.nix @@ -168,40 +168,23 @@ boot.loader.limine.bootMode = lib.mkDefault "bios"; - # sops-nix configuration + # sops-nix configuration — uses SSH host keys automatically, no age key file needed sops = { defaultSopsFile = ./../../secrets/secrets.yaml; - age.keyFile = "/etc/age/keys.txt"; - # Explicitly define secrets to ensure they're generated secrets = { - discordo = { owner = "someone"; group = "users"; mode = "0440"; }; - openrouter = { owner = "someone"; group = "users"; mode = "0440"; }; - github = { owner = "someone"; group = "users"; mode = "0440"; }; - twt = { owner = "someone"; group = "users"; mode = "0440"; }; - gemini = { owner = "someone"; group = "users"; mode = "0440"; }; - context7 = { owner = "someone"; group = "users"; mode = "0440"; }; - exa = { owner = "someone"; group = "users"; mode = "0440"; }; - ssh_config = { owner = "someone"; group = "users"; mode = "0440"; }; gitea_laptop = { owner = "someone"; group = "users"; mode = "0400"; }; + github_laptop = { owner = "someone"; group = "users"; mode = "0400"; }; hetzner_server = { owner = "someone"; group = "users"; mode = "0400"; }; }; }; - environment.systemPackages = [pkgs.cryptsetup pkgs.age pkgs.nixd pkgs.apparmor-parser pkgs.xdg-desktop-portal-wlr]; + nixpkgs.config.allowUnfree = true; - # Provide age private key for sops decryption at activation time - systemd.tmpfiles.rules = [ - "d /etc/age 0700 root root -" - "w /etc/age/keys.txt 0600 root root - # created by activation script" + nixpkgs.overlays = [ + (self: super: { + cisco-secure-client = super.callPackage ../../pkgs/cisco-secure-client {}; + }) ]; - # Activation script to write age key - system.activationScripts.write-age-key = '' - cat > /etc/age/keys.txt << 'AGEEOF' - # created: 2026-07-12T10:20:38+02:00 - # public key: age1n2kvnwdzrd5vw70wwmm90a4lg6wj3665egzpnz72r98epr0rhc0q3yp356 - AGE-SECRET-KEY-1A49GYAG5AJWGW0XM7HWC8QFE6UUF0S3Z99T252SKX2JHW6NM0HDQESWAQC - AGEEOF - chmod 600 /etc/age/keys.txt - ''; + environment.systemPackages = [pkgs.cryptsetup pkgs.age pkgs.nixd pkgs.apparmor-parser pkgs.xdg-desktop-portal-wlr]; } diff --git a/hosts/default.nix b/hosts/default.nix index e2a0049..902900c 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -24,7 +24,9 @@ "${mod}/services/gnome-services.nix" "${mod}/core/limine.nix" "${home}" + "${self}/work" inputs.sops-nix.nixosModules.sops + inputs.himmelblau.nixosModules.himmelblau ]; in { flake.nixosConfigurations = { diff --git a/pkgs/cisco-secure-client/default.nix b/pkgs/cisco-secure-client/default.nix new file mode 100644 index 0000000..6f8804c --- /dev/null +++ b/pkgs/cisco-secure-client/default.nix @@ -0,0 +1,126 @@ +{ lib, stdenv, fetchurl, dpkg, makeWrapper, patchelf +, coreutils, systemd, glib, zlib, xz, curl, libxml2 +}: + +let + version = "5.1.17.3394"; + # libxml2's "out" output has lib/libxml2.so.16 + libxml2_out = libxml2.out; + + # System library RPATH for all bundled ELF binaries (cisco's own lib dir is + # appended during fixupPhase via $out) + sysRpath = lib.makeLibraryPath [ + systemd glib zlib xz stdenv.cc.cc.lib curl libxml2_out + ]; +in stdenv.mkDerivation { + pname = "cisco-secure-client"; + inherit version; + + src = fetchurl { + url = "https://archive.org/download/cisco-secure-client-linux64-${version}/cisco-secure-client-linux64-${version}-predeploy-deb-k9.tgz"; + sha256 = "5c4cafb4694e64cbf041481f5df3d70389399926f8aa2a469d480c0555b58c2c"; + }; + + nativeBuildInputs = [ dpkg makeWrapper patchelf ]; + + buildInputs = [ + systemd glib zlib xz stdenv.cc.cc.lib curl libxml2_out + ]; + + dontStrip = true; + dontAutoPatchelf = true; + + unpackPhase = '' + tar xzf "$src" + DEB_FILE=$(ls cisco-secure-client-vpn-cli_*_amd64.deb 2>/dev/null || true) + if [ -z "$DEB_FILE" ]; then + DEB_FILE=$(ls cisco-secure-client-vpn_*_amd64.deb 2>/dev/null || true) + fi + if [ -z "$DEB_FILE" ]; then + echo "ERROR: No .deb file found" + exit 1 + fi + dpkg-deb -x "$DEB_FILE" . + ''; + + installPhase = '' + runHook preInstall + mkdir -p "$out" + cp -r opt/* "$out/" + runHook postInstall + ''; + + # fixupPhase: patchelf corrupts Cisco's embedded code signatures on ALL + # shipped ELF binaries and .so plugins. We skip patchelf entirely and + # instead rely on LD_LIBRARY_PATH wrappers for system library resolution. + # The binaries' original RPATH of /opt/cisco/secureclient/lib resolves + # correctly at runtime via the /opt/cisco/secureclient -> store symlink. + fixupPhase = '' + runHook preFixup + + # Fix absolute symlinks — the deb assumes install under /opt/cisco/secureclient/ + # but nix puts it in the store. Convert to relative symlinks. + for link in $(find "$out" -type l); do + target=$(readlink "$link") + if echo "$target" | grep -q "^/opt/"; then + rel=$(basename "$target") + ln -sf "$rel" "$link" + fi + done + + for f in "$out"/cisco/secureclient/bin/* "$out"/cisco/secureclient/lib/*.so*; do + chmod +x "$f" 2>/dev/null || true + done + + # Create libxml2.so.2 symlink (SONAME mismatch: Cisco wants .2, nixpkgs provides .16) + libxml2_so=$(find ${libxml2_out}/lib -name "libxml2.so.16*" 2>/dev/null | head -1) + if [ -n "$libxml2_so" ]; then + ln -sf "$libxml2_so" "$out/cisco/secureclient/lib/libxml2.so.2" + fi + + # NO patchelf on Cisco ELFs — their embedded code signatures are + # verified at runtime (especially plugins loaded by vpnagentd). + # All ELFs keep their original RPATH /opt/cisco/secureclient/lib + # which resolves via the tmpfiles symlink. + # System libs are provided via LD_LIBRARY_PATH in wrappers below. + + ldPath="$out/cisco/secureclient/lib:${sysRpath}" + + # Wrap vpn CLI — wrapProgram renames the original to .vpn-wrapped + wrapProgram "$out/cisco/secureclient/bin/vpn" \ + --prefix LD_LIBRARY_PATH : "$ldPath" \ + --prefix PATH : ${lib.makeBinPath [ coreutils ]} + + # Create $out/bin/ wrappers for all user-facing executables + mkdir -p "$out/bin" + + makeWrapper "$out/cisco/secureclient/bin/vpn" "$out/bin/vpn" \ + --prefix LD_LIBRARY_PATH : "$ldPath" \ + --prefix PATH : ${lib.makeBinPath [ coreutils ]} + + makeWrapper "$out/cisco/secureclient/bin/vpnagentd" "$out/bin/vpnagentd" \ + --prefix LD_LIBRARY_PATH : "$ldPath" \ + --prefix PATH : ${lib.makeBinPath [ coreutils ]} + + for cli in acinstallhelper manifesttool_vpn vpndownloader-cli; do + if [ -f "$out/cisco/secureclient/bin/$cli" ]; then + makeWrapper "$out/cisco/secureclient/bin/$cli" "$out/bin/$cli" \ + --prefix LD_LIBRARY_PATH : "$ldPath" + fi + done + + runHook postFixup + ''; + + meta = with lib; { + description = "Cisco Secure Client (AnyConnect successor) VPN client"; + homepage = "https://www.cisco.com/site/us/en/products/security/secure-client/index.html"; + sourceProvenance = with sourceTypes; [ binaryNativeCode ]; + license = { + name = "Cisco Secure Client EULA — proprietary, not redistributable"; + url = "https://www.cisco.com/c/en/us/products/security/secure-client/eula.html"; + }; + platforms = [ "x86_64-linux" ]; + maintainers = [ ]; + }; +} diff --git a/secrets/age.key b/secrets/age.key deleted file mode 100644 index c969f0c..0000000 --- a/secrets/age.key +++ /dev/null @@ -1,3 +0,0 @@ -# created: 2026-07-12T10:20:38+02:00 -# public key: age1n2kvnwdzrd5vw70wwmm90a4lg6wj3665egzpnz72r98epr0rhc0q3yp356 -AGE-SECRET-KEY-1A49GYAG5AJWGW0XM7HWC8QFE6UUF0S3Z99T252SKX2JHW6NM0HDQESWAQC diff --git a/secrets/aur.age b/secrets/aur.age deleted file mode 100644 index 25239035321f21becb3b8f5bad3adae106d032a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 624 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCU7H})>B3REaCPRwvM z4ht$ZcD4)-_jZYN^mBDf%d!Xx^zf~6tBSD9uJnk^bgayGjO5BGa}23)PA(0K3eGeS zcguAua?6VH$}_19Dsc|8%nOYu(9iRX$O?_hHsR9M)m5Ex_~+L z2eXoL-nx?G^~PM&|6dPL`?g9h&Sb@t-L1Ry=kOgn5PdpC@0hFHTnWGAYl`=$svWmt z_uS%e!gfmU%npu?KK>n7Urk(p;lYbUZ=)oCyK03kQ+Hgv!C+*voj=Or_dAQ&rCJKPRRtj_nTL@X|^XF3Yg7*<-OvzEmc9Mbs4 f%I5IguCH*d7`I{iF%dB3RK7qh;R-G z%&aUd4GJsI3Qfz%$j!+sFRIMe_bw<%b&1MIbhLDHGj?%x3*>S&G>%BgGAi?q$|*3m zbgIb6^2sd>u&l~7F$>U6izwDNi1aBfcJXoc4dl|*)m1R`33T>#*AFf8%L*-ZH89Ms zGO2Ja$xJCXHwrg1DvL;WGAk-FDAG3c@Z_pkxqvgNS7@#_!-?lRJ}+5uJca$vzNypI z=hZBA@!lo1FuR_Yd!4fPt8YgBY@0ZQ&c8D~K2iK>pQ?hm`s>dp+a~^fGbu;&7nkVH z3>~+PpDuk`{72zU`MxjROiU*KmY%U*@JFR_>Y?ox-V6o*&NuI?WZ9eR_QNQD3P;F} z{vBG37o8%PB~M@T%|a`;<4M=FUw3ETwwlm1?_GQ~*Qck6f5RJ{Jj|Vp{nswqKX1yn zBhRMCq;rJ&hsnsX2bwzPf8WHu|I7c-*SsIT?_V-gENS~>SsUxSC&VpoZWApwzudO+ z)wmvMY}>f7y^lha)GPCddLD|p6bZThM3#rox}`zCw0C9Iab z=4HdQC4UFQ?Pu;xc}s%L?ydM1pLWmq>K?847Qx)hc*_jUW;ZLX+10Sz-TL*zRUVR2 zp${w9&C=RY&T>TBjZFR diff --git a/secrets/github_key.age b/secrets/github_key.age deleted file mode 100644 index c1cc51f7810c1b4285aa4ed070b0a18779dcd233..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 624 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCU7H})>B3RH0QH!$~4 zPfRrq%JfK0cQN%&&B{vgC=4quGmCT&bn$g5tH>+OEb}z?h~!Fk40d;^vM|nYFL2H) ziOelZH%iSlcCjcgEwKo!ERS?g&vwa8bBl0E^X1aj)m1Rh4m33lvkdggcP()$D=3L@ z&(yZ?46w|KG%YTP@^UgOGWAai_cF^&Eap0WCw+zM8vR2B-KX6R3&J%2&AefMCs$~C z|7wptkIRldIevVqT~zKDHmz0KJ?ko-x4D$es_3?m&{CQybgzWrehAB{X-B0N%=?=a zm(a#)u*WBDQKMB>{^Nw{j`#BqJ9RGDTW)bx|3{2gs?MzNCw_~RfB*4y3g3VF$-0+$ zGhP?-c}zRZZ*2a@(zjsQb9QB;$jebIep~F;WVqPx{nRnf@c^SGBZtj&gGCDLi$2?4 zI=s`?it!1zxZIo2+~P?h{M8W*KvNnnXN1we~{frPz<_|;`-*n{+PRU3Re0~K zxR>@(^S-(Uzt}1D{EvWbenP+K8!7^}TOYj!TLlr?Cb_~fYPht2$lHYuH6UiYl@ f ssh-ed25519 o3KszQ O4xOtTDK/DH+r81x55jFRFtPAFpTpvCiUcUBy/bm320 -K8kjoDS2ODYJdNZCUmhTfQOWFHEFCkb90d9K5fEnxYo ---- j1a/Uo7QXWC0dnbSGKaRj/T9GkChC7BQf6kYC0HN8f4 -}N ,xoT#cdb,owah@Z&WU]S6T )Yg -/?Ԡ8B£O7zRQي6sfSka$J'jBf,Խc Zn ذogproLIPL gA2L~---T-f>PAa'npPص'ײ.oKn:@̶m~Psŋu[z+ԵCf*+~WXx6(3io~lw;5BjF~En} * dnAڄo#;Dw~h^"zbY֍CPpTQID H_ BBh.+4({3}T3?g{~PτeF,T/_ ̽ diff --git a/secrets/secrets.nix b/secrets/secrets.nix deleted file mode 100644 index 92b314c..0000000 --- a/secrets/secrets.nix +++ /dev/null @@ -1,22 +0,0 @@ -let - host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICL0B9moxOPY4XYim8826M+Tf0sWErwWljz1gkDZPwuF"; -in { - "gitea_laptop.age".publicKeys = [ - host - ]; - "hetzner_server.age".publicKeys = [ - host - ]; - "aur.age".publicKeys = [ - host - ]; - "ssh_config.age".publicKeys = [ - host - ]; - "github_key.age".publicKeys = [ - host - ]; - "sporestack_server.age".publicKeys = [ - host - ]; -} diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml index 4aadba7..c18e494 100644 --- a/secrets/secrets.yaml +++ b/secrets/secrets.yaml @@ -1,25 +1,18 @@ -discordo: "" -openrouter: "" -github: "" -twt: "" -gemini: "" -context7: "" -exa: "" -gitea_laptop: "" -ssh_config: ENC[AES256_GCM,data:TqAUIElmt9nmVC9GuPoo+4/K1VSjxyJdqKe2ra38cJjC66aozIBk5dHyJPgMai/V7jPfYGk366cQUmkE1cvzz/DCw19Xa06YPM2qr93g0FOq0YFu33Vn+33Sx5UAM2QeaTHlIOqqZDBYhJpiOH/5WwCZ/Ai2qInj2G5lH28FiJU5frpImqY2Sq0E6Mhwt3++4+tAcaam+jp1V+PfdcroCULOjpJkbIpNx34TPZPmAtEN/fkkKr6NLj1Jh4RnmdMSW20FHzKSeDKIuDbFdUODRd+jRGo1G6DyujrWV10JrggxR24cfXA15C4nFaEZ6ZHshU1IXoq2msalGqaAHhLetaJaybsWTVpbpkMEozswrkmHiGSHHmq1b6A15i3QVApvFkT02D2Rihs4i3wTPav3zsPdUEUVTGOKI/VQcbJIfckZLZLxLUQjpX+Y62pbsIjtdfF6c/PvCSp5B0+KSZOGvOmZj/RvpDLLeeg5l0tSz5HBaaNPC5LHNuI9Fjabja6EjLhtmZdffOF0yyHjau0AwYYelyjao87gXSz9SuAt5NBvvkB6QifvLJZS6PaNl38OMkDvl1W5n89S8bJVZfmV/1nDZqDdpAPidn0AtT+iKP8As6tuTWnRKATALNqFKMpac3NOAuDWxzB2awhdGBFOJlwjTeepUVZrAbk9sqr9TsNXv8Kr8CyAW59ZL3GmbEik6JN0yuWJioHL4G6TiYbkAK4iIfjhnoyyyUtQhw==,iv:UsyEPs3PbY4rqS2ovBsUUv50ksVUp6UJyKn39i6G5O8=,tag:7s0iZKcLtlUiP7AIP+d5dA==,type:str] -hetzner_server: ENC[AES256_GCM,data:Cb/oa7oDO6nsbxEQmqYHqPP6AEqUHQzHc49axXPJWOkvOb4WMAMh93xVdFzdgPIR1MjLusrD0q2azE6gEQtT+qPbhB0A0/RN/DR49U04UGzWAPltDGlJX+0Z01CL34Kvy6lzOeaVgWLD5Uzg628uGNqL3PKHceJI6Q9lWbH9E19jBGOq86ceXerVlzwDQNyLyrT75O3zOXFy3V0OmG0WDi6pI61ReZVx5HZe3nmxkAMTsRjs+FxA/Yr6hZa0QVqczoZ+i/+qI3RBrWxqUko/A6CGWM/PzMkhw9FCVRoMwRANKoaom2MX+DSDIbg1Bg2JvhUR9oxtNRpO9mj0R6wLlFzA31h9tle0q+7pNxW68G9YDhWUFcxcvb/xFjpSJ7C1kfGQJADpLJoIgT+Fo1XvyiyRKwIXDN2wvAGoCF6gtZcVesN/xhMbmLHPOedHdNrUbSNhZGvR4/mzSlmSLkixddI+r9cXbH/VH+rXd0cCOaqcMEv2FmSRW9z1/y9dPZrpdwg88oouSNzVIE0ANxoARyF8x7mEGNwGHBG1,iv:AreeGiJvChbJDqBdR1L0c/7aqqrfcsQ7ApBpg+0hYOQ=,tag:1lnO8QlFad56basn0NpYmg==,type:str] +gitea_laptop: ENC[AES256_GCM,data:nfiUKIe/+4CuHcv9oBNRFL+gGx2XEvjZlllOVhQYKd00rlffCh1k2BHChdXYziaPVo7SvFkZUX1OLLYqtKC90qMocfSq+6j7hJiTO7RH+DUaAzUEY1bANd6mwh2gl63Xcq3Z65VFRnYvXigJS3QZGykeXNancXjs3TK5pjJZDXgXef7gKzs7yLlnr41Ntk2eiOv08334aa046Qjr6kDjtGd/uUkTzuetMPfGadr/I0VBf0S/SjwSRSzM12CTa7vIz+AbY4pOrZYV+s0bHtuVfE0Xv9WqjC2rA9rqhzrcVfzdbhIEIpADoyhezImcZTzUFQFgaPRoH6ko8GhZKUXPRAmLeMvuzHy1y4kXjsfSixMM2doEfh2lKJTAf1DtAt4OrzXLYt+n5gxCuXdcIMHGP/wfbfmC+Lb1iPZ1ywzICBmBXugNw1KoIMnnr/DjRdqjNQiGQtEd8ylu3VpK7a5OHb0/kW6YQCvtPy5xgYn19LYJUIp8xb4bA2Ty2Bi0FbnfDQbtejUK1bfgz14SQXK6,iv:O+8iWBbXSiyagkfRjzYDxMukBZHfCgxxsEx6C1OBjjQ=,tag:KyzATKtgjutfDmHjR5Gq9g==,type:str] +github_laptop: ENC[AES256_GCM,data:sIiuxSVQyxNIM1BDXx/Wjtdjl7CS9Hdq8tQu9Qdu9fcoDVwNpuidflhb7K7jXmynLJDcAgqSJIBuVngU6mf7nA/k/EmWc8T/+Pl8RUqR/Z85F0Bby/PEULf8pljxiqbolm9fIe9ayThxFJux6tq+cfXiN/omHWxJuMNWgroX6xoxmBla/TDI8VdO1z60wogAJDd0XWp766tFX11iXMuTJhFUKO4Ah3CCHTuIvmXhfMrqdykrulbRgkhoOl/ufNZnJA0cMeg3hjb/yZU29TNaKHXZyeIbP2B/dvEJjNgBQnVoqEL3K4ZZOp4Bo52pdw+wLQ9bQY1hN/XYwi5qNC6G5A0i9r3tmYGeR+6lHIWGaQ0LbFiGmnLQGIeYOU0b7CweJFqJzBDkmfPnglnsRNJtVb7UgBJYGFcLPS0XfVYUVjN0OTqUugeTJSUCAMnWnBlsIgWbrclwe9ilNRPELf7bqXC+Lfcl5vgH1JJRB1Q8m//v+2j764m04Oo4uVZRHqkhA0Jdq/58E2NQpBSM1UNY,iv:cFyGuGa9dWITfJY5rvYe6WIZDouU1ZQ1Lj5x9mU/9wc=,tag:dH5XDlbi4LE8uyAVDMT6dw==,type:str] +hetzner_server: ENC[AES256_GCM,data:YW3eiBJ+4hqBY3BVIcoJicSRz2L+9iZzwVdhpRl/BARtwkkPEohRUUIXY15HqS/DqhcKaojh1YqlUzFh5Z+FKTnizhPNHwWN+Dnz4d9dNTyIdzRkKOp31uYTJi2v2uwoYc60y4wkhHO5dAvWKdHz2qdvXCS9uspfaVpc2k/HasnBmpUODZSfUnLq2bInifDf+lPuJqTVAH0QXo93Nx6IqbgOA0WLfdi6xC3PemzwtqL6dhXUPehF3N4aULfbph/JHnxqQ3LqvDnr8wQsqBfePpFfxpod0rtYnYOwQ/TDEErLIG8d7Idvlzgmr8WFBpgYQuoMyYuDr9PYenpNnbeIF3JesCocsBEw4jpoQT7K1Pd0iVTuvp/41X7gPmYrPviVbWx9X99FeHzUDxhOcNSc/QZ4UtPoLMprlmPK2XQPbQBJyy9KXGNMBW/jERE7Et0cmlx/TVA7tN8T6/Y2vrBlgtmE3m6Fn7ZhtiNFZs4GMbK9KGtmgxwN75yJML3x77Wsleco6nrBcYEghf3LoviwQVjw9KKgwSVLJzW+,iv:rhp4eqmAzmQOAtPy9+ATqth5IKKzk3evJyVw5UtDrSc=,tag:TP/2plD04GU9zKfpesLqeA==,type:str] sops: age: - - recipient: age1vtlutzzhgsy4ef8jd97jaay30zwygj68jwgn0zx64m2d5u57sqzsngy7lf - enc: | + - enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1WUlMWE93cGJxbDY4VzNB - VkVMMXFqZTVXaTFXeFNWdHNJUjV2OE84YVZFClhhK0tUQVlSUXF2NWJFVHFKQXF2 - VUJ5d0t6Um43bmQ5RmExd1QzZ1BxN0EKLS0tIGNnWlZwUkhxbndSRkxia0dFVjVB - TnNEOFBIbU5kSWRCSERQR2hPWnJQM1EKvGPbq3jltkJXL6ExowUeuZ6/WYaBuojX - XzUaNchtd22IhWB50V4IDyl79gb4y0felRS4qe5LQvnvXnjCTwoqyQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYVGxBMmhqdDBmRjlSY2Jp + TVlFKzc3dnM4YUwzZm1iTXY0Q1ROazZQTWc4CjZQZzRIeFYxaGlrSmZTVEFNb21T + M2xGN1ozaEdOak5kQTRYRENXZFpNRmcKLS0tIFhCNHVWejFpeGtCL1cwNi9lU0pq + dzJLbGRzZTlnZVAra2x0SXAvclcrelkKZdnhAPvrqixSbUNfn1Tj7ZYaeCUxfZnf + T9KxEukEKRXMPfCANiQvlG3bM6pPM7L2l8TjTzWOSN/M31cgbiLjyg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-07-12T08:59:50Z" - mac: ENC[AES256_GCM,data:3faasx6fkL6wv9oDDXlxlcbvGIj1D9l2FpkDhYHhyCjN8ZZeRCX4qznos5eLMnDAQUhUZgyvCCXidlHJsYUZcj11p7T0YcGnr+6lzi/p9VkETA2v42BlgXgz0M9nLY0mB6kbAY8JhaJ5fO59DDEhSZRKNgIvzFv2Rv/SoyjpV10=,iv:J1g5R43LOKMSy0V0/cO8eUiuF52ML+2G8gp1WZeOFNM=,tag:PobaSjf5ZPVcNDYmaX02vA==,type:str] + recipient: age1vtlutzzhgsy4ef8jd97jaay30zwygj68jwgn0zx64m2d5u57sqzsngy7lf + lastmodified: "2026-07-12T19:19:12Z" + mac: ENC[AES256_GCM,data:iF2a+wQXiWw4vqOedlZyWda3x66lonwh6WFcB5DdZyXbZzxq8Nvz4POGVYS4ZDwDlWrDhS9RTCX/UyclrHxBslu+rkSUqnOITOABWlnwFPTjGRz4EVMk1MGpRHXL9c8N2O1SS0LnkL8O6+9qsIROkNQVi4nyo4zIYTEfcdxDx+w=,iv:qPf6pl8d4egPitSCheccfiek+WPJVx33cZe81HggBio=,tag:4zXI+g6+vPo0YWOoyud8vw==,type:str] unencrypted_suffix: _unencrypted - version: 3.12.2 + version: 3.13.2 diff --git a/secrets/sporestack_server.age b/secrets/sporestack_server.age deleted file mode 100644 index 676cf66e44b041237ea295237923e8a8e0aea3aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 624 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCU7H})>B3RFlm&NVYJ zHcxe}$_~%6aP4YC*_T_rI(3rnpC|7fFyLafld6Vf7 zGP&gIPX5&`Zi#_UZr&&h-0n5w@}+|C9G(zwHv8qezWe_3Y0i3ZGWnX(DRIX2vKNkt zDO=@yJS4C!#cPH-i`52C(>H5n?)XeBVv9`vqSf{DqNd2r`+LQePwDRw411Jl?9aB= z%e$_VCxOjcY-*>nNW#x(y<=QE9>hid_FfTn>UX_Dm@iXw=RVedPZnx-Dw|GOdOq)l zFTkq5kaCbL9*4ozTBXgWFB@zu`mCj!q8i%E(rdTn3X@NiT1Ozsg`GUA1=((k$(X3*n5l~CybD}m`kLuzQRd0?+i$)*R&2Wc^55+pF(+8(y)`g9 zU~-$u;;i5gfAL(4ub#@Kx9(1qE#HxGIW_VjAM3jBe9peD+oQN$KMgz7LL7muq#e?A0@WQRUYdXSYLEG(nw9=ef(K&7AV9>)p1n zOSL5_UoglJs%m9hzmx5;P}PS+Ef?Bboyx2yf0>e1687lgvLE4lL#8}>{Gx2?LykAo dY+Rzl3?+nJZ~usnGc5Gq`A2B3REyJ$tw%W z^tH@zclS5UHcu_gt12~14NCR1F!4$(P05Z7Ofkqd@kkDhFyL~H@X5|JiZD(!$w^B! z@-I%zG>j}N^7JnaFLsIyHVR724bLty3~(+Daplt0)m6y!a4XA9Dl14c$g;>y$%v{< zjIyW*OY=&0^)j^xEiJRq_YKJnD9kM{E9YVek?7w1PoTWx&Wcr~F}wEZKDfPW#px@D zXMa|#_CL73=}ER<=KgE354fWq9Q}Q%bfZP~xp(4!;yCWjQ?a?MaqBe4!RwE2%Q2lR z^U>ZeP=82UvGM+i%RP5*)b5pvJMdK?X#JGsxBX_>HGeYHxTxg+t8?P7YvNb)*H(xh z?(?1gbpGr&Vuw;Ur6+Sf{Mi4j%}0CR+EuPQ%;VUaYBtI;l&C20@_p5FIlXS-E@q1v zTY|UqYTV2TS#eNenM3_#!#555g7$OfePfFdyS4gGta1LLUEldcK3n^4J@{|;zUqyg zM*46^|CG`ikxTw&E2sXx^TDoG`m?f7U9>LIs`cXS-a-sY2iLM6?Rft;A!N(1`*&Aea!Na_ z`r1Try_fQ#5_131qi!awmHevz i@^+(LKi{pbp0HR|;s0L8>1tD6%ilkzr@UpsSuOyM(!S>a diff --git a/work/cisco.nix b/work/cisco.nix new file mode 100644 index 0000000..f7915f6 --- /dev/null +++ b/work/cisco.nix @@ -0,0 +1,92 @@ +{ config, lib, pkgs, self, ... }: + +# Cisco Secure Client (proprietary VPN client, successor to AnyConnect) +# +# Package: pkgs/cisco-secure-client — fetches the Linux pre-deployment .tgz +# from archive.org and extracts the bundled .deb. +# +# The user can override the source by passing a different package: +# work.cisco.package = pkgs.cisco-secure-client.overrideAttrs (_: { +# src = /path/to/local/cisco-secure-client-linux64-5.1.17.3394-predeploy-deb-k9.tgz; +# }); +# +# Reference: https://github.com/NixOS/nixpkgs/issues/265443 + +let + cfg = config.work.cisco; +in { + options.work.cisco = { + enable = lib.mkEnableOption "Cisco Secure Client" // { + default = true; + }; + + package = lib.mkOption { + description = "cisco-secure-client package to use"; + type = lib.types.package; + default = pkgs.cisco-secure-client; + defaultText = "pkgs.cisco-secure-client"; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + cfg.package + ]; + + # The vpnagentd binary has /opt/cisco/secureclient/ hardcoded for runtime + # config paths (openssl.cnf, ossl-modules/). Create a symlink to the Nix store. + systemd.tmpfiles.rules = [ + "d /opt 0755 root root -" + "L+ /opt/cisco/secureclient - - - - ${cfg.package}/cisco/secureclient" + ]; + + # Load the tun module required by the VPN client + boot.kernelModules = [ "tun" ]; + + systemd.services.cisco-vpnagentd = { + description = "Cisco Secure Client VPN Agent Daemon"; + # vpnagentd daemonizes itself; tracked via PID file. + after = [ "network-online.target" "NetworkManager.service" ]; + wants = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + Type = "forking"; + PIDFile = "/run/vpnagentd.pid"; + # Use the wrapper (sets LD_LIBRARY_PATH) — the raw binary was restored + # from backup to preserve its embedded Cisco code signature, so it has + # no RPATH and needs the env var to find its bundled .so files. + ExecStart = "${cfg.package}/bin/vpnagentd"; + Restart = "on-failure"; + RestartSec = "5"; + + # Minimal capability set for VPN operation + CapabilityBoundingSet = [ + "CAP_NET_ADMIN" + "CAP_NET_RAW" + "CAP_NET_BIND_SERVICE" + "CAP_DAC_OVERRIDE" + "CAP_SETUID" + "CAP_SETGID" + "CAP_CHOWN" + "CAP_FOWNER" + ]; + AmbientCapabilities = [ + "CAP_NET_ADMIN" + "CAP_NET_RAW" + "CAP_NET_BIND_SERVICE" + "CAP_DAC_OVERRIDE" + "CAP_SETUID" + "CAP_SETGID" + "CAP_CHOWN" + "CAP_FOWNER" + ]; + DeviceAllow = [ "/dev/net/tun rw" ]; + PrivateTmp = true; + ProtectSystem = "full"; + ProtectHome = false; + NoNewPrivileges = false; + }; + }; + }; +} diff --git a/work/default.nix b/work/default.nix new file mode 100644 index 0000000..83ec763 --- /dev/null +++ b/work/default.nix @@ -0,0 +1,12 @@ +{ config, lib, ... }: { + imports = [ + ./overlay.nix + ./cisco.nix + ./himmelblau.nix + ]; + + # Create the work directory for the user + systemd.tmpfiles.rules = [ + "d /home/someone/work 0755 someone users -" + ]; +} diff --git a/work/himmelblau.nix b/work/himmelblau.nix new file mode 100644 index 0000000..56b9c79 --- /dev/null +++ b/work/himmelblau.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, inputs, ... }: + +# Himmelblau: Microsoft Entra ID authentication for Linux +# +# Authenticates Linux users against the digistate.nl Entra ID tenant. +# Users log in with their Entra ID credentials via OIDC Device Authorization +# Grant flow (browser-based) or the native PAM orchestrator. +# +# Requires: +# - A working Entra ID tenant with digistate.nl as a verified domain +# - An OIDC app registration (Himmelblau client) in the tenant +# - Network connectivity to login.microsoftonline.com +# +# References: +# - https://himmelblau-idm.org/docs/ +# - https://github.com/himmelblau-idm/himmelblau + +let + cfg = config.work.himmelblau; +in { + options.work.himmelblau = { + enable = lib.mkEnableOption "Himmelblau Entra ID authentication" // { + default = true; + }; + }; + + config = lib.mkIf cfg.enable { + services.himmelblau = { + enable = true; + settings = { + domain = [ "digistate.nl" ]; + # Uncomment and set to Entra ID group Object IDs or names to + # restrict which users can authenticate: + # pam_allow_groups = [ "ENTRA-GROUP-GUID-HERE" ]; + }; + }; + + # Himmelblau registers an NSS module (system.nssModules) for user/group lookups, + # which requires nscd to be enabled. Keep it on. + # services.nscd.enable = lib.mkForce false; + + # Expose the aad-tool CLI for diagnostics and enrollment + environment.systemPackages = [ + inputs.himmelblau.packages.${pkgs.system}.aad-tool + ]; + }; +} diff --git a/work/overlay.nix b/work/overlay.nix new file mode 100644 index 0000000..2f577a0 --- /dev/null +++ b/work/overlay.nix @@ -0,0 +1,9 @@ +{ config, lib, pkgs, ... }: +{ + # Overlay to add cisco-secure-client to pkgs + nixpkgs.overlays = [ + (self: super: { + cisco-secure-client = super.callPackage ./pkgs/cisco-secure-client {}; + }) + ]; +} \ No newline at end of file