incorporated john-p14s, big squash merge of stuff

This commit is contained in:
John Lancaster
2026-03-29 15:12:38 -05:00
parent 31df60a718
commit 93458a5e53
37 changed files with 924 additions and 419 deletions
+16
View File
@@ -0,0 +1,16 @@
# This module is for programs with GUIs that run in a desktop environment
{ self, inputs, ... }: {
flake.modules.homeManager.desktop = { config, pkgs, lib, ... }: {
imports = with inputs.self.modules.homeManager; [
brave
ghostty
onepassword
vscode
];
home.packages = with pkgs; [
mangohud
sublime4
proton-vpn
];
};
}
+107
View File
@@ -0,0 +1,107 @@
{ inputs, ... }: {
flake.modules.nixos.gnome = {pkgs, ... }: {
services = {
desktopManager.gnome.enable = true;
displayManager.gdm = {
enable = true;
wayland = true;
banner = "Welcome to John's NixOS implementation";
};
udev.packages = [
pkgs.gnome-settings-daemon # For gnome systray icons
];
};
};
flake.modules.homeManager.gnome = { config, pkgs, ... }:
let
# `gnome-extensions list` for a list
extensions = with pkgs.gnomeExtensions; [
appindicator # For gnome systray icons
dash-to-panel
gtile
space-bar
switcher
tactile
vitals
];
enabledExtensions = map (ext: ext.extensionUuid) extensions;
in
{
gtk = {
enable = true;
theme = {
name = "Orchis-Dark";
package = pkgs.orchis-theme;
};
gtk4.theme = config.gtk.theme;
};
home.packages = [ pkgs.gnome-tweaks ] ++ extensions;
dconf.settings = {
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
};
"org/gnome/shell" = {
disable-user-extensions = false;
enabled-extensions = enabledExtensions;
};
"org/gnome/desktop/wm/preferences" = {
button-layout = ":minimize,close";
};
"org/gnome/desktop/wm/keybindings" = {
"switch-to-workspace-1" = ["<Super>1"];
"switch-to-workspace-2" = ["<Super>2"];
"switch-to-workspace-3" = ["<Super>3"];
"switch-to-workspace-4" = ["<Super>4"];
"move-to-workspace-1" = ["<Shift><Super>1"];
"move-to-workspace-2" = ["<Shift><Super>2"];
"move-to-workspace-3" = ["<Shift><Super>3"];
"move-to-workspace-4" = ["<Shift><Super>4"];
};
"org/gnome/settings-daemon/plugins/media-keys" = {
custom-keybindings = [
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/edit-nix/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch-browser/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/ad-dev/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/shutdown/"
];
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/edit-nix" = {
binding = "<Primary><Alt>n";
command = "code /etc/nixos";
name = "Edit Nix config";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/launch-browser" = {
binding = "<Primary><Alt>b";
command = "brave";
name = "Launch Brave browser";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/ad-dev" = {
binding = "<Primary><Alt>d";
command = ''code --file-uri "vscode-remote://ssh-remote+ad-nix/etc/nixos/ad-nix.code-workspace"'';
name = "Launch AppDaemon Development over Tailscale";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/ws1" = {
binding = "<Super>1";
command = "wmctrl -s 0";
name = "Switch to workspace 1";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/shutdown" = {
binding = "<Primary><Alt>p";
command = "gnome-session-quit --power-off --force";
name = "Shutdown immediately";
};
};
};
}
+28
View File
@@ -0,0 +1,28 @@
# https://github.com/glabrie/dotfiles/blob/main/modules/system/settings/greetd.nix
{ inputs, ... }: {
flake.module.nixos.greetd = { pkgs, lib, ... }: {
services.greetd = {
enable = true;
settings = {
default_session = {
command = "${lib.getExe pkgs.tuigreet} --time --remember --cmd niri-session";
user = "greeter";
};
};
};
systemd.services.greetd.serviceConfig = {
Type = "idle";
StandardInput = "tty";
StandardOutput = "tty";
StandardError = "journal"; # Without this errors will spam on screen
# Without these bootlogs will spam on screen
TTYReset = true;
TTYVHangup = true;
TTYVTDisallocate = true;
};
# Let's allow our keyring to work from the start
security.pam.services.greetd.enableGnomeKeyring = true;
};
}
+334
View File
@@ -0,0 +1,334 @@
{ self, inputs, lib, ... }:
let
# Options that will be in common between
opts = {
enable = lib.mkEnableOption "Enable mTLS";
subject = lib.mkOption {
description = "The Common Name, DNS Name, or IP address that will be set as the Subject Common Name for the certificate. If no Subject Alternative Names (SANs) are configured (via the --san flag) then the subject will be set as the only SAN.";
type = lib.types.str;
};
certDir = lib.mkOption {
description = "String path to the directory where the certs will be stored";
type = lib.types.str;
};
keyFilename = lib.mkOption {
description = "String filename for the private key";
type = lib.types.str;
default = "key.pem";
};
certFilename = lib.mkOption {
description = "String filename for the public certificate";
type = lib.types.str;
default = "cert.pem";
};
bundleFilename = lib.mkOption {
description = "String filename for the mTLS key bundle";
type = lib.types.str;
default = "mtls.pem";
};
san = lib.mkOption {
description = "List of SAN to give the mTLS cert";
type = lib.types.listOf lib.types.str;
default = [ ];
};
provisioner = lib.mkOption {
type = lib.types.str;
default = "admin";
};
lifetime = lib.mkOption {
type = lib.types.str;
default = "6h";
};
renew = {
enable = lib.mkOption {
description = "Enable automatic mTLS certificate renewal using a systemd timer.";
type = lib.types.bool;
default = true;
};
onCalendar = lib.mkOption {
description = "systemd OnCalendar schedule for mTLS certificate renewal checks.";
type = lib.types.str;
default = "*:1/15";
};
randomizedDelaySec = lib.mkOption {
description = "Randomized delay added to renewal timer runs to avoid synchronized renewals.";
type = lib.types.str;
default = "5m";
};
user = lib.mkOption {
description = "User account to run the mTLS renewal service as.";
type = lib.types.str;
default = "root";
};
group = lib.mkOption {
description = "Group to run the mTLS renewal service as. Defaults to the configured renewal user when null.";
type = lib.types.nullOr lib.types.str;
default = null;
};
reloadUnits = lib.mkOption {
description = "systemd units to try-reload-or-restart after a successful certificate renewal.";
type = lib.types.listOf lib.types.str;
default = [ ];
};
postCommands = lib.mkOption {
description = "Shell commands to run after a successful certificate renewal.";
type = lib.types.listOf lib.types.lines;
default = [ ];
};
};
};
mkMtlsGenerateScript = {
pkgs,
subject,
provisioner,
san,
tlsCert,
tlsKey,
mtlsBundle,
lifetime,
}:
let
stepCmd = lib.getExe pkgs.step-cli;
sanArgs = lib.concatMapStringsSep " " (s: "--san \"${s}\"") san;
in
pkgs.writeShellScriptBin "mtls-generate" ''
set -euo pipefail
${stepCmd} ca certificate \
${subject} ${tlsCert} ${tlsKey} \
--not-before=-5m --not-after=${lifetime} \
--provisioner ${provisioner} \
${sanArgs} \
"$@"
cat ${tlsCert} ${tlsKey} > ${mtlsBundle}
'';
mkMtlsCheckScript = { pkgs, mtlsBundle }: pkgs.writeShellScriptBin "mtls-check" ''
${lib.getExe pkgs.openssl} x509 \
-noout -subject -issuer \
-ext subjectAltName,extendedKeyUsage \
-enddate -in ${mtlsBundle}
'';
mkMtlsRenewScript = {
pkgs,
tlsCert,
tlsKey,
mtlsBundle,
reloadUnits ? [ ],
postCommands ? [ ],
systemctlArgs ? [ ],
}:
let
echoCmd = lib.getExe' pkgs.coreutils "echo";
systemctl = lib.getExe' pkgs.systemd "systemctl";
escapedArgs = lib.escapeShellArgs systemctlArgs;
systemctlCommand = "${systemctl} ${escapedArgs}";
renewReloadScript = lib.concatMapStringsSep "\n" (unit: ''
if ${systemctlCommand} --quiet is-active "${unit}"; then
${systemctlCommand} try-reload-or-restart "${unit}"
fi
'') reloadUnits;
renewPostCommands = lib.concatStringsSep "\n" postCommands;
in
pkgs.writeShellScriptBin "mtls-renew" ''
set -euo pipefail
if ${lib.getExe pkgs.step-cli} certificate needs-renewal "${tlsCert}"; then
${echoCmd} "Renewing mTLS certificate"
else
${echoCmd} "Skipping renew"
exit "$?"
fi
${lib.getExe pkgs.step-cli} ca renew --force "${tlsCert}" "${tlsKey}"
umask 077
${lib.getExe' pkgs.coreutils "cat"} "${tlsCert}" "${tlsKey}" > "${mtlsBundle}"
${echoCmd} "Reloading units:"
${renewReloadScript}
${echoCmd} "Post commands:"
${renewPostCommands}
'';
mkNixosMtlsRenewService = {
pkgs,
tlsCert,
tlsKey,
mtlsBundle,
reloadUnits ? [ ],
postCommands ? [ ],
user ? "root",
group ? null,
}:
let
serviceGroup = if group == null then user else group;
renewScript = mkMtlsRenewScript {
inherit pkgs tlsCert tlsKey mtlsBundle reloadUnits postCommands;
};
in
{
description = "Renew the mTLS certificate when Smallstep marks it ready";
wantedBy = [ ];
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
User = user;
Group = serviceGroup;
ExecStart = lib.getExe renewScript;
};
};
mkNixosMtlsRenewTimer = {
onCalendar,
randomizedDelaySec,
unit ? "mtls-renew.service",
}: {
description = "Periodic Smallstep renewal for the mTLS certificate";
wantedBy = [ "timers.target" ];
timerConfig = {
Persistent = true;
OnCalendar = onCalendar;
AccuracySec = "1us";
RandomizedDelaySec = randomizedDelaySec;
Unit = unit;
};
};
mkHomeManagerMtlsRenewService = {
pkgs,
tlsCert,
tlsKey,
mtlsBundle,
reloadUnits ? [ ],
postCommands ? [ ],
}:
let
renewScript = mkMtlsRenewScript {
inherit pkgs tlsCert tlsKey mtlsBundle reloadUnits postCommands;
systemctlArgs = [ "--user" ];
};
in
{
Unit = {
Description = "Renew the mTLS certificate when Smallstep marks it ready";
After = [ "network-online.target" ];
Wants = [ "network-online.target" ];
};
Service = {
Type = "oneshot";
ExecStart = lib.getExe renewScript;
};
};
mkHomeManagerMtlsRenewTimer = {
onCalendar,
randomizedDelaySec,
unit ? "mtls-renew.service",
}: {
Unit = {
Description = "Periodic Smallstep renewal for the mTLS certificate";
};
Timer = {
Persistent = true;
OnCalendar = onCalendar;
AccuracySec = "1us";
RandomizedDelaySec = randomizedDelaySec;
Unit = unit;
};
Install = {
WantedBy = [ "timers.target" ];
};
};
in
{
flake.modules.nixos.mtls = { config, lib, pkgs, ... }:
let
cfg = config.mtls;
tlsKey = "${cfg.certDir}/${cfg.keyFilename}";
tlsCert = "${cfg.certDir}/${cfg.certFilename}";
mtlsBundle = "${cfg.certDir}/${cfg.bundleFilename}";
sanArgs = lib.concatMapStringsSep " " (san: "--san \"${san}\"") cfg.san;
in
{
options.mtls = opts // {
certDir = lib.mkOption {
description = "String path to where the mtls certs will be stored.";
type = lib.types.str;
default = "/etc/step/certs";
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; lib.optionals cfg.enable [
step-cli
(mkMtlsGenerateScript {
inherit (cfg) subject provisioner san lifetime;
inherit pkgs tlsCert tlsKey mtlsBundle;
})
(mkMtlsCheckScript { inherit pkgs mtlsBundle; })
(mkMtlsRenewScript { inherit pkgs tlsCert tlsKey mtlsBundle; })
];
systemd.tmpfiles.rules = [
"d ${cfg.certDir} 0750 ${cfg.renew.user} ${if cfg.renew.group == null then cfg.renew.user else cfg.renew.group} -"
];
systemd.services.mtls-renew = lib.mkIf cfg.renew.enable (mkNixosMtlsRenewService {
inherit pkgs tlsCert tlsKey mtlsBundle;
inherit (cfg.renew) reloadUnits postCommands user group;
});
systemd.timers.mtls-renew = lib.mkIf cfg.renew.enable (mkNixosMtlsRenewTimer {
inherit (cfg.renew) onCalendar randomizedDelaySec;
});
};
};
flake.modules.homeManager.mtls = { config, lib, pkgs, ... }:
let
cfg = config.mtls;
tlsKey = "${cfg.certDir}/${cfg.keyFilename}";
tlsCert = "${cfg.certDir}/${cfg.certFilename}";
mtlsBundle = "${cfg.certDir}/${cfg.bundleFilename}";
sanArgs = lib.concatMapStringsSep " " (san: "--san \"${san}\"") cfg.san;
in
{
options.mtls = opts // {
certDir = lib.mkOption {
description = "String path to where the mtls certs will be stored.";
type = lib.types.str;
default = "${config.home.homeDirectory}/.step/certs";
};
};
config = {
home.packages = with pkgs; lib.optionals cfg.enable [
step-cli
(mkMtlsGenerateScript {
inherit (cfg) subject provisioner san lifetime;
inherit pkgs tlsCert tlsKey mtlsBundle;
})
(mkMtlsCheckScript { inherit pkgs mtlsBundle; })
(mkMtlsRenewScript { inherit pkgs tlsCert tlsKey mtlsBundle; })
];
systemd.user.tmpfiles.rules = lib.mkIf cfg.enable [
"d ${cfg.certDir} 0700 - - -"
];
systemd.user.services.mtls-renew = lib.mkIf cfg.renew.enable (mkHomeManagerMtlsRenewService {
inherit pkgs tlsCert tlsKey mtlsBundle;
inherit (cfg.renew) reloadUnits postCommands;
});
systemd.user.timers.mtls-renew = lib.mkIf cfg.renew.enable (mkHomeManagerMtlsRenewTimer {
inherit (cfg.renew) onCalendar randomizedDelaySec;
});
};
};
}
+108
View File
@@ -0,0 +1,108 @@
{ self, inputs, ... }: {
flake.modules.nixos.restic-server = { config, pkgs, lib, ... }: {
services.restic.server = {
enable = true;
dataDir = "/mnt/restic";
listenAddress = "0.0.0.0:8080";
extraFlags = [ "--no-auth" ];
};
};
flake.modules.homeManager.restic = { config, pkgs, lib, ... }:
let
cfg = config.restic;
in
{
options.restic = {
repoName = lib.mkOption {
description = "Name of the restic repo to use";
type = lib.types.str;
default = "john-ubuntu";
};
passwordFile = lib.mkOption {
description = "String path to the restic password file";
type = lib.types.str;
};
paths = lib.mkOption {
description = "List of string paths to include in the backup";
type = lib.types.listOf lib.types.str;
default = [ ];
};
exclude = lib.mkOption {
description = "List of string paths to include in the backup. There are already some common ones included by default.";
type = lib.types.listOf lib.types.str;
default = [ ];
};
OnCalendar = lib.mkOption {
description = "";
type = lib.types.str;
};
RandomizedDelaySec = lib.mkOption {
description = "";
type = lib.types.str;
default = "1m";
};
};
config = let
resticRepository = "rest:https://soteria.john-stream.com/${cfg.repoName}";
caCert = "${config.mtls.certDir}/root_ca.crt";
mtlsBundle = "${config.mtls.certDir}/${config.mtls.bundleFilename}";
in
{
home.sessionVariables = {
RESTIC_REPOSITORY = resticRepository;
RESTIC_PASSWORD_FILE = cfg.passwordFile;
RESTIC_CACERT = caCert;
RESTIC_TLS_CLIENT_CERT = mtlsBundle;
};
# This is necessary because the restic service in home manager doesn't otherwise expose these options.
systemd.user.services."restic-backups-${cfg.repoName}".Service.Environment = [
"RESTIC_CACERT=${caCert}"
"RESTIC_TLS_CLIENT_CERT=${mtlsBundle}"
];
services.restic = {
enable = true;
backups.${cfg.repoName} = {
repository = resticRepository;
passwordFile = cfg.passwordFile;
paths = cfg.paths;
timerConfig = {
OnCalendar = cfg.OnCalendar;
RandomizedDelaySec = cfg.RandomizedDelaySec;
Persistent = true;
};
runCheck = true;
pruneOpts = [
"--keep-last 10"
"--keep-hourly 8"
"--keep-daily 14"
"--keep-weekly 8"
"--keep-monthly 12"
];
exclude = cfg.exclude ++ [
".cache"
".devenv"
".rustup"
".cargo"
".venv"
".pyenv"
".vscode*"
"data/postgres"
"build"
"dist"
"__pycache__"
"*.log"
"*.egg-info"
"*.csv"
"*.m4a"
".local/share/Steam"
".local/share/Trash"
];
};
};
};
};
}
+40
View File
@@ -0,0 +1,40 @@
# This module provides all the shell options
{ inputs, lib, ... }:
{
flake.modules.homeManager.shell-tools = { config, pkgs, ... }: {
options.shell.program = lib.mkOption {
type = lib.types.enum [ "bash" "zsh" ];
default = "zsh";
description = "Which interactive shell configuration to enable.";
};
imports = with inputs.self.modules.homeManager; [
bash
zsh
# Tools
eza
files
];
config = {
home.shell.enableShellIntegration = true;
programs.zsh.enable = lib.mkForce (config.shell.program == "zsh");
home.packages = with pkgs; [
wget
curl
busybox
gnugrep
dig
btop
uv
xclip
jq
ripgrep
(writeShellScriptBin "ds" ''
${lib.getExe pkgs.gdu} -x -I /snap /
'')
];
};
};
}