phase 3: new flake.nix + extract common-{nix,doas,shell-fish}; rewire imports

- New unified flake with two nixpkgs channels (unstable for desktops, 25.11 for muffin)
- modules/common-{doas,shell-fish,nix}.nix extracted from duplicated blocks
- modules/desktop-common.nix: renamed from system/common.nix; secret paths point to secrets/desktop/
- hosts/{mreow,yarn}/default.nix import desktop-common; yarn imports modules/no-rgb.nix
- hosts/muffin/default.nix imports common-* + server-prefixed modules + services/; duplicate doas/fish/nix blocks removed; gc retention preserved as mkForce override
- modules/age-secrets.nix: file paths → ../secrets/server/*.age
- services/{minecraft,matrix/livekit}: secret paths → ../secrets/server/
- home/profiles/*.nix: ./progs/ → ../progs/
- hosts/{mreow,yarn}/home.nix: imports rewired to ../../home/profiles/ and ../../home/progs/
- home/progs/pi.nix and hosts/yarn/home.nix: secret reads → ../../secrets/home/
- tests/*.nix: ../modules/security.nix → ../modules/server-security.nix; ../modules/overlays.nix → ../lib/overlays.nix
- lib/default.nix: takes explicit lib param (defaults to nixpkgs-stable.lib)
This commit is contained in:
primary
2026-04-18 00:58:55 -04:00
parent 05fd05deda
commit 1719d54ee0
28 changed files with 562 additions and 203 deletions

370
flake.nix Normal file
View File

@@ -0,0 +1,370 @@
{
description = "Unified NixOS flake for mreow (laptop), yarn (desktop), muffin (server)";
inputs = {
# Two channels: unstable for desktops, 25.11 for server.
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.11";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
home-manager-stable = {
url = "github:nix-community/home-manager/release-25.11";
inputs.nixpkgs.follows = "nixpkgs-stable";
};
# Shared across all hosts
lanzaboote = {
url = "github:nix-community/lanzaboote";
inputs.nixpkgs.follows = "nixpkgs";
inputs.rust-overlay.follows = "rust-overlay";
};
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
disko = {
url = "github:nix-community/disko/latest";
inputs.nixpkgs.follows = "nixpkgs";
};
impermanence = {
url = "github:nix-community/impermanence";
inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
};
# Desktop (mreow + yarn)
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
zen-browser = {
url = "github:0xc000022070/zen-browser-flake";
inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
};
firefox-addons = {
url = "gitlab:rycee/nur-expressions?dir=pkgs/firefox-addons";
inputs.nixpkgs.follows = "nixpkgs";
};
niri = {
url = "github:sodiboo/niri-flake";
inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs-stable.follows = "nixpkgs";
};
emacs-overlay = {
url = "github:nix-community/emacs-overlay";
inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs-stable.follows = "nixpkgs";
};
nix-flatpak.url = "github:gmodena/nix-flatpak/";
nix-doom-emacs-unstraightened = {
url = "github:marienz/nix-doom-emacs-unstraightened";
inputs.nixpkgs.follows = "nixpkgs";
inputs.emacs-overlay.follows = "emacs-overlay";
};
jovian-nixos = {
url = "github:Jovian-Experiments/Jovian-NixOS";
inputs.nixpkgs.follows = "nixpkgs";
};
noctalia = {
url = "github:noctalia-dev/noctalia-shell";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-cachyos-kernel = {
url = "github:xddxdd/nix-cachyos-kernel/release";
inputs.nixpkgs.follows = "nixpkgs";
};
llm-agents = {
url = "github:numtide/llm-agents.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
json2steamshortcut = {
url = "github:ChrisOboe/json2steamshortcut";
inputs.nixpkgs.follows = "nixpkgs";
};
# Server (muffin) — follows nixpkgs-stable
nix-minecraft = {
url = "github:Infinidoge/nix-minecraft";
inputs.nixpkgs.follows = "nixpkgs-stable";
};
vpn-confinement.url = "github:Maroka-chan/VPN-Confinement";
llamacpp = {
url = "github:TheTom/llama-cpp-turboquant/feature/turboquant-kv-cache";
inputs.nixpkgs.follows = "nixpkgs-stable";
};
srvos = {
url = "github:nix-community/srvos";
inputs.nixpkgs.follows = "nixpkgs-stable";
};
deploy-rs = {
url = "github:serokell/deploy-rs";
inputs.nixpkgs.follows = "nixpkgs-stable";
};
agenix = {
url = "github:ryantm/agenix";
inputs.nixpkgs.follows = "nixpkgs-stable";
inputs.home-manager.follows = "home-manager-stable";
inputs.darwin.follows = "";
};
senior_project-website = {
url = "github:Titaniumtown/senior-project-website";
flake = false;
};
website = {
url = "git+https://git.sigkill.computer/titaniumtown/website";
flake = false;
};
trackerlist = {
url = "github:ngosang/trackerslist";
flake = false;
};
ytbn-graphing-software = {
url = "git+https://git.sigkill.computer/titaniumtown/YTBN-Graphing-Software";
};
arr-init = {
url = "git+ssh://gitea@git.gardling.com/titaniumtown/arr-init";
inputs.nixpkgs.follows = "nixpkgs-stable";
};
nixpkgs-p2pool-module = {
url = "github:JacoMalan1/nixpkgs/create-p2pool-service";
flake = false;
};
qbittorrent-metrics-exporter = {
url = "git+https://codeberg.org/anriha/qbittorrent-metrics-exporter";
inputs.nixpkgs.follows = "nixpkgs-stable";
};
};
outputs =
inputs@{
self,
nixpkgs,
nixpkgs-stable,
home-manager,
home-manager-stable,
lanzaboote,
nixos-hardware,
disko,
impermanence,
nix-minecraft,
vpn-confinement,
srvos,
deploy-rs,
agenix,
arr-init,
nixpkgs-p2pool-module,
jovian-nixos,
...
}:
let
username = "primary";
system = "x86_64-linux";
niriPackage = inputs.niri.packages.${system}.niri-unstable;
# --- Server (muffin) plumbing ---
bootstrapPkgs = import nixpkgs-stable { inherit system; };
patchedStableSrc = bootstrapPkgs.applyPatches {
name = "nixpkgs-stable-patched";
src = nixpkgs-stable;
patches = [
./patches/nixpkgs/0001-firefox-syncserver-add-postgresql-backend-support.patch
];
};
serverPkgs = import patchedStableSrc {
inherit system;
targetPlatform = system;
buildPlatform = builtins.currentSystem;
};
serviceConfigs = import ./hosts/muffin/service-configs.nix;
serverLib = import ./lib {
inherit inputs;
lib = nixpkgs-stable.lib;
pkgs = serverPkgs;
service_configs = serviceConfigs;
};
testSuite = import ./tests/tests.nix {
pkgs = serverPkgs;
lib = serverLib;
inherit inputs;
config = self.nixosConfigurations.muffin.config;
};
# --- Host builders ---
# Desktop: unstable + home-manager-unstable + niri-unstable
mkDesktopHost =
hostname:
nixpkgs.lib.nixosSystem {
specialArgs = {
inherit inputs username hostname;
niri-package = niriPackage;
};
modules = [
home-manager.nixosModules.home-manager
(
{ config, ... }:
{
home-manager.useUserPackages = true;
home-manager.sharedModules = [
inputs.zen-browser.homeModules.twilight
];
home-manager.extraSpecialArgs = {
inherit
inputs
hostname
username
;
niri-package = niriPackage;
homeDirectory = "/home/${username}";
stateVersion = config.system.stateVersion;
};
home-manager.users.${username} = import ./hosts/${hostname}/home.nix;
}
)
./hosts/${hostname}/default.nix
];
};
# Server: stable + home-manager-stable + srvos + agenix + patched pkgs
muffinHost = serverLib.nixosSystem {
inherit system;
specialArgs = {
inherit
username
inputs
;
hostname = "muffin";
eth_interface = "enp4s0";
service_configs = serviceConfigs;
lib = serverLib;
};
modules = [
# SAFETY! port sanity checks
(
{ config, lib, ... }:
let
publicPorts = lib.attrValues serviceConfigs.ports.public;
privatePorts = lib.attrValues serviceConfigs.ports.private;
allPortNumbers = map (p: p.port) (publicPorts ++ privatePorts);
uniquePortNumbers = lib.unique allPortNumbers;
publicTcp = map (p: p.port) (lib.filter (p: p.proto == "tcp" || p.proto == "both") publicPorts);
publicUdp = map (p: p.port) (lib.filter (p: p.proto == "udp" || p.proto == "both") publicPorts);
privatePortNumbers = map (p: p.port) privatePorts;
fwTcp = config.networking.firewall.allowedTCPPorts;
fwUdp = config.networking.firewall.allowedUDPPorts;
missingTcp = lib.filter (p: !(builtins.elem p fwTcp)) publicTcp;
missingUdp = lib.filter (p: !(builtins.elem p fwUdp)) publicUdp;
leakedTcp = lib.filter (p: builtins.elem p fwTcp) privatePortNumbers;
leakedUdp = lib.filter (p: builtins.elem p fwUdp) privatePortNumbers;
in
{
config.assertions = [
{
assertion = (lib.length allPortNumbers) == (lib.length uniquePortNumbers);
message = "Duplicate port numbers detected in ports.public / ports.private";
}
{
assertion = missingTcp == [ ];
message = "Public ports missing from allowedTCPPorts: ${builtins.toString missingTcp}";
}
{
assertion = missingUdp == [ ];
message = "Public ports missing from allowedUDPPorts: ${builtins.toString missingUdp}";
}
{
assertion = leakedTcp == [ ] && leakedUdp == [ ];
message = "Private ports leaked into firewall allow-lists TCP: ${builtins.toString leakedTcp}, UDP: ${builtins.toString leakedUdp}";
}
];
}
)
srvos.nixosModules.server
srvos.nixosModules.mixins-terminfo
./hosts/muffin/disk.nix
./hosts/muffin/default.nix
# Firefox-syncserver: swap upstream module + package for patched versions.
{
disabledModules = [ "services/networking/firefox-syncserver.nix" ];
imports = [
"${patchedStableSrc}/nixos/modules/services/networking/firefox-syncserver.nix"
];
nixpkgs.overlays = [
nix-minecraft.overlay
(import ./lib/overlays.nix)
(_final: prev: {
syncstorage-rs =
prev.callPackage "${patchedStableSrc}/pkgs/by-name/sy/syncstorage-rs/package.nix"
{ };
})
];
nixpkgs.config.allowUnfreePredicate =
pkg:
builtins.elem (nixpkgs-stable.lib.getName pkg) [
"minecraft-server"
];
}
lanzaboote.nixosModules.lanzaboote
arr-init.nixosModules.default
(import "${nixpkgs-p2pool-module}/nixos/modules/services/networking/p2pool.nix")
home-manager-stable.nixosModules.home-manager
(
{ ... }:
{
home-manager.users.${username} = import ./hosts/muffin/home.nix;
}
)
]
++ (with nixos-hardware.nixosModules; [
common-cpu-amd-pstate
common-cpu-amd-zenpower
common-pc-ssd
common-gpu-intel
]);
};
in
{
formatter.${system} = nixpkgs.legacyPackages.${system}.nixfmt-tree;
nixosConfigurations = {
mreow = mkDesktopHost "mreow";
yarn = mkDesktopHost "yarn";
muffin = muffinHost;
};
deploy.nodes.muffin = {
hostname = "server-public";
profiles.system = {
sshUser = "root";
user = "root";
path = deploy-rs.lib.${system}.activate.nixos self.nixosConfigurations.muffin;
};
};
checks.${system} = testSuite;
packages.${system} = {
tests = serverPkgs.linkFarm "all-tests" (
serverPkgs.lib.mapAttrsToList (name: test: {
name = name;
path = test;
}) testSuite
);
}
// (serverPkgs.lib.mapAttrs' (name: test: {
name = "test-${name}";
value = test;
}) testSuite);
lib = serverLib;
};
}

View File

@@ -7,16 +7,16 @@
{
imports = [
# niri wayland compositor
./progs/niri.nix
../progs/niri.nix
# lockscreen
./progs/swaylock.nix
../progs/swaylock.nix
# notification daemon
./progs/dunst.nix
../progs/dunst.nix
# noctalia desktop shell
./progs/noctalia.nix
../progs/noctalia.nix
];
home.packages = with pkgs; [

View File

@@ -8,12 +8,12 @@
{
imports = [
./no-gui.nix
# ./progs/ghostty.nix
./progs/alacritty.nix
./progs/emacs.nix
# ./progs/trezor.nix # - broken
./progs/flatpak.nix
./progs/zen
# ../progs/ghostty.nix
../progs/alacritty.nix
../progs/emacs.nix
# ../progs/trezor.nix # - broken
../progs/flatpak.nix
../progs/zen
];
nixpkgs.config.allowUnfreePredicate =

View File

@@ -117,9 +117,9 @@ let
in
{
imports = [
./progs/fish.nix
./progs/helix.nix
./progs/pi.nix
../progs/fish.nix
../progs/helix.nix
../progs/pi.nix
(
{ ... }:
{

View File

@@ -23,11 +23,11 @@ let
ompModels = {
providers = {
openrouter = {
apiKey = lib.strings.trim (builtins.readFile ../secrets/openrouter_api_key);
apiKey = lib.strings.trim (builtins.readFile ../../secrets/home/openrouter_api_key);
};
"llama.cpp" = {
baseUrl = "https://llm.sigkill.computer";
apiKey = lib.strings.trim (builtins.readFile ../secrets/llama_cpp_api_key);
apiKey = lib.strings.trim (builtins.readFile ../../secrets/home/llama_cpp_api_key);
api = "openai-responses";
authHeader = true;
discovery.type = "llama.cpp";

View File

@@ -8,8 +8,8 @@
}:
{
imports = [
./common.nix
./disk_mreow.nix
../../modules/desktop-common.nix
./disk.nix
inputs.nixos-hardware.nixosModules.framework-amd-ai-300-series
];

View File

@@ -6,12 +6,12 @@
}:
{
imports = [
./gui.nix
./desktop.nix
./progs/borg.nix
../../home/profiles/gui.nix
../../home/profiles/desktop.nix
../../home/progs/borg.nix
# effects headphones too
# ./progs/framework-13-easyeffects.nix
# ../../home/progs/framework-13-easyeffects.nix
];
# media controls

View File

@@ -11,68 +11,74 @@
}:
{
imports = [
./modules/hardware.nix
./modules/zfs.nix
./modules/impermanence.nix
./modules/usb-secrets.nix
./modules/age-secrets.nix
./modules/secureboot.nix
./modules/no-rgb.nix
./modules/security.nix
./modules/ntfy-alerts.nix
./modules/power.nix
# common across all hosts
../../modules/common-doas.nix
../../modules/common-shell-fish.nix
../../modules/common-nix.nix
./services/postgresql.nix
./services/jellyfin
./services/caddy
./services/immich.nix
./services/gitea.nix
./services/gitea-actions-runner.nix
./services/minecraft.nix
# muffin-only system modules
./hardware.nix
../../modules/zfs.nix
../../modules/server-impermanence.nix
../../modules/usb-secrets.nix
../../modules/age-secrets.nix
../../modules/server-lanzaboote-agenix.nix
../../modules/no-rgb.nix
../../modules/server-security.nix
../../modules/ntfy-alerts.nix
../../modules/server-power.nix
./services/wg.nix
./services/qbittorrent.nix
./services/bitmagnet.nix
../../services/postgresql.nix
../../services/jellyfin
../../services/caddy
../../services/immich.nix
../../services/gitea.nix
../../services/gitea-actions-runner.nix
../../services/minecraft.nix
./services/arr/prowlarr.nix
./services/arr/sonarr.nix
./services/arr/radarr.nix
./services/arr/bazarr.nix
./services/arr/jellyseerr.nix
./services/arr/recyclarr.nix
./services/arr/arr-search.nix
./services/arr/torrent-audit.nix
./services/arr/init.nix
../../services/wg.nix
../../services/qbittorrent.nix
../../services/bitmagnet.nix
./services/soulseek.nix
../../services/arr/prowlarr.nix
../../services/arr/sonarr.nix
../../services/arr/radarr.nix
../../services/arr/bazarr.nix
../../services/arr/jellyseerr.nix
../../services/arr/recyclarr.nix
../../services/arr/arr-search.nix
../../services/arr/torrent-audit.nix
../../services/arr/init.nix
# ./services/llama-cpp.nix
./services/trilium.nix
../../services/soulseek.nix
./services/ups.nix
# ../../services/llama-cpp.nix
../../services/trilium.nix
./services/grafana
../../services/ups.nix
./services/bitwarden.nix
./services/firefox-syncserver.nix
../../services/grafana
./services/matrix
../../services/bitwarden.nix
../../services/firefox-syncserver.nix
./services/monero
../../services/matrix
./services/graphing-calculator.nix
../../services/monero
./services/ssh.nix
../../services/graphing-calculator.nix
./services/syncthing.nix
../../services/ssh.nix
./services/ntfy
../../services/syncthing.nix
./services/mollysocket.nix
../../services/ntfy
./services/harmonia.nix
../../services/mollysocket.nix
./services/ddns-updater.nix
../../services/harmonia.nix
../../services/ddns-updater.nix
];
# Hosts entries for CI/CD deploy targets
@@ -110,17 +116,8 @@
}
];
nix = {
# optimize the store
optimise.automatic = true;
# garbage collection
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 7d";
};
};
# muffin overrides default gc retention (30d in common-nix.nix)
nix.gc.options = lib.mkForce "--delete-older-than 7d";
# Intel Arc A380 (DG2, 56a5) uses the i915 driver on kernel 6.12.
# The xe driver's iHD media driver integration has buffer mapping
@@ -276,31 +273,8 @@
hashedPasswordFile = config.age.secrets.hashedPass.path;
};
# https://nixos.wiki/wiki/Fish#Setting_fish_as_your_shell
programs.fish.enable = true;
programs.bash = {
interactiveShellInit = ''
if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
then
shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
exec ${pkgs.fish}/bin/fish $LOGIN_OPTION
fi
'';
};
security = {
#lets use doas and not sudo!
doas.enable = true;
sudo.enable = false;
# Configure doas
doas.extraRules = [
{
users = [ username ];
keepEnv = true;
persist = true;
}
];
};
# programs.fish + bash→fish redirect and security.doas block are in
# modules/common-shell-fish.nix and modules/common-doas.nix.
services.murmur = {
enable = true;

View File

@@ -8,10 +8,10 @@
}:
{
imports = [
./disk_yarn.nix
./common.nix
../../modules/desktop-common.nix
../../modules/no-rgb.nix
./disk.nix
./impermanence.nix
./no-rgb.nix
./vr.nix
inputs.impermanence.nixosModules.impermanence

View File

@@ -7,8 +7,8 @@
}:
{
imports = [
./gui.nix
./desktop.nix
../../home/profiles/gui.nix
../../home/profiles/desktop.nix
inputs.json2steamshortcut.homeModules.default
];
@@ -31,7 +31,7 @@
services.steam-shortcuts = {
enable = true;
overwriteExisting = true;
steamUserId = lib.strings.toInt (lib.strings.trim (builtins.readFile ./secrets/steam-user-id));
steamUserId = lib.strings.toInt (lib.strings.trim (builtins.readFile ../../secrets/home/steam-user-id));
shortcuts = [
{
AppName = "Prism Launcher";

View File

@@ -2,9 +2,10 @@
inputs,
pkgs,
service_configs,
lib ? inputs.nixpkgs-stable.lib,
...
}:
inputs.nixpkgs.lib.extend (
lib.extend (
final: prev:
let
lib = prev;

View File

@@ -15,7 +15,7 @@
# ZFS encryption key
# path is set to /etc/zfs-key to match the ZFS dataset keylocation property
zfs-key = {
file = ../secrets/zfs-key.age;
file = ../secrets/server/zfs-key.age;
mode = "0400";
owner = "root";
group = "root";
@@ -24,7 +24,7 @@
# Secureboot keys archive
secureboot-tar = {
file = ../secrets/secureboot.tar.age;
file = ../secrets/server/secureboot.tar.age;
mode = "0400";
owner = "root";
group = "root";
@@ -32,7 +32,7 @@
# System passwords
hashedPass = {
file = ../secrets/hashedPass.age;
file = ../secrets/server/hashedPass.age;
mode = "0400";
owner = "root";
group = "root";
@@ -40,7 +40,7 @@
# Service authentication
caddy_auth = {
file = ../secrets/caddy_auth.age;
file = ../secrets/server/caddy_auth.age;
mode = "0400";
owner = "caddy";
group = "caddy";
@@ -48,7 +48,7 @@
# Njalla API token (NJALLA_API_TOKEN=...) for Caddy DNS-01 challenge
njalla-api-token-env = {
file = ../secrets/njalla-api-token-env.age;
file = ../secrets/server/njalla-api-token-env.age;
mode = "0400";
owner = "caddy";
group = "caddy";
@@ -56,21 +56,21 @@
# ddns-updater config.json with Njalla provider credentials
ddns-updater-config = {
file = ../secrets/ddns-updater-config.age;
file = ../secrets/server/ddns-updater-config.age;
mode = "0400";
owner = "ddns-updater";
group = "ddns-updater";
};
jellyfin-api-key = {
file = ../secrets/jellyfin-api-key.age;
file = ../secrets/server/jellyfin-api-key.age;
mode = "0400";
owner = "root";
group = "root";
};
slskd_env = {
file = ../secrets/slskd_env.age;
file = ../secrets/server/slskd_env.age;
mode = "0500";
owner = config.services.slskd.user;
group = config.services.slskd.group;
@@ -78,7 +78,7 @@
# Network configuration
wg0-conf = {
file = ../secrets/wg0.conf.age;
file = ../secrets/server/wg0.conf.age;
mode = "0400";
owner = "root";
group = "root";
@@ -86,14 +86,14 @@
# ntfy-alerts secrets (group-readable for CI runner notifications)
ntfy-alerts-topic = {
file = ../secrets/ntfy-alerts-topic.age;
file = ../secrets/server/ntfy-alerts-topic.age;
mode = "0440";
owner = "root";
group = "gitea-runner";
};
ntfy-alerts-token = {
file = ../secrets/ntfy-alerts-token.age;
file = ../secrets/server/ntfy-alerts-token.age;
mode = "0440";
owner = "root";
group = "gitea-runner";
@@ -101,19 +101,19 @@
# Firefox Sync server secrets (SYNC_MASTER_SECRET)
firefox-syncserver-env = {
file = ../secrets/firefox-syncserver-env.age;
file = ../secrets/server/firefox-syncserver-env.age;
mode = "0400";
};
# MollySocket env (MOLLY_VAPID_PRIVKEY + MOLLY_ALLOWED_UUIDS)
mollysocket-env = {
file = ../secrets/mollysocket-env.age;
file = ../secrets/server/mollysocket-env.age;
mode = "0400";
};
# Murmur (Mumble) server password
murmur-password-env = {
file = ../secrets/murmur-password-env.age;
file = ../secrets/server/murmur-password-env.age;
mode = "0400";
owner = "murmur";
group = "murmur";
@@ -121,7 +121,7 @@
# Coturn static auth secret
coturn-auth-secret = {
file = ../secrets/coturn-auth-secret.age;
file = ../secrets/server/coturn-auth-secret.age;
mode = "0400";
owner = "turnserver";
group = "turnserver";
@@ -129,7 +129,7 @@
# Matrix (continuwuity) registration token
matrix-reg-token = {
file = ../secrets/matrix-reg-token.age;
file = ../secrets/server/matrix-reg-token.age;
mode = "0400";
owner = "continuwuity";
group = "continuwuity";
@@ -138,7 +138,7 @@
# Matrix (continuwuity) TURN secret — same secret as coturn-auth-secret,
# decrypted separately so continuwuity can read it with its own ownership
matrix-turn-secret = {
file = ../secrets/coturn-auth-secret.age;
file = ../secrets/server/coturn-auth-secret.age;
mode = "0400";
owner = "continuwuity";
group = "continuwuity";
@@ -146,7 +146,7 @@
# CI deploy SSH key
ci-deploy-key = {
file = ../secrets/ci-deploy-key.age;
file = ../secrets/server/ci-deploy-key.age;
mode = "0400";
owner = "gitea-runner";
group = "gitea-runner";
@@ -154,7 +154,7 @@
# Git-crypt symmetric key for dotfiles repo
git-crypt-key-dotfiles = {
file = ../secrets/git-crypt-key-dotfiles.age;
file = ../secrets/server/git-crypt-key-dotfiles.age;
mode = "0400";
owner = "gitea-runner";
group = "gitea-runner";
@@ -162,7 +162,7 @@
# Git-crypt symmetric key for server-config repo
git-crypt-key-server-config = {
file = ../secrets/git-crypt-key-server-config.age;
file = ../secrets/server/git-crypt-key-server-config.age;
mode = "0400";
owner = "gitea-runner";
group = "gitea-runner";
@@ -170,7 +170,7 @@
# Gitea Actions runner registration token
gitea-runner-token = {
file = ../secrets/gitea-runner-token.age;
file = ../secrets/server/gitea-runner-token.age;
mode = "0400";
owner = "gitea-runner";
group = "gitea-runner";
@@ -178,7 +178,7 @@
# llama-cpp API key for bearer token auth
llama-cpp-api-key = {
file = ../secrets/llama-cpp-api-key.age;
file = ../secrets/server/llama-cpp-api-key.age;
mode = "0400";
owner = "root";
group = "root";
@@ -186,7 +186,7 @@
# Harmonia binary cache signing key
harmonia-sign-key = {
file = ../secrets/harmonia-sign-key.age;
file = ../secrets/server/harmonia-sign-key.age;
mode = "0400";
owner = "harmonia";
group = "harmonia";
@@ -194,7 +194,7 @@
# Caddy basic auth for nix binary cache (separate from main caddy_auth)
nix-cache-auth = {
file = ../secrets/nix-cache-auth.age;
file = ../secrets/server/nix-cache-auth.age;
mode = "0400";
owner = "caddy";
group = "caddy";

15
modules/common-doas.nix Normal file
View File

@@ -0,0 +1,15 @@
{ username, ... }:
{
# doas replaces sudo on every host
security = {
doas.enable = true;
sudo.enable = false;
doas.extraRules = [
{
users = [ username ];
keepEnv = true;
persist = true;
}
];
};
}

22
modules/common-nix.nix Normal file
View File

@@ -0,0 +1,22 @@
{ lib, ... }:
{
# Common Nix daemon settings. Host-specific overrides (binary cache substituters,
# gc retention) live in the host's default.nix.
nix = {
optimise.automatic = true;
gc = {
automatic = true;
dates = "weekly";
# Default retention: override per-host via lib.mkForce if different.
options = lib.mkDefault "--delete-older-than 30d";
};
settings = {
experimental-features = [
"nix-command"
"flakes"
];
};
};
}

View File

@@ -0,0 +1,16 @@
{ pkgs, lib, ... }:
{
# https://nixos.wiki/wiki/Fish#Setting_fish_as_your_shell
# Login shells stay bash but immediately `exec fish` so fish is the effective shell
# without breaking scripts that hardcode #!/bin/bash.
programs.fish.enable = true;
programs.bash = {
interactiveShellInit = ''
if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
then
shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
exec ${lib.getExe pkgs.fish} $LOGIN_OPTION
fi
'';
};
}

View File

@@ -4,17 +4,21 @@
pkgs,
lib,
username,
system,
hostname,
inputs,
niri-package,
...
}:
{
imports = [
./vm.nix
./steam.nix
./networking.nix
# shared across all hosts
./common-doas.nix
./common-shell-fish.nix
./common-nix.nix
# desktop-only modules
./desktop-vm.nix
./desktop-steam.nix
./desktop-networkmanager.nix
inputs.disko.nixosModules.disko
inputs.lanzaboote.nixosModules.lanzaboote
@@ -59,7 +63,7 @@
#!/usr/bin/env sh
rm -fr ${config.boot.lanzaboote.pkiBundle} || true
mkdir -p ${config.boot.lanzaboote.pkiBundle}
${lib.getExe pkgs.gnutar} xf ${./secrets/secureboot.tar} -C ${config.boot.lanzaboote.pkiBundle}
${lib.getExe pkgs.gnutar} xf ${../secrets/desktop/secureboot.tar} -C ${config.boot.lanzaboote.pkiBundle}
chown -R root:wheel ${config.boot.lanzaboote.pkiBundle}
chmod -R 500 ${config.boot.lanzaboote.pkiBundle}
'';
@@ -67,31 +71,14 @@
swapDevices = [ ];
nix = {
# optimize the store
optimise.automatic = true;
# auto garbage collect old generations
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
settings = {
# enable flakes!
experimental-features = [
"nix-command"
"flakes"
];
# Use muffin server as a binary cache
substituters = [ "https://nix-cache.sigkill.computer" ];
trusted-public-keys = [
"nix-cache.sigkill.computer-1:ONtQC9gUjL+2yNgMWB68NudPySXhyzJ7I3ra56/NPgk="
];
netrc-file = "${./secrets/nix-cache-netrc}";
};
# Desktop-specific Nix cache — muffin serves it, desktops consume.
# Base nix settings (optimise, gc, experimental-features) come from common-nix.nix.
nix.settings = {
substituters = [ "https://nix-cache.sigkill.computer" ];
trusted-public-keys = [
"nix-cache.sigkill.computer-1:ONtQC9gUjL+2yNgMWB68NudPySXhyzJ7I3ra56/NPgk="
];
netrc-file = "${../secrets/desktop/nix-cache-netrc}";
};
# cachyos kernel overlay
@@ -380,20 +367,6 @@
# EST
time.timeZone = "America/New_York";
security = {
# lets use doas and not sudo!
doas.enable = true;
sudo.enable = false;
# Configure doas
doas.extraRules = [
{
users = [ username ];
keepEnv = true;
persist = true;
}
];
};
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
@@ -430,7 +403,7 @@
"adbusers"
];
# TODO! this is really bad :( I should really figure out how to do proper secrets management
hashedPasswordFile = "${./secrets/password-hash}";
hashedPasswordFile = "${../secrets/desktop/password-hash}";
};
services.gvfs.enable = true;
@@ -473,18 +446,6 @@
# wayland with electron/chromium applications
environment.sessionVariables.NIXOS_OZONE_WL = "1";
# https://nixos.wiki/wiki/Fish#Setting_fish_as_your_shell
programs.fish.enable = true;
programs.bash = {
interactiveShellInit = ''
if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
then
shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
exec ${lib.getExe pkgs.fish} $LOGIN_OPTION
fi
'';
};
# port 53317 for localsend
networking.firewall.allowedUDPPorts = [ 53317 ];
networking.firewall.allowedTCPPorts = [ 53317 ];

View File

@@ -3,7 +3,7 @@
...
}:
let
keyFile = ../../secrets/livekit_keys;
keyFile = ../../secrets/server/livekit_keys;
in
{
services.livekit = {

View File

@@ -92,7 +92,7 @@
spawn-protection = 0;
};
whitelist = import ../secrets/minecraft-whitelist.nix;
whitelist = import ../secrets/server/minecraft-whitelist.nix;
symlinks = {
"mods" = pkgs.linkFarmFromDrvs "mods" (

View File

@@ -17,7 +17,7 @@ pkgs.testers.runNixOSTest {
}:
{
imports = [
../modules/security.nix
../modules/server-security.nix
];
# Set up Caddy with basic auth (minimal config, no production stuff)

View File

@@ -53,7 +53,7 @@ pkgs.testers.runNixOSTest {
}:
{
imports = [
../modules/security.nix
../modules/server-security.nix
giteaModule
];

View File

@@ -51,7 +51,7 @@ pkgs.testers.runNixOSTest {
}:
{
imports = [
../modules/security.nix
../modules/server-security.nix
immichModule
];

View File

@@ -51,7 +51,7 @@ pkgs.testers.runNixOSTest {
}:
{
imports = [
../modules/security.nix
../modules/server-security.nix
jellyfinModule
];

View File

@@ -5,7 +5,7 @@
...
}:
let
securityModule = import ../modules/security.nix;
securityModule = import ../modules/server-security.nix;
sshModule =
{

View File

@@ -46,7 +46,7 @@ pkgs.testers.runNixOSTest {
}:
{
imports = [
../modules/security.nix
../modules/server-security.nix
vaultwardenModule
];

View File

@@ -5,7 +5,7 @@
...
}:
let
testPkgs = pkgs.appendOverlays [ (import ../modules/overlays.nix) ];
testPkgs = pkgs.appendOverlays [ (import ../lib/overlays.nix) ];
in
testPkgs.testers.runNixOSTest {
name = "file-perms test";

View File

@@ -22,7 +22,7 @@ let
config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ "minecraft-server" ];
overlays = [
inputs.nix-minecraft.overlay
(import ../modules/overlays.nix)
(import ../lib/overlays.nix)
];
};
in

View File

@@ -5,7 +5,7 @@
...
}:
let
testPkgs = pkgs.appendOverlays [ (import ../modules/overlays.nix) ];
testPkgs = pkgs.appendOverlays [ (import ../lib/overlays.nix) ];
in
testPkgs.testers.runNixOSTest {
name = "ntfy-alerts";

View File

@@ -7,7 +7,7 @@
}:
let
# Create pkgs with ensureZfsMounts overlay
testPkgs = pkgs.appendOverlays [ (import ../modules/overlays.nix) ];
testPkgs = pkgs.appendOverlays [ (import ../lib/overlays.nix) ];
in
testPkgs.testers.runNixOSTest {
name = "zfs test";