From 23ef05f355d0fd1a06d55e30c28dd422bb1d4215 Mon Sep 17 00:00:00 2001 From: Lorenz Leutgeb Date: Tue, 20 May 2025 03:14:09 +0200 Subject: [PATCH] Initial Commit --- .sops.yaml | 15 + flake.lock | 727 +++++++++++++++++++++++++++++++++ flake.nix | 176 ++++++++ lib.nix | 21 + os/host/xyz/seed/default.nix | 141 +++++++ os/host/xyz/seed/radicle.nix | 40 ++ os/host/xyz/seed/sops/ssh.yaml | 44 ++ os/host/xyz/seed/ssh.nix | 33 ++ os/host/xyz/seed/tor.nix | 6 + os/mixin/kmscon.nix | 11 + os/mixin/motd.nix | 16 + os/mixin/nix.nix | 38 ++ os/mixin/sops.nix | 13 + os/mixin/users.nix | 52 +++ 14 files changed, 1333 insertions(+) create mode 100644 .sops.yaml create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 lib.nix create mode 100644 os/host/xyz/seed/default.nix create mode 100644 os/host/xyz/seed/radicle.nix create mode 100644 os/host/xyz/seed/sops/ssh.yaml create mode 100644 os/host/xyz/seed/ssh.nix create mode 100644 os/host/xyz/seed/tor.nix create mode 100644 os/mixin/kmscon.nix create mode 100644 os/mixin/motd.nix create mode 100644 os/mixin/nix.nix create mode 100644 os/mixin/sops.nix create mode 100644 os/mixin/users.nix diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..96fcc65 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,15 @@ +seys: + - &lorenz age1c0g6s6daxy79dlm9uqczwlkh0hvjpghw5h8zzljc3vs275rvvqus30hv9l + # Taken from `heartwood/.gitsigners`: + - &fintan age15fd8ljdtzkphz3gf9ezpz58u5fhc7260h68nn32znn4m00ank45skd3luy + # Taken from `heartwood/.gitsigners`: + - &erik age1kygyyrr6m43lgmy8pq57nc0jfmzr38uv8p5udg956p39ghs4qvnsdzs6nm + - &seed age1jemy54kqt4xgglg5f3g3sda5tndsqhjynvdugpy0yknefnw69u7qwymfj4 +creation_rules: + - path_regex: os/host/xyz/seed/sops/[^/]+\.(bin|json|yaml)$ + key_groups: + - age: + - *lorenz + - *fintan + - *erik + - *seed \ No newline at end of file diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..80e0cd3 --- /dev/null +++ b/flake.lock @@ -0,0 +1,727 @@ +{ + "nodes": { + "advisory-db": { + "flake": false, + "locked": { + "lastModified": 1723137097, + "narHash": "sha256-Q/TeuIV610BJ39UkP4zRm6pG6BWEaOCih/WXNR2V9rk=", + "owner": "rustsec", + "repo": "advisory-db", + "rev": "1d209d3f18c740f104380e988b5aa8eb360190d1", + "type": "github" + }, + "original": { + "owner": "rustsec", + "repo": "advisory-db", + "type": "github" + } + }, + "authentik": { + "inputs": { + "authentik-src": "authentik-src", + "flake-compat": [ + "lorenz", + "compat" + ], + "flake-parts": "flake-parts", + "flake-utils": [ + "lorenz", + "utils" + ], + "napalm": "napalm", + "nixpkgs": [ + "lorenz", + "nixpkgs" + ], + "pyproject-build-systems": "pyproject-build-systems", + "pyproject-nix": "pyproject-nix", + "systems": "systems", + "uv2nix": "uv2nix" + }, + "locked": { + "lastModified": 1746874492, + "narHash": "sha256-Gm2Eb5KBxAL6y9WJj7phRMXNAZzVkKlm9Dky9WDZHtQ=", + "owner": "nix-community", + "repo": "authentik-nix", + "rev": "2ef24fac993808a1a57f367ef58ac0f5254c3489", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "authentik-nix", + "type": "github" + } + }, + "authentik-src": { + "flake": false, + "locked": { + "lastModified": 1745954192, + "narHash": "sha256-QuIgeu3CN6S44/zSiaj+iIkDz2494mb1MWvD3eYYkVE=", + "owner": "goauthentik", + "repo": "authentik", + "rev": "22412729e2379d645da2ac0c0270a0ac6147945e", + "type": "github" + }, + "original": { + "owner": "goauthentik", + "ref": "version/2025.4.0", + "repo": "authentik", + "type": "github" + } + }, + "compat": { + "locked": { + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "crane": { + "inputs": { + "nixpkgs": [ + "lorenz", + "radicle-tui", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1722960479, + "narHash": "sha256-NhCkJJQhD5GUib8zN9JrmYGMwt4lCRp6ZVNzIiYCl0Y=", + "owner": "ipetkov", + "repo": "crane", + "rev": "4c6c77920b8d44cd6660c1621dea6b3fc4b4c4f4", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1743550720, + "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c621e8422220273271f52058f618c94e405bb0f5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "garnix-lib": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1746387091, + "narHash": "sha256-YivN7BL4XkZIJpUTdDJRQpYX/JORVdbZTQbSnULgRnY=", + "owner": "garnix-io", + "repo": "garnix-lib", + "rev": "4cc103317aef34dd99617ed9ff12c44d659d86d0", + "type": "github" + }, + "original": { + "owner": "garnix-io", + "repo": "garnix-lib", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "hardware": { + "locked": { + "lastModified": 1746814339, + "narHash": "sha256-hf2lICJzwACWuzHCmZn5NI6LUAOgGdR1yh8ip+duyhk=", + "owner": "NixOS", + "repo": "nixos-hardware", + "rev": "3c5e12673265dfb0de3d9121420c0c2153bf21e0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixos-hardware", + "type": "github" + } + }, + "hm": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1747688838, + "narHash": "sha256-FZq4/3OtGV/cti9Vccsy2tGSUrxTO4hkDF9oeGRTen4=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "45c2985644b60ab64de2a2d93a4d132ecb87cf66", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "hm_2": { + "inputs": { + "nixpkgs": [ + "lorenz", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1746798521, + "narHash": "sha256-axfz/jBEH9XHpS7YSumstV7b2PrPf7L8bhWUtLBv3nA=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "e95a7c5b6fa93304cd2fd78cf676c4f6d23c422c", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "lorenz": { + "inputs": { + "authentik": "authentik", + "compat": [ + "compat" + ], + "hardware": "hardware", + "hm": "hm_2", + "nix-index-database": "nix-index-database", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": [ + "nixpkgs-stable" + ], + "nixpkgs-unstable": [ + "nixpkgs-unstable" + ], + "pre-commit-hooks": [ + "pre-commit-hooks" + ], + "radicle-tui": "radicle-tui", + "rust-overlay": "rust-overlay_2", + "sbt": "sbt", + "sops": [ + "sops" + ], + "utils": [ + "utils" + ], + "vscode-server": "vscode-server", + "wsl": "wsl" + }, + "locked": { + "lastModified": 1746913738, + "narHash": "sha256-/BtmdQs81VWLO5/2mq2iqfb0MX69lk+J7K/uVLb+Ntw=", + "owner": "lorenzleutgeb", + "repo": "nur", + "rev": "abd85271a4c3e63c1a06daf3e13b4269615f571d", + "type": "github" + }, + "original": { + "owner": "lorenzleutgeb", + "repo": "nur", + "type": "github" + } + }, + "napalm": { + "inputs": { + "flake-utils": [ + "lorenz", + "authentik", + "flake-utils" + ], + "nixpkgs": [ + "lorenz", + "authentik", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1725806412, + "narHash": "sha256-lGZjkjds0p924QEhm/r0BhAxbHBJE1xMOldB/HmQH04=", + "owner": "willibutz", + "repo": "napalm", + "rev": "b492440d9e64ae20736d3bec5c7715ffcbde83f5", + "type": "github" + }, + "original": { + "owner": "willibutz", + "ref": "avoid-foldl-stack-overflow", + "repo": "napalm", + "type": "github" + } + }, + "nix-index-database": { + "inputs": { + "nixpkgs": [ + "lorenz", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1746330942, + "narHash": "sha256-ShizFaJCAST23tSrHHtFFGF0fwd72AG+KhPZFFQX/0o=", + "owner": "Mic92", + "repo": "nix-index-database", + "rev": "137fd2bd726fff343874f85601b51769b48685cc", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "nix-index-database", + "type": "github" + } + }, + "nix-index-database_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1747540584, + "narHash": "sha256-cxCQ413JTUuRv9Ygd8DABJ1D6kuB/nTfQqC0Lu9C0ls=", + "owner": "Mic92", + "repo": "nix-index-database", + "rev": "ec179dd13fb7b4c6844f55be91436f7857226dce", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "nix-index-database", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1743296961, + "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1746557022, + "narHash": "sha256-QkNoyEf6TbaTW5UZYX0OkwIJ/ZMeKSSoOMnSDPQuol0=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "1d3aeb5a193b9ff13f63f4d9cc169fb88129f860", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1746592047, + "narHash": "sha256-GYYT5Pc+sZZWomgC7EgDSNSfmXd9Jby9nXQ6bAswUCg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "8fcc71459655f2486b3da197b8d6a62f595a33d2", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": [ + "compat" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1746537231, + "narHash": "sha256-Wb2xeSyOsCoTCTj7LOoD6cdKLEROyFAArnYoS+noCWo=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "fa466640195d38ec97cf0493d6d6882bc4d14969", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pyproject-build-systems": { + "inputs": { + "nixpkgs": [ + "lorenz", + "authentik", + "nixpkgs" + ], + "pyproject-nix": [ + "lorenz", + "authentik", + "pyproject-nix" + ], + "uv2nix": [ + "lorenz", + "authentik", + "uv2nix" + ] + }, + "locked": { + "lastModified": 1744599653, + "narHash": "sha256-nysSwVVjG4hKoOjhjvE6U5lIKA8sEr1d1QzEfZsannU=", + "owner": "pyproject-nix", + "repo": "build-system-pkgs", + "rev": "7dba6dbc73120e15b558754c26024f6c93015dd7", + "type": "github" + }, + "original": { + "owner": "pyproject-nix", + "repo": "build-system-pkgs", + "type": "github" + } + }, + "pyproject-nix": { + "inputs": { + "nixpkgs": [ + "lorenz", + "authentik", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1746146146, + "narHash": "sha256-60+mzI2lbgn+G8F5mz+cmkDvHFn4s5oqcOna1SzYy74=", + "owner": "pyproject-nix", + "repo": "pyproject.nix", + "rev": "3e9623bdd86a3c545e82b7f97cfdba5f07232d9a", + "type": "github" + }, + "original": { + "owner": "pyproject-nix", + "repo": "pyproject.nix", + "type": "github" + } + }, + "radicle-tui": { + "inputs": { + "advisory-db": "advisory-db", + "crane": "crane", + "flake-utils": [ + "lorenz", + "utils" + ], + "nixpkgs": [ + "lorenz", + "nixpkgs" + ], + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1744642603, + "narHash": "sha256-XG4qsL9aSPNJ/raXbcRwTqdOK4ZjGhe0maPi8FgL7Kc=", + "ref": "main", + "rev": "227bd3b15b6dbbdcf64408240f50f3db37853453", + "revCount": 825, + "type": "git", + "url": "https://seed.radicle.xyz/z39mP9rQAaGmERfUMPULfPUi473tY.git" + }, + "original": { + "ref": "main", + "type": "git", + "url": "https://seed.radicle.xyz/z39mP9rQAaGmERfUMPULfPUi473tY.git" + } + }, + "root": { + "inputs": { + "compat": "compat", + "garnix-lib": "garnix-lib", + "hm": "hm", + "lorenz": "lorenz", + "nix-index-database": "nix-index-database_2", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "nixpkgs-stable": "nixpkgs-stable", + "nixpkgs-unstable": "nixpkgs-unstable", + "pre-commit-hooks": "pre-commit-hooks", + "sops": "sops", + "utils": "utils" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "lorenz", + "radicle-tui", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1723170066, + "narHash": "sha256-SFkQfOA+8AIYJsPlQtxNP+z5jRLfz91z/aOrV94pPmw=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "fecfe4d7c96fea2982c7907997b387a6b52c1093", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_2": { + "inputs": { + "nixpkgs": [ + "lorenz", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1746844454, + "narHash": "sha256-GcUWDQUDRYrD34ol90KGUpjbVcOfUNbv0s955jPecko=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "be092436d4c0c303b654e4007453b69c0e33009e", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "sbt": { + "inputs": { + "flake-utils": [ + "lorenz", + "utils" + ], + "nixpkgs": [ + "lorenz", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1698464090, + "narHash": "sha256-Pnej7WZIPomYWg8f/CZ65sfW85IfIUjYhphMMg7/LT0=", + "owner": "zaninime", + "repo": "sbt-derivation", + "rev": "6762cf2c31de50efd9ff905cbcc87239995a4ef9", + "type": "github" + }, + "original": { + "owner": "zaninime", + "repo": "sbt-derivation", + "type": "github" + } + }, + "sops": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1746485181, + "narHash": "sha256-PxrrSFLaC7YuItShxmYbMgSuFFuwxBB+qsl9BZUnRvg=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "e93ee1d900ad264d65e9701a5c6f895683433386", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "uv2nix": { + "inputs": { + "nixpkgs": [ + "lorenz", + "authentik", + "nixpkgs" + ], + "pyproject-nix": [ + "lorenz", + "authentik", + "pyproject-nix" + ] + }, + "locked": { + "lastModified": 1746048139, + "narHash": "sha256-LdCLyiihLg6P2/mjzP0+W7RtraDSIaJJPTy6SCtW5Ag=", + "owner": "pyproject-nix", + "repo": "uv2nix", + "rev": "680e2f8e637bc79b84268949d2f2b2f5e5f1d81c", + "type": "github" + }, + "original": { + "owner": "pyproject-nix", + "repo": "uv2nix", + "type": "github" + } + }, + "vscode-server": { + "inputs": { + "flake-utils": [ + "lorenz", + "utils" + ], + "nixpkgs": [ + "lorenz", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1711042850, + "narHash": "sha256-8PDNi/dgoI2kyM7uSiU4eoLBqUKoA+3TXuz+VWmuCOc=", + "owner": "Ten0", + "repo": "nixos-vscode-server", + "rev": "b02b3cceaae22fb66c00f03f1aff705e9711956e", + "type": "github" + }, + "original": { + "owner": "Ten0", + "repo": "nixos-vscode-server", + "type": "github" + } + }, + "wsl": { + "inputs": { + "flake-compat": [ + "lorenz", + "compat" + ], + "nixpkgs": [ + "lorenz", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1746453552, + "narHash": "sha256-r66UGha+7KVHkI7ksrcMjnw/mm9Sg4l5bQlylxHwdGU=", + "owner": "nix-community", + "repo": "nixos-wsl", + "rev": "be618645aa0adf461f778500172b6896d5ab2d01", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixos-wsl", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..5a50a08 --- /dev/null +++ b/flake.nix @@ -0,0 +1,176 @@ +{ + description = "Lorenz Leutgeb's Flake"; + inputs = { + # This looks redundant, but actually is nice. + # Allows to model "stable" vs. "unstable" vs. "don't care". + # Don't forget to also adjust the URL for home-manager below + # accordingly. + nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; + nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.11"; + nixpkgs.follows = "nixpkgs-unstable"; + + hm = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + garnix-lib = { + url = "github:garnix-io/garnix-lib"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + compat.url = "github:edolstra/flake-compat"; + sops = { + url = "github:Mic92/sops-nix"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; + utils.url = "github:numtide/flake-utils"; + pre-commit-hooks = { + url = "github:cachix/pre-commit-hooks.nix"; + inputs = { + flake-compat.follows = "compat"; + nixpkgs.follows = "nixpkgs"; + }; + }; + + nix-index-database = { + url = "github:Mic92/nix-index-database"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + lorenz = { + url = "github:lorenzleutgeb/nur"; + inputs = { + nixpkgs.follows = "nixpkgs"; + nixpkgs-stable.follows = "nixpkgs-stable"; + nixpkgs-unstable.follows = "nixpkgs-unstable"; + sops.follows = "sops"; + compat.follows = "compat"; + utils.follows = "utils"; + pre-commit-hooks.follows = "pre-commit-hooks"; + }; + }; + }; + + outputs = inputs @ { + self, + garnix-lib, + hm, + nix-index-database, + nixpkgs, + nixpkgs-unstable, + pre-commit-hooks, + sops, + ... + }: let + lib = nixpkgs.lib.recursiveUpdate nixpkgs.lib (import ./lib.nix {inherit (nixpkgs) lib;}); + + inherit + (lib) + attrValues + dirToAttrs + nameValuePair + mapAttrs + mapAttrs' + ; + + inherit + (builtins) + readDir + ; + + system = "x86_64-linux"; + + modules = { + input = [ + garnix-lib.nixosModules.garnix + hm.nixosModules.home-manager + nixpkgs.nixosModules.notDetected + sops.nixosModules.sops + ]; + }; + + homeModules.input = [ + nix-index-database.hmModules.nix-index + sops.homeManagerModule + ]; + + pkgs = import nixpkgs { + inherit system; + }; + + host = preconfig: let + result = lib.nixosSystem { + specialArgs = { + inherit self inputs lib; + }; + modules = + modules.input + ++ [ + { + system.stateVersion = "23.11"; + system.configurationRevision = + pkgs.lib.mkIf (self ? rev) self.rev; + nix.registry = { + nixpkgs-unstable = { + from = { + id = "nixpkgs-unstable"; + type = "indirect"; + }; + flake = nixpkgs-unstable; + }; + }; + nixpkgs = { + config.allowUnfree = true; + }; + + home-manager = { + users.lorenz.imports = homeModules.input; + + useGlobalPkgs = true; + useUserPackages = false; + backupFileExtension = "bak"; + extraSpecialArgs = { + inherit inputs self; + }; + }; + } + preconfig + ]; + }; + in + result; + in { + nixosConfigurations."seed.radicle.xyz" = host (import ./os/host/xyz/seed); + + devShells.${system}.default = pkgs.mkShell { + inherit (self.checks.${system}.pre-commit) shellHook; + buildInputs = self.checks.${system}.pre-commit.enabledPackages; + }; + + formatter.${system} = pkgs.writeShellApplication { + name = "formatter"; + text = '' + # shellcheck disable=all + shell-hook () { + ${self.checks.${system}.pre-commit.shellHook} + } + + shell-hook + pre-commit run --all-files + ''; + }; + + checks.${system} = + { + pre-commit = pre-commit-hooks.lib.${system}.run { + src = ./.; + hooks = { + alejandra.enable = true; + }; + }; + } + #// (mapAttrs' (name: value: nameValuePair "packages/${name}" value) self.packages.${system}) + // (mapAttrs' (name: value: nameValuePair "nixosConfigurations/${name}" value.config.system.build.toplevel) self.nixosConfigurations); + }; +} diff --git a/lib.nix b/lib.nix new file mode 100644 index 0000000..d95fcc8 --- /dev/null +++ b/lib.nix @@ -0,0 +1,21 @@ +{lib}: let + inherit + (lib) + listToAttrs + attrNames + replaceStrings + ; + inherit + (builtins) + readDir + ; +in rec { + kebabCaseToCamelCase = + replaceStrings (map (s: "-${s}") lib.lowerChars) lib.upperChars; + + dirToAttrs = dir: + listToAttrs (map (name: { + name = kebabCaseToCamelCase (lib.removeSuffix ".nix" name); + value = dir + "/${name}"; + }) (attrNames (readDir dir))); +} diff --git a/os/host/xyz/seed/default.nix b/os/host/xyz/seed/default.nix new file mode 100644 index 0000000..77dabc0 --- /dev/null +++ b/os/host/xyz/seed/default.nix @@ -0,0 +1,141 @@ +{ + self, + config, + pkgs, + lib, + modulesPath, + ... +}: { + imports = [ + ../../../mixin/kmscon.nix + ../../../mixin/nix.nix + ../../../mixin/motd.nix + ../../../mixin/sops.nix + ../../../mixin/users.nix + + ./ssh.nix + ./tor.nix + ./radicle.nix + + (modulesPath + "/profiles/qemu-guest.nix") + ]; + + # /var/lib/radicle /mnt/HC_Volume_30473554/heartwood/.radicle/ + + systemd.network.enable = true; + + fileSystems = + (builtins.listToAttrs (map + ({ + subvol, + mountpoint ? "/${subvol}", + }: { + name = mountpoint; + value = { + device = "/dev/disk/by-uuid/e55dc01e-ecab-4cd2-ad08-e773615f36fd"; + fsType = "btrfs"; + options = ["compress=zstd" "discard=async" "noatime" "subvol=${subvol}"]; + }; + }) [ + { + mountpoint = "/"; + subvol = "root"; + } + {subvol = "home";} + {subvol = "nix";} + ])) + // { + "/boot" = { + device = "/dev/disk/by-uuid/5d17c66f-46fc-484d-be63-b21786e61af9"; + fsType = "ext2"; + }; + }; + + boot = { + kernel.sysctl."net.ipv4.ip_forward" = 1; + loader.grub = { + enable = true; + efiSupport = false; + device = "/dev/disk/by-uuid/5d17c66f-46fc-484d-be63-b21786e61af9"; + }; + + initrd.availableKernelModules = [ + "ata_piix" + "uhci_hcd" + "virtio_pci" + "sr_mod" + "virtio_blk" + + "ahci" + "xhci_pci" + "virtio_scsi" + "sd_mod" + ]; + }; + + # The global useDHCP flag is deprecated, therefore explicitly set to false here. + # Per-interface useDHCP will be mandatory in the future, so this generated config + # replicates the default behaviour. + networking = { + hostName = "seed"; + domain = "radicle.xyz"; + useNetworkd = true; + useDHCP = false; + + firewall = { + allowedTCPPorts = [ + 22 # ssh + 443 # https + ]; + }; + }; + + # Select internationalisation properties. + # i18n.defaultLocale = "en_US.UTF-8"; + # console = { + # font = "Lat2-Terminus16"; + # keyMap = "us"; + # }; + + # Set your time zone. + time.timeZone = "UTC"; + i18n.defaultLocale = "en_US.UTF-8"; + + environment.systemPackages = with pkgs; [ + coreutils-full + dmidecode + exfat + libvirt + lshw + lsof + nfs-utils + utillinux + which + config.boot.kernelPackages.perf + ]; + + services = { + accounts-daemon.enable = true; + resolved.enable = true; + + caddy = { + enable = true; + email = "team@radicle.xyz"; + virtualHosts = { + # TODO: Remove once radicle-httpd is up. + "https://${config.networking.fqdn}".extraConfig = "respond `${builtins.toJSON { + rev = self.rev or self.dirtyRev; + inherit (self) lastModified; + }}`"; + }; + }; + }; + + networking.interfaces.enp1s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = "x86_64-linux"; + + security = { + sudo.wheelNeedsPassword = false; + }; +} diff --git a/os/host/xyz/seed/radicle.nix b/os/host/xyz/seed/radicle.nix new file mode 100644 index 0000000..dc214d2 --- /dev/null +++ b/os/host/xyz/seed/radicle.nix @@ -0,0 +1,40 @@ +{config, ...}: { + fileSystems."/var/lib/radicle" = { + device = "/dev/disk/by-id/scsi-0HC_Volume_30473554"; + fsType = "ext4"; + options = ["discard" "defaults"]; + }; + + services.radicle = { + enable = true; + privateKeyFile = "/etc/ssh/ssh_host_ed25519_key"; + publicKey = "/etc/ssh/ssh_host_ed25519_key.pub"; + settings = { + node = { + alias = config.networking.fqdn; + externalAddresses = [ + "${config.networking.fqdn}:8776" + ]; + peers = { + type = "dynamic"; + target = 8; + }; + db.journalMode = "wal"; + workers = 32; + relay = "always"; + }; + web.pinned.repositories = [ + "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5" + "rad:z371PVmDHdjJucejRoRYJcDEvD5pp" + "rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5" + "rad:z3TajuiHXifEDEX4qbJxe8nXr9ufi" + "rad:z3trNYnLWS11cJWC6BbxDs5niGo82" + "rad:z6cFWeWpnZNHh9rUW8phgA3b5yGt" + "rad:z39mP9rQAaGmERfUMPULfPUi473tY" + "rad:zwTxygwuz5LDGBq255RA2CbNGrz8" + "rad:z3qg5TKmN83afz2fj9z3fQjU8vaYE" + "rad:z4D5UCArafTzTQpDZNQRuqswh3ury" + ]; + }; + }; +} diff --git a/os/host/xyz/seed/sops/ssh.yaml b/os/host/xyz/seed/sops/ssh.yaml new file mode 100644 index 0000000..b474135 --- /dev/null +++ b/os/host/xyz/seed/sops/ssh.yaml @@ -0,0 +1,44 @@ +ssh: + key: ENC[AES256_GCM,data:KjPrmSW5uIZ8BZqfM710+x0U5KiPRjwyX9VWbRoxfG3mpcesN1hQm2tUCuSmBk7e0HttuHI0sVX4lv6jcAG5pH8wWTISyOIytzOToZnO17gKU4T2P4dufly0+94PJAmeuMUlNJBTxDLbUIM1rxwatfdKpGEW6NT/0ki0Jwpm6kfc2oUsVsj/YvrBgdzjRR2wligdj9LlNR51Q52vwFEWBqKsOiJFoXaYANV4nH/2Bvtpt9K+ky+0ekUf5Pfacs5wHoUt0pnjCo1hZlR4IZrXyvktzHTlB1IRM2xAXJMTycOcvqedBwWZRnzPm1JOXKoKBBk1jvBlOblO8RCYvSawnMeJuLBuq79IrtKrkmdtXBIU85sCGr/Eur9CRclcCBUOHreNI6jsIxDUYtVUrnqwBuI4C/cZwwqkkGVeAn5OKAXoMOvJyTeadvoX4sK0Jiw/yZpWleBy8v0qZ/YMwryYEhUxu26QcL8ymMPl98k2xtYBr1qpcCHbwzNYA1TU2siCmXcYseLAERSTNy8nK4MbclZ68bOvyazIBIdCr5R7nNl33r3p1eEBLKmpr7bn56b2O+IyGMRE0VQvPSsB,iv:wbmX5MPvrZKehE1lNCoL1V0y6i87uS6VVNJ4ijpOPgc=,tag:/82F0SLAfy9DdWEIHB1vLQ==,type:str] +sops: + age: + - recipient: age1c0g6s6daxy79dlm9uqczwlkh0hvjpghw5h8zzljc3vs275rvvqus30hv9l + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkQXU3d3cxVEFaRm9ROTlC + bHE4VUREamJkMnZveWFxem9ZTnY0SGRtRFZZCk5tbTNXWWZITVZPdzRlNGNnV1pk + T2xhUzUySk5vN2NDY0JVclFwUFM0ZTgKLS0tIG5Pd29Fazk3SFdCWGJ5NlVqaXQ3 + WUE0RjVPSDhwYk1KZDhHU0ZXZ3ZtK28KxrvCTc/tOh+sBlIDx//X+kkKt9bWnU6Y + /wctm5gK+D3Bkol+l4hfAPmvn2GU34lEoZkOEBA2IhHTLZzNc7+vjw== + -----END AGE ENCRYPTED FILE----- + - recipient: age15fd8ljdtzkphz3gf9ezpz58u5fhc7260h68nn32znn4m00ank45skd3luy + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6aFdoRXNHcmR0ekI1ZytN + VytjdGhlNjZqZFZQd3hyWWZnS1BoRmZmN1c0Ckx3cWFhVnFZT0VtU1R4RGJjcmZi + T0RETWtVMFVRNTVOMWQ2aVFnY2NGdFkKLS0tIE85bmRPVjBZenIxenk5cWtvT0Q5 + UUdkekZQMVpVYlhudVBteTM3NTdONjgKruh5uLD5cikj6Wx2NvZyduazhl7wRkWP + 4MJxRjMhbmYY0vsa9oJ0xN1LFcpV6tVr7n8D1GapsJwO6bcETwfT8A== + -----END AGE ENCRYPTED FILE----- + - recipient: age1kygyyrr6m43lgmy8pq57nc0jfmzr38uv8p5udg956p39ghs4qvnsdzs6nm + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwZExEc2lsY1RCVmM2eElu + OGozMjJEb29UdkJ6RXNtSytFQ1hlZUx5R0VVCkFaMmRlTGd3UnBBNVJNOFdVWG54 + MkRIc25yVWRMdTdoN01qQTZUTTN4R0EKLS0tIFR2MlRCd2N5SXd6UDVCNC8wekhv + SG9IVlh5eU9jNHFWWSttenFBUG96RDQKzVuI9+WuiCbfQuYsW9uysI9Qs6XqpEXa + gSmaNseJoDtlOVocYRE0EkOy9JhaCih1CwZqrByIfgBUG9g2y3VdNQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age1jemy54kqt4xgglg5f3g3sda5tndsqhjynvdugpy0yknefnw69u7qwymfj4 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzODc1YUd2QUNxcko1R3ow + ZG1IejJHb2oySk1EQzNDbTdzRnoyWmxZbGtnCmZvNDdJNDlZTDVuR2dsN1ZlZFl3 + MXpqNU52ek5jbUVaZHdmWGVSSlNOOWcKLS0tIHZHR1pXU1p0Z3JWQ1pSbE82SW14 + ZXZGT2UzRzlXVElaazhRY3RHbXE4MFUKGirCy5kdGzxXgjis6tYKi6JoTI0H16al + Pic4ZAIO6U6H+Q39hobW/gAl9wU7s+pf3fxrzJRI1twIQNPa3zc2rQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-05-19T22:10:45Z" + mac: ENC[AES256_GCM,data:/Nj6F8rt20KcRFjRiOcxAFNgms6nT08V4w+EU5E7l/CY+KFLrffn+lV/wwLDrMR1m8frdSOPNMayO2V2v9D8dXbXmdVPfb+/AqOU3RTT5cAJ60ZCtoiXIxVtj3Z0QeXpNMA0QvS0h9O9C7KBXf53T2WPxLVKausHwHqyUIWCQjc=,iv:ZaF/0DPy5h7tbigqDHgQvHb+5PzGB8WsdX7MxY4vX9k=,tag:+JDo+a8P9rpGZ+Bsy++dkg==,type:str] + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/os/host/xyz/seed/ssh.nix b/os/host/xyz/seed/ssh.nix new file mode 100644 index 0000000..f152a0d --- /dev/null +++ b/os/host/xyz/seed/ssh.nix @@ -0,0 +1,33 @@ +{ + pkgs, + config, + lib, + ... +}: { + services = { + openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + }; + + hostKeys = [ + { + path = "/etc/ssh/ssh_host_ed25519_key"; + type = "ed25519"; + } + ]; + }; + + sshguard.enable = true; + }; + + sops = { + age.sshKeyPaths = map (x: x.path) config.services.openssh.hostKeys; + secrets = { + "ssh/key".sopsFile = ./sops/ssh.yaml; + }; + }; + + environment.etc."ssh/ssh_host_ed25519_key.pub".text = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMXpC2X07TCIslR907omxrk6J+K3p0rGOMaJAHe1K2i3 ${config.networking.fqdn}"; +} diff --git a/os/host/xyz/seed/tor.nix b/os/host/xyz/seed/tor.nix new file mode 100644 index 0000000..3e3831f --- /dev/null +++ b/os/host/xyz/seed/tor.nix @@ -0,0 +1,6 @@ +{ + services.tor = { + enable = true; + client.enable = true; + }; +} diff --git a/os/mixin/kmscon.nix b/os/mixin/kmscon.nix new file mode 100644 index 0000000..770caaa --- /dev/null +++ b/os/mixin/kmscon.nix @@ -0,0 +1,11 @@ +{pkgs, ...}: { + services.kmscon = { + enable = true; + fonts = [ + { + name = "Fira Code"; + package = pkgs.fira-code; + } + ]; + }; +} diff --git a/os/mixin/motd.nix b/os/mixin/motd.nix new file mode 100644 index 0000000..135ba6b --- /dev/null +++ b/os/mixin/motd.nix @@ -0,0 +1,16 @@ +{ + config, + inputs, + self, + pkgs, + ... +}: { + users.motdFile = "/etc/motd"; + environment.etc.motd.text = '' + 👾 ${config.networking.fqdn} + + Radicle ${pkgs.radicle-node.version} ${pkgs.radicle-node.src.rev} + NixOS ${config.system.nixos.release} ${inputs.nixpkgs.rev} + • ${self.rev or self.dirtyRev} + ''; +} diff --git a/os/mixin/nix.nix b/os/mixin/nix.nix new file mode 100644 index 0000000..f3ad77b --- /dev/null +++ b/os/mixin/nix.nix @@ -0,0 +1,38 @@ +{ + config, + pkgs, + ... +}: { + environment = { + etc."nix/inputs/nixpkgs".source = pkgs.path; + systemPackages = [ + pkgs.nil + ]; + }; + + nixpkgs.config.allowUnfree = true; + + nix = { + nixPath = ["nixpkgs=/etc/${config.environment.etc."nix/inputs/nixpkgs".target}"]; + settings = { + auto-optimise-store = true; + }; + extraOptions = '' + allow-import-from-derivation = true + experimental-features = nix-command flakes + builders-use-substitutes = true + log-lines = 30 + max-silent-time = 600 + timeout = 7200 + #pure-eval = true + #use-xdg-base-directories = true + + # NOTE: Disabling URL literals is desired, but breaks + # evaluation of ngipkgs as of 2023-08-23. Bring it back + # once ngipkgs evaluates with it. + # See . + # experimental-features = no-url-literals + ''; + gc.automatic = true; + }; +} diff --git a/os/mixin/sops.nix b/os/mixin/sops.nix new file mode 100644 index 0000000..348bc49 --- /dev/null +++ b/os/mixin/sops.nix @@ -0,0 +1,13 @@ +{ + config, + pkgs, + ... +}: { + sops.age.sshKeyPaths = map (x: x.path) (builtins.filter (x: x.type == "ed25519") config.services.openssh.hostKeys); + + environment.systemPackages = with pkgs; [ + age + sops + ssh-to-age + ]; +} diff --git a/os/mixin/users.nix b/os/mixin/users.nix new file mode 100644 index 0000000..8d882e5 --- /dev/null +++ b/os/mixin/users.nix @@ -0,0 +1,52 @@ +{ + pkgs, + inputs, + ... +}: { + home-manager.users.lorenz.imports = [ + "${inputs.lorenz}/hm/profiles/terminal.nix" + ]; + + users.users = { + lorenz = { + isNormalUser = true; + createHome = true; + home = "/home/lorenz"; + description = "Lorenz"; + extraGroups = ["disk" "docker" "wheel"]; + uid = 1000; + shell = pkgs.dash; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFhK7CqgIIbSthoNn8ea32krOnMzC807Z+PpBkR2YOVj" + ]; + }; + + fintan = { + isNormalUser = true; + createHome = true; + home = "/home/fintan"; + description = "Fintan"; + extraGroups = ["disk" "docker" "wheel"]; + uid = 1001; + shell = pkgs.zsh; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOl44zVBYvu1Uhmq9nshhic4r1Moz5fdNOoWTtdJrUwd" + ]; + }; + + erik = { + isNormalUser = true; + createHome = true; + home = "/home/erik"; + description = "Erik"; + extraGroups = ["disk" "docker" "wheel"]; + uid = 1002; + shell = pkgs.bash; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBrJyJTwj/xG7F7qY0HDFXbb8A+xNNH8eILQ8hlvKW7/" + ]; + }; + }; + + programs.zsh.enable = true; +}