Compare commits

..

1 commit

Author SHA1 Message Date
ef43efdf53
flake: Upgrade nixpkgs to nixos-25.11 family
This commit upgrades nixpkgs to nixos-25.11, and all other management
systems (home-manager, nix-darwin, etc.) to the equivalent tag, and also
upgrades any syntax within the modules to follow new syntax.

1. Upgrades nixpkgs to nixos-25.11 2. Upgrades nixpkgs-darwin to
nixpkgs-25.11-darwin 3. Upgrades home-manger to release-25.11 4.
Upgrades nix-darwin to 25.11 5. Implements conditional to use nixpkgs on
Linux and nixpkgs-darwin on Darwin 6. Replace micromamba with mamba-cpp
and set alias, see
https://github.com/NixOS/nixpkgs/issues/456288#issuecomment-3584844923
7. Replace asitop with its new name - macpm 8. Remove ollama package and
launchd service. ollama was removed from Linux in 275270cef7, but
remained in Darwin. The build process technically did not fail, but it
did extend build time and is unused, so it was removed. 9. Switch git
program module to use new syntax
2025-12-02 09:56:36 -06:00
14 changed files with 190 additions and 305 deletions

113
flake.lock generated
View file

@ -27,6 +27,27 @@
"type": "github" "type": "github"
} }
}, },
"crowdsec": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1752497357,
"narHash": "sha256-9epXn1+T6U4Kfyw8B9zMzbERxDB3VfaPXhVebtai6CE=",
"ref": "refs/heads/main",
"rev": "84db7dcea77f7f477d79e69e35fb0bb560232667",
"revCount": 42,
"type": "git",
"url": "https://codeberg.org/kampka/nix-flake-crowdsec.git"
},
"original": {
"type": "git",
"url": "https://codeberg.org/kampka/nix-flake-crowdsec.git"
}
},
"flake-parts": { "flake-parts": {
"inputs": { "inputs": {
"nixpkgs-lib": [ "nixpkgs-lib": [
@ -48,6 +69,23 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"id": "flake-utils",
"type": "indirect"
}
},
"home-manager": { "home-manager": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -90,64 +128,6 @@
"type": "github" "type": "github"
} }
}, },
"nix-rosetta-builder": {
"inputs": {
"nixos-generators": "nixos-generators",
"nixpkgs": [
"nixpkgs-darwin"
]
},
"locked": {
"lastModified": 1756177999,
"narHash": "sha256-aSbB7/jrt7ujiJ55f2uGhOo+usGxVSkqbAMVgg2jDls=",
"owner": "cpick",
"repo": "nix-rosetta-builder",
"rev": "ebb7162a975074fb570a2c3ac02bc543ff2e9df4",
"type": "github"
},
"original": {
"owner": "cpick",
"repo": "nix-rosetta-builder",
"type": "github"
}
},
"nixlib": {
"locked": {
"lastModified": 1736643958,
"narHash": "sha256-tmpqTSWVRJVhpvfSN9KXBvKEXplrwKnSZNAoNPf/S/s=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "1418bc28a52126761c02dd3d89b2d8ca0f521181",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"nixos-generators": {
"inputs": {
"nixlib": "nixlib",
"nixpkgs": [
"nix-rosetta-builder",
"nixpkgs"
]
},
"locked": {
"lastModified": 1737057290,
"narHash": "sha256-3Pe0yKlCc7EOeq1X/aJVDH0CtNL+tIBm49vpepwL1MQ=",
"owner": "nix-community",
"repo": "nixos-generators",
"rev": "d002ce9b6e7eb467cd1c6bb9aef9c35d191b5453",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixos-generators",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1764522689, "lastModified": 1764522689,
@ -258,9 +238,9 @@
"root": { "root": {
"inputs": { "inputs": {
"agenix": "agenix", "agenix": "agenix",
"crowdsec": "crowdsec",
"home-manager": "home-manager", "home-manager": "home-manager",
"nix-darwin": "nix-darwin", "nix-darwin": "nix-darwin",
"nix-rosetta-builder": "nix-rosetta-builder",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"nixpkgs-darwin": "nixpkgs-darwin", "nixpkgs-darwin": "nixpkgs-darwin",
"nixpkgs-unstable": "nixpkgs-unstable", "nixpkgs-unstable": "nixpkgs-unstable",
@ -306,6 +286,21 @@
"repo": "default", "repo": "default",
"type": "github" "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"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -30,6 +30,10 @@
}; };
# Linux-specific inputs # Linux-specific inputs
crowdsec = {
url = "git+https://codeberg.org/kampka/nix-flake-crowdsec.git";
inputs.nixpkgs.follows = "nixpkgs";
};
plasma-manager = { plasma-manager = {
url = "github:nix-community/plasma-manager"; url = "github:nix-community/plasma-manager";
inputs = { inputs = {
@ -44,15 +48,11 @@
url = "github:LnL7/nix-darwin/nix-darwin-25.11"; url = "github:LnL7/nix-darwin/nix-darwin-25.11";
inputs.nixpkgs.follows = "nixpkgs-darwin"; inputs.nixpkgs.follows = "nixpkgs-darwin";
}; };
nix-rosetta-builder = {
url = "github:cpick/nix-rosetta-builder";
inputs.nixpkgs.follows = "nixpkgs-darwin";
};
}; };
outputs = { self, nix-darwin, nixpkgs, nixpkgs-darwin, nixpkgs-unstable outputs = { self, nix-darwin, nixpkgs, nixpkgs-darwin, nixpkgs-unstable
, home-manager, agenix, rycee-nurpkgs, nur, plasma-manager, quadlet-nix , home-manager, agenix, rycee-nurpkgs, nur, crowdsec, plasma-manager
, nix-rosetta-builder, ... }: , quadlet-nix, ... }:
let let
mkHomeConfiguration = { hostname, arch ? "x86_64", os ? "linux" mkHomeConfiguration = { hostname, arch ? "x86_64", os ? "linux"
, desktop ? false, extraModules ? [ ] }: , desktop ? false, extraModules ? [ ] }:
@ -123,11 +123,8 @@
}; };
agenix = agenix; agenix = agenix;
}; };
modules = [ modules =
./systems/darwin/corianne.nix [ ./systems/darwin/corianne.nix agenix.darwinModules.default ];
agenix.darwinModules.default
nix-rosetta-builder.darwinModules.default
];
}; };
nixosConfigurations = { nixosConfigurations = {
@ -150,6 +147,9 @@
agenix.nixosModules.default agenix.nixosModules.default
home-manager.nixosModules.home-manager home-manager.nixosModules.home-manager
quadlet-nix.nixosModules.quadlet quadlet-nix.nixosModules.quadlet
crowdsec.nixosModules.crowdsec
crowdsec.nixosModules.crowdsec-firewall-bouncer
{ nixpkgs.overlays = [ crowdsec.overlays.default ]; }
]; ];
}; };
}; };

View file

@ -22,7 +22,6 @@
nil nil
nixd nixd
nixfmt-classic nixfmt-classic
nixos-rebuild
quarto quarto
roboto-slab roboto-slab
shellcheck shellcheck

View file

@ -1,4 +1,4 @@
{ pkgs, ... }: { { ... }: {
programs.zed-editor = { programs.zed-editor = {
enable = true; enable = true;
extensions = [ extensions = [
@ -58,22 +58,6 @@
initialization_options.formatting.command = [ "nixfmt" ]; initialization_options.formatting.command = [ "nixfmt" ];
settings.nix.flake.autoArchive = true; settings.nix.flake.autoArchive = true;
}; };
texlab = {
settings = {
build = {
onSave = false;
forwardSearchAfter = true;
};
forwardSearch = if pkgs.stdenv.hostPlatform.isDarwin then {
executable =
"/Applications/Skim.app/Contents/SharedSupport/displayline";
args = [ "-r" "%l" "%p" "%f" "-g" ];
} else {
executable = "/usr/bin/okular";
args = [ "--unique" "file:%p#src:%l%f" ];
};
};
};
tinymist = { tinymist = {
settings = { settings = {
exportPdf = "onSave"; exportPdf = "onSave";
@ -97,12 +81,5 @@
ui_font_size = 16; ui_font_size = 16;
wrap_guides = [ 80 92 120 ]; wrap_guides = [ 80 92 120 ];
}; };
userTasks = [{
label = "latexmk (project)";
command = "latexmk";
args = [ "-synctex=1" "-pdf" "-recorder" ];
cwd = "$ZED_DIRNAME";
tags = [ "latex-build" ];
}];
}; };
} }

View file

@ -34,8 +34,7 @@ in {
++ [ mcentire-host ]; ++ [ mcentire-host ];
"secrets/darwin-policies-json.age".publicKeys = system-administrators "secrets/darwin-policies-json.age".publicKeys = system-administrators
++ [ corianne-host ]; ++ [ corianne-host ];
"secrets/freshrss.toml.age".publicKeys = system-administrators
++ [ mcentire-host ];
"secrets/network-information.age".publicKeys = system-administrators "secrets/network-information.age".publicKeys = system-administrators
++ [ bosephus-host ]; ++ [ bosephus-host ];
"secrets/pihole.age".publicKeys = system-administrators ++ [ bosephus-host ];
} }

Binary file not shown.

BIN
secrets/pihole.age Normal file

Binary file not shown.

View file

@ -1,49 +1,101 @@
{ pkgs, config, ... }: { { pkgs, config, ... }:
let
crowdsec-port = "2763";
firewall-bouncer-name = "fw-bouncer";
# Although this key can be reproduced by anyone who actually cares to, the
# Crowdsec API will not be exposed to the outside world, so keeping this key
# super secret really isn't that important to me. Still make it look random
# so that hungry botnets can't just slurp up the password in plaintext.
firewall-bouncer-key = builtins.hashString "sha256"
"${config.networking.hostName}-crowdsec-bouncer-salt";
toMultiYAML = items:
pkgs.lib.concatMapStrings (item:
''
---
'' + (pkgs.lib.generators.toYAML { } item) + "\n") items;
in {
services = { services = {
crowdsec = { crowdsec = {
enable = true; enable = true;
localConfig = { allowLocalJournalAccess = true;
acquisitions = [
{
source = "journalctl";
journalctl_filter = [ "_SYSTEMD_UNIT=sshd.service" ];
labels.type = "syslog";
}
{
filenames = [ "/var/log/auth.log" ];
labels.type = "syslog";
}
{
filenames = [ "/var/log/syslog" "/var/log/kern.log" ];
labels.type = "syslog";
}
];
};
hub = {
collections = [
"crowdsecurity/base-http-scenarios"
"crowdsecurity/http-cve"
"crowdsecurity/http-dos"
"crowdsecurity/iptables"
"crowdsecurity/linux"
"crowdsecurity/sshd"
"crowdsecurity/whitelist-good-actors"
];
};
settings = { settings = {
general = { api.server.enable = true; }; api.server = { listen_uri = "127.0.0.1:${crowdsec-port}"; };
# See https://github.com/NixOS/nixpkgs/issues/445342 crowdsec_service.acquisition_path = pkgs.writeText "acquisitions.yaml"
lapi.credentialsFile = "/var/lib/crowdsec/lapi-credentials.yaml"; (toMultiYAML [
{
source = "journalctl";
journalctl_filter = [ "_SYSTEMD_UNIT=sshd.service" ];
labels.type = "syslog";
}
{
filenames = [ "/var/log/auth.log" ];
labels.type = "syslog";
}
{
filenames = [ "/var/log/syslog" "/var/log/kern.log" ];
labels.type = "syslog";
}
]);
}; };
autoUpdateService = true;
}; };
crowdsec-firewall-bouncer = { crowdsec-firewall-bouncer = {
enable = true; enable = true;
registerBouncer.enable = true; settings = {
api_url = "http://localhost:${crowdsec-port}";
api_key = firewall-bouncer-key;
};
}; };
}; };
systemd.tmpfiles.rules = let cfg = config.services.crowdsec; systemd.services.crowdsec.serviceConfig = {
in [ "d /var/lib/crowdsec 0755 ${cfg.user} ${cfg.group}" ]; ExecStartPre = let
bouncer-script = pkgs.writeScriptBin "register-bouncer" ''
#!${pkgs.runtimeShell}
set -eu
set -o pipefail
if ! cscli bouncers list | grep -q "${firewall-bouncer-name}"; then
cscli bouncers add "${firewall-bouncer-name}" --key "${firewall-bouncer-key}"
fi
'';
collection-check = collection: ''
if ! cscli collections list | grep -q "${collection}"; then
cscli collections --trace install "${collection}"
sleep 1
fi
'';
collections = [
"crowdsecurity/base-http-scenarios"
"crowdsecurity/http-cve"
"crowdsecurity/http-dos"
"crowdsecurity/iptables"
"crowdsecurity/linux"
"crowdsecurity/sshd"
"crowdsecurity/whitelist-good-actors"
];
collection-script = pkgs.writeScriptBin "install-collections" ''
#!${pkgs.runtimeShell}
set -eu
set -o pipefail
# I had to run these commands in order to manually install collections
# using cscli.
# Not sure how often they should actually be run, but I would rather
# include this here.
# https://discourse.crowdsec.net/t/solved-cant-find-collections-appsec/1830
cscli capi register
sleep 1
cscli hub update
sleep 1
${pkgs.lib.concatMapStrings collection-check collections}
'';
in [
"${bouncer-script}/bin/register-bouncer"
"${collection-script}/bin/install-collections"
];
};
} }

View file

@ -1,146 +0,0 @@
{ config, pkgs, home-manager-quadlet-nix, ... }:
let
user = "freshrss";
port = "37374";
stateDirectory = "/var/lib/freshrss";
serviceContainer = "freshrss";
stateSubDir = subDir: "${stateDirectory}/${subDir}";
createTmpfilesRule = subDir: "d ${stateSubDir subDir} 1755 ${user} ${user}";
dbDirectories = [ "database" ];
serviceDirectories = [ "data" "extensions" ];
in {
age.secrets = {
"freshrss.toml" = {
file = ./../secrets/freshrss.toml.age;
owner = "${user}";
};
};
millironx.podman-secrets.freshrss = {
user = "${user}";
secrets-files = [ config.age.secrets."freshrss.toml".path ];
};
services.caddy.virtualHosts."feeds.millironx.com".extraConfig = ''
reverse_proxy http://127.0.0.1:${port} {
header_up X-Forwarded-Port 443
}
'';
systemd.tmpfiles.rules = builtins.map createTmpfilesRule
([ stateDirectory ] ++ dbDirectories ++ serviceDirectories);
services.borgmatic.configurations."${config.networking.hostName}" = {
source_directories = builtins.map stateSubDir dbDirectories;
postgresql_databases = [{
name = serviceContainer;
psql_command =
"/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec ${serviceContainer}-db psql --username=${user}";
pg_dump_command =
"/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec ${serviceContainer}-db pg_dump --username=${user}";
pg_restore_command =
"/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec ${serviceContainer}-db pg_restore --username=${user}";
}];
};
users.users."${user}" = {
group = "${user}";
isNormalUser = true;
home = "${stateDirectory}";
createHome = true;
linger = true;
autoSubUidGidRange = true;
};
users.groups."${user}" = { };
home-manager.users."${user}" = { config, osConfig, ... }: {
imports = [ home-manager-quadlet-nix ];
home.stateVersion = "25.05";
virtualisation.quadlet = let
inherit (config.virtualisation.quadlet) containers;
inherit (config.virtualisation.quadlet) networks;
secrets = osConfig.millironx.podman-secrets.freshrss;
in {
containers = {
"${serviceContainer}-db" = {
autoStart = true;
containerConfig = {
image = "docker.io/library/postgres:16";
environments = {
POSTGRES_DB = "${user}";
POSTGRES_USER = "${user}";
};
secrets = [
"POSTGRES_PASSWORD,type=env"
"POSTGRES_PASSWORD,type=env,target=PGPASSWORD"
];
healthCmd = "pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}";
healthInterval = "30s";
healthRetries = 5;
healthStartPeriod = "20s";
volumes =
[ "${stateDirectory}/database:/var/lib/postgresql/data:U" ];
networks = [ networks."${serviceContainer}".ref ];
};
unitConfig.Requires = [ secrets.ref ];
unitConfig.After = [ secrets.ref ];
};
"${serviceContainer}" = {
autoStart = true;
containerConfig = {
image = "docker.io/freshrss/freshrss:1";
# Required to allow the container to talk to the host ports, in
# other words, to resolve Authentik correctly
addHosts = [ "auth.millironx.com:host-gateway" ];
environments = {
TZ = osConfig.time.timeZone;
CRON_MIN = "2,32";
LISTEN = "0.0.0.0:${port}";
TRUSTED_PROXY = "172.16.0.1/12 192.168.0.1/16";
OIDC_ENABLED = "1";
OIDC_PROVIDER_METADATA_URL =
"https://auth.millironx.com/application/o/freshrss/.well-known/openid-configuration";
OIDC_REMOTE_USER_CLAIM = "preferred_username";
OIDC_SCOPES = "openid email profile";
OIDC_X_FORWARDED_HEADERS =
"X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto";
};
secrets = [
"OIDC_CLIENT_ID,type=env"
"OIDC_CLIENT_SECRET,type=env"
"OIDC_CLIENT_CRYPTO_KEY,type=env"
];
healthCmd = "cli/health.php";
healthTimeout = "10s";
healthStartPeriod = "60s";
healthStartupInterval = "11s";
healthInterval = "75s";
healthRetries = 3;
networks = [ networks."${serviceContainer}".ref ];
publishPorts = [ "127.0.0.1:${port}:${port}" ];
volumes = [
"${stateDirectory}/data:/var/www/FreshRSS/data:U"
"${stateDirectory}/extensions:/var/www/FreshRSS/extensions:U"
];
};
unitConfig.Requires =
[ secrets.ref containers."${serviceContainer}-db".ref ];
unitConfig.After =
[ secrets.ref containers."${serviceContainer}-db".ref ];
};
};
networks."${serviceContainer}" = { };
autoUpdate.enable = true;
autoEscape = true;
};
};
}

27
services/pihole.nix Normal file
View file

@ -0,0 +1,27 @@
{ config, ... }:
{
age.secrets = {
pihole-credentials = {
file = ./../secrets/pihole.age;
owner = "root";
group = "root";
};
};
virtualisation = {
quadlet = {
containers = {
pihole = {
containerConfig = {
image = "docker.io/pihole/pihole:2025.06.2";
publishPorts =
[ "53:53/tcp" "53:53/udp" "80:80/tcp" "443:443/tcp" ];
environmentFiles = [ config.age.secrets.pihole-credentials.path ];
networks = [ "bridge" ];
dns = [ "127.0.0.1" "194.242.2.9" "9.9.9.9" ];
};
};
};
};
};
}

View file

@ -2,6 +2,7 @@
services.samba = { services.samba = {
enable = true; enable = true;
package = pkgs.sambaFull; package = pkgs.sambaFull;
securityType = "user";
openFirewall = true; openFirewall = true;
settings = { settings = {
global = { global = {

View file

@ -26,27 +26,9 @@ in {
}; };
# Auto upgrade nix package and the daemon service. # Auto upgrade nix package and the daemon service.
nix = { nix.enable = true;
enable = true; #services.nix-daemon.tempDir = "/nix/tmp";
gc = { nix.package = pkgs.nix;
automatic = true;
interval = { Weekday = 1; };
options = ''
--delete-older-than 14d
'';
};
# Needed for rosetta-builder, see
# <https://github.com/cpick/nix-rosetta-builder/issues/40#issuecomment-3368602687>
# <https://github.com/cpick/nix-rosetta-builder/issues/37>
linux-builder = {
enable = true;
ephemeral = true;
};
extraOptions = ''
extra-platforms = x86_64-darwin
'';
};
nix-rosetta-builder.onDemand = true;
# Create /etc/zshrc that loads the nix-darwin environment. # Create /etc/zshrc that loads the nix-darwin environment.
programs.zsh.enable = true; # default shell on catalina programs.zsh.enable = true; # default shell on catalina
@ -224,7 +206,6 @@ in {
"rig" "rig"
"rstudio" "rstudio"
"signal" "signal"
"skim"
"slack" "slack"
"stats" "stats"
"steam" "steam"

View file

@ -9,6 +9,7 @@
./hardware-configuration/bosephus.nix ./hardware-configuration/bosephus.nix
./hardware-configuration/bosephus-external-drives.nix ./hardware-configuration/bosephus-external-drives.nix
./../../services/samba.nix ./../../services/samba.nix
./../../services/pihole.nix
]; ];
# Bootloader. # Bootloader.
@ -16,8 +17,8 @@
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;
# Ignore lid - so I can close without having the system go into sleep mode # Ignore lid - so I can close without having the system go into sleep mode
services.logind.settings.Login.HandleLidSwitch = "ignore"; services.logind.lidSwitch = "ignore";
services.logind.settings.Login.HandleLidSwitchDocked = "ignore"; services.logind.lidSwitchDocked = "ignore";
# Secrets # Secrets
age.secrets = { age.secrets = {

View file

@ -7,7 +7,6 @@
./../../services/borgmatic.nix ./../../services/borgmatic.nix
./../../services/crowdsec.nix ./../../services/crowdsec.nix
./../../services/authentik.nix ./../../services/authentik.nix
./../../services/freshrss.nix
]; ];
# Use the GRUB 2 boot loader. # Use the GRUB 2 boot loader.