Compare commits

..

1 commit

95 changed files with 743 additions and 4173 deletions

View file

@ -1,19 +0,0 @@
{ ... }:
{
flake.modules.nixos.ai =
{ inputs, pkgs, ... }:
{
environment.systemPackages =
(with pkgs; [ ])
++ (with inputs.nix-ai-tools.packages.${pkgs.stdenv.hostPlatform.system}; [
opencode
]);
nix.settings = {
extra-substituters = [ "https://cache.numtide.com" ];
extra-trusted-public-keys = [
"niks3.numtide.com-1:DTx8wZduET09hRmMtKdQDxNNthLQETkc/yaX7M4qK0g="
];
};
};
}

View file

@ -1,16 +0,0 @@
{ ... }:
{
flake.modules.homeManager.bash =
{
config,
lib,
pkgs,
...
}:
{
programs.bash = {
enable = true;
historyFile = "~/.cache/bash_history";
};
};
}

View file

@ -1,23 +0,0 @@
{ ... }:
{
flake.modules.nixos.boot =
{ pkgs, ... }:
{
boot = {
loader = {
timeout = 1;
efi.canTouchEfiVariables = true;
systemd-boot = {
enable = true;
editor = false;
consoleMode = "max";
sortKey = "aa";
netbootxyz = {
enable = true;
sortKey = "zz";
};
};
};
};
};
}

View file

@ -1,11 +0,0 @@
{ ... }:
{
flake.modules.nixos.console =
{ ... }:
{
console = {
useXkbConfig = true;
earlySetup = true;
};
};
}

View file

@ -1,11 +0,0 @@
{ ... }:
{
flake.modules.nixos.firewall =
{ ... }:
{
networking = {
firewall.enable = true;
nftables.enable = true;
};
};
}

View file

@ -1,47 +0,0 @@
{ ... }:
{
flake.modules = {
nixos.fish =
{ ... }:
{
programs.fish.enable = true;
};
homeManager.fish =
{
config,
lib,
pkgs,
...
}:
{
programs.fish = {
enable = true;
interactiveShellInit = ''
set fish_greeting
${lib.getExe pkgs.nix-your-shell} fish | source
'';
loginShellInit = "${lib.getExe pkgs.nix-your-shell} fish | source";
plugins = [
{
name = "bang-bang";
src = pkgs.fetchFromGitHub {
owner = "oh-my-fish";
repo = "plugin-bang-bang";
rev = "f969c618301163273d0a03d002614d9a81952c1e";
sha256 = "sha256-A8ydBX4LORk+nutjHurqNNWFmW6LIiBPQcxS3x4nbeQ=";
};
}
{
name = "z";
src = pkgs.fetchFromGitHub {
owner = "jethrokuan";
repo = "z";
rev = "067e867debee59aee231e789fc4631f80fa5788e";
sha256 = "sha256-emmjTsqt8bdI5qpx1bAzhVACkg0MNB/uffaRjjeuFxU=";
};
}
];
};
};
};
}

View file

@ -1,24 +0,0 @@
{ ... }:
{
flake.modules.nixos.locale =
{ ... }:
{
time.timeZone = "America/Bahia";
i18n = {
defaultLocale = "en_US.UTF-8";
extraLocaleSettings = {
LC_ADDRESS = "pt_BR.utf8";
LC_COLLATE = "pt_BR.utf8";
LC_IDENTIFICATION = "pt_BR.utf8";
LC_MEASUREMENT = "pt_BR.utf8";
LC_MONETARY = "pt_BR.utf8";
LC_NAME = "pt_BR.utf8";
LC_NUMERIC = "pt_BR.utf8";
LC_PAPER = "pt_BR.utf8";
LC_TELEPHONE = "pt_BR.utf8";
LC_TIME = "en_IE.utf8";
};
};
};
}

View file

@ -1,51 +0,0 @@
{ ... }:
{
flake.modules.nixos.nix =
{ inputs, pkgs, ... }:
{
imports = [ inputs.nixos-cli.nixosModules.nixos-cli ];
nix = {
settings = {
auto-optimise-store = true;
connect-timeout = 10;
log-lines = 25;
min-free = 128000000;
max-free = 1000000000;
trusted-users = [ "@wheel" ];
};
extraOptions = "experimental-features = nix-command flakes";
gc = {
automatic = true;
options = "--delete-older-than 8d";
};
};
nixpkgs.config = {
allowUnfree = true;
enableParallelBuilding = true;
buildManPages = false;
buildDocs = false;
};
services.nixos-cli = {
enable = true;
config = {
use_nvd = true;
ignore_dirty_tree = true;
apply = {
reexec_as_root = true;
use_nom = true;
};
confirmation.empty = "default-yes";
};
};
environment.systemPackages = with pkgs; [
nix-output-monitor
nvd
];
system.stateVersion = "22.11";
};
}

View file

@ -1,13 +0,0 @@
{ ... }:
{
flake.modules.nixos.security =
{ ... }:
{
security.sudo = {
wheelNeedsPassword = false;
extraConfig = ''
Defaults lecture = never
'';
};
};
}

View file

@ -1,32 +0,0 @@
{ ... }:
{
flake.modules.nixos.ssh =
{ ... }:
{
services.openssh = {
enable = true;
settings.PermitRootLogin = "no";
extraConfig = ''
PrintLastLog no
'';
};
programs = {
bash.interactiveShellInit = ''
if [ -n "$SSH_CONNECTION" ] && [ -z "$IN_NIX_SHELL" ] && [ -z "$TMUX" ]; then
export TERM=xterm-256color
clear
fastfetch
fi
'';
fish.interactiveShellInit = ''
set fish_greeting
if set -q SSH_CONNECTION; and not set -q IN_NIX_SHELL; and not set -q TMUX
export TERM=xterm-256color
clear
fastfetch
end
'';
};
};
}

View file

@ -1,16 +0,0 @@
{ ... }:
{
flake.modules.nixos.bluetooth =
{
config,
lib,
pkgs,
...
}:
{
hardware.bluetooth = {
enable = true;
powerOnBoot = false;
};
};
}

View file

@ -1,28 +0,0 @@
{ ... }:
{
flake.modules = {
nixos.btop =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ btop ];
};
homeManager.btop =
{
config,
lib,
pkgs,
...
}:
{
programs.btop = {
enable = true;
settings = {
theme_background = false;
proc_sorting = "cpu direct";
update_ms = 500;
};
};
};
};
}

View file

@ -1,16 +0,0 @@
{ ... }:
{
flake.modules.homeManager.comma =
{
config,
lib,
pkgs,
inputs,
...
}:
{
imports = [ inputs.nix-index-database.homeModules.nix-index ];
programs.nix-index-database.comma.enable = true;
};
}

View file

@ -1,16 +0,0 @@
{ ... }:
{
flake.modules.homeManager.direnv =
{
config,
lib,
pkgs,
...
}:
{
programs.direnv = {
enable = true;
nix-direnv.enable = true;
};
};
}

View file

@ -1,67 +0,0 @@
{ ... }:
{
flake.modules = {
nixos.helix =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
helix
];
};
homeManager.helix =
{
config,
lib,
pkgs,
...
}:
{
home.sessionVariables = {
EDITOR = "hx";
};
programs.helix = {
enable = true;
settings = {
editor = {
file-picker.hidden = false;
idle-timeout = 0;
line-number = "relative";
cursor-shape = {
normal = "underline";
insert = "bar";
select = "underline";
};
soft-wrap.enable = true;
auto-format = true;
indent-guides.render = true;
};
keys.normal = {
space = {
o = "file_picker_in_current_buffer_directory";
esc = [
"collapse_selection"
"keep_primary_selection"
];
};
};
};
languages = {
language = [
{
name = "nix";
auto-format = true;
formatter.command = "nixfmt";
}
{
name = "typst";
auto-format = true;
formatter.command = "typstyle -c 1000 -i";
}
];
};
};
};
};
}

View file

@ -1,18 +0,0 @@
{ ... }:
{
flake.modules.homeManager.hm-cli =
{
config,
lib,
pkgs,
...
}:
{
home = {
packages = with pkgs; [ hm-cli ];
sessionVariables = {
HM_PATH = "/etc/nixos";
};
};
};
}

View file

@ -1,48 +0,0 @@
{ ... }:
{
flake.modules.homeManager.starship =
{
config,
lib,
pkgs,
...
}:
{
programs.starship = {
enable = true;
enableBashIntegration = true;
enableFishIntegration = true;
settings = {
add_newline = false;
format = ''
$hostname$directory$git_branch$git_status$nix_shell
[ ](bold green)
'';
right_format = "$cmd_duration$character";
hostname = {
ssh_symbol = "󰖟 ";
};
character = {
error_symbol = "[](red)";
success_symbol = "[󱐋](green)";
};
cmd_duration = {
format = "[󰄉 $duration ]($style)";
style = "yellow";
min_time = 500;
};
git_branch = {
symbol = " ";
style = "purple";
};
git_status.style = "red";
nix_shell = {
format = "via [$symbol$state]($style)";
heuristic = true;
style = "blue";
symbol = "󱄅 ";
};
};
};
};
}

View file

@ -1,29 +0,0 @@
{ ... }:
{
flake.modules = {
nixos.tmux =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
tmux
];
};
homeManager.tmux =
{
config,
lib,
pkgs,
...
}:
{
programs.tmux = {
enable = true;
clock24 = true;
terminal = "xterm-256color";
mouse = true;
keyMode = "vi";
};
};
};
}

View file

@ -1,217 +0,0 @@
{
inputs,
lib,
config,
...
}:
let
# Host submodule type
hostType = lib.types.submodule {
options = {
lanIP = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "LAN IP address for the host";
};
tailscaleIP = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Tailscale IP address for the host";
};
};
};
# Service submodule type
serviceType = lib.types.submodule {
options = {
name = lib.mkOption {
type = lib.types.str;
description = "Service name";
};
domain = lib.mkOption {
type = lib.types.str;
description = "Domain name for the service";
};
host = lib.mkOption {
type = lib.types.str;
description = "Host where the service runs";
};
public = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether the service is publicly accessible";
};
lanIP = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "LAN IP address (inherited from host)";
};
tailscaleIP = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Tailscale IP address (inherited from host)";
};
};
};
# Import shared data (also used by terranix)
sharedData = import ../data/services.nix;
# Enrich services with host IP information
enrichServices =
hosts: services:
map (
svc:
let
hostInfo = hosts.${svc.host} or { };
in
svc
// {
lanIP = hostInfo.lanIP or null;
tailscaleIP = hostInfo.tailscaleIP or null;
}
) services;
in
{
options.flake = {
hosts = lib.mkOption {
type = lib.types.attrsOf hostType;
default = { };
description = "Host definitions with IP addresses";
};
services = lib.mkOption {
type = lib.types.listOf serviceType;
default = [ ];
description = "Service definitions with enriched host information";
};
lib = lib.mkOption {
type = lib.types.attrsOf lib.types.raw;
default = { };
description = "Utility functions for flake configuration";
};
};
config.flake = {
hosts = sharedData.hosts;
services = enrichServices config.flake.hosts sharedData.services;
lib = {
# Nginx virtual host utilities
mkNginxVHosts =
{ domains }:
let
mkVHostConfig =
domain: vhostConfig:
lib.recursiveUpdate {
useACMEHost = domain;
forceSSL = true;
kTLS = true;
} vhostConfig;
in
lib.mapAttrs mkVHostConfig domains;
# Split DNS utilities for unbound
# Generates unbound view config from a list of DNS entries
mkSplitDNS =
entries:
let
tailscaleData = map (e: ''"${e.domain}. IN A ${e.tailscaleIP}"'') entries;
lanData = map (e: ''"${e.domain}. IN A ${e.lanIP}"'') entries;
in
[
{
name = "tailscale";
view-first = true;
local-zone = ''"baduhai.dev." transparent'';
local-data = tailscaleData;
}
{
name = "lan";
view-first = true;
local-zone = ''"baduhai.dev." transparent'';
local-data = lanData;
}
];
# Generates flake.homeConfigurations
mkHomeConfiguration =
{
user,
hostname,
system ? "x86_64-linux",
stateVersion ? "22.05",
nixpkgs ? inputs.nixpkgs, # override with e.g. inputs.nixpkgs-stable
userModules ? [ ],
overlays ? [ inputs.self.overlays.default ],
homeManagerModules ? with inputs.self.modules.homeManager; [
base
cli
],
userDirectory ? "/home/${user}",
}:
inputs.home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.${system};
extraSpecialArgs = {
inherit inputs hostname;
};
modules = [
{ nixpkgs.overlays = overlays; }
{
home = {
username = user;
homeDirectory = userDirectory;
inherit stateVersion;
};
}
((inputs.import-tree.initFilter (p: lib.hasSuffix ".nix" p))
"/${inputs.self}/aspects/users/_${user}"
)
]
++ homeManagerModules
++ userModules;
};
# Generates flake.nixosConfigurations
mkHost =
{
hostname,
system ? "x86_64-linux",
nixpkgs ? inputs.nixpkgs,
overlays ? [
inputs.agenix.overlays.default
inputs.self.overlays.default
],
ephemeralRootDev ? null, # pass rootDevice string to enable, e.g. ephemeralephemeralRootDev = "/dev/mapper/cryptroot"
nixosModules ? with inputs.self.modules.nixos; [
base
cli
user
root
],
extraModules ? [ ],
}:
nixpkgs.lib.nixosSystem {
inherit system;
specialArgs = { inherit inputs; };
modules = [
inputs.agenix.nixosModules.default
{ networking.hostName = hostname; }
{ nixpkgs.overlays = overlays; }
((inputs.import-tree.initFilter (p: lib.hasSuffix ".nix" p))
"${inputs.self}/aspects/hosts/_${hostname}"
)
]
++ (lib.optional (ephemeralRootDev != null) (
inputs.self.factory.ephemeral { rootDevice = ephemeralRootDev; }
))
++ nixosModules
++ extraModules;
};
};
};
}

View file

@ -1,25 +0,0 @@
{ ... }:
{
flake.modules.nixos.graphics =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
gimp
inkscape
plasticity
];
services.flatpak.packages = [
"com.boxy_svg.BoxySVG"
rec {
appId = "io.github.softfever.OrcaSlicer";
sha256 = "0hdx5sg6fknj1pfnfxvlfwb5h6y1vjr6fyajbsnjph5gkp97c6p1";
bundle = "${pkgs.fetchurl {
url = "https://github.com/SoftFever/OrcaSlicer/releases/download/v2.3.0/OrcaSlicer-Linux-flatpak_V2.3.0_x86_64.flatpak";
inherit sha256;
}}";
}
];
};
}

View file

@ -1,29 +0,0 @@
{ ... }:
{
flake.modules = {
nixos.media =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
decibels
loupe
obs-studio
showtime
];
};
homeManager.media =
{ pkgs, ... }:
{
programs.obs-studio = {
enable = true;
plugins = with pkgs.obs-studio-plugins; [
obs-vkcapture
obs-backgroundremoval
obs-pipewire-audio-capture
];
};
};
};
}

View file

@ -1,246 +0,0 @@
{ ... }:
{
flake.modules = {
nixos.niri =
{
config,
lib,
pkgs,
...
}:
{
services.greetd.settings = {
default_session.command = "${lib.getExe pkgs.tuigreet} --user-menu --time --remember --asterisks --cmd ${config.programs.niri.package}/bin/niri-session";
};
programs.niri.enable = true;
};
homeManager.niri =
{
config,
lib,
pkgs,
inputs,
hostname ? null,
...
}:
let
isRotterdam = hostname == "rotterdam";
in
{
imports = [ inputs.noctalia.homeModules.default ];
services.kanshi = {
enable = true;
settings = [
{
profile.name = "default";
profile.outputs = [
{
criteria = "*";
scale = 1.0;
}
];
}
];
};
home = {
packages = with pkgs; [
xwayland-satellite
inputs.noctalia.packages.${pkgs.stdenv.hostPlatform.system}.default
];
sessionVariables.QT_QPA_PLATFORMTHEME = "gtk3";
};
xdg.configFile."niri/config.kdl".text = ''
input {
keyboard {
xkb {
layout "us"
variant "altgr-intl"
}
}
touchpad {
tap
dwt
drag true
drag-lock
natural-scroll
accel-speed 0.2
accel-profile "flat"
scroll-method "two-finger"
middle-emulation
}
mouse {
natural-scroll
accel-speed 0.2
accel-profile "flat"
}
warp-mouse-to-focus mode="center-xy"
focus-follows-mouse
}
output "LG Electronics LG ULTRAWIDE 206AZFM5E459" {
layout {
preset-column-widths {
proportion 0.33333
proportion 0.5
proportion 0.66667
}
default-column-width { proportion 0.33333; }
}
}
layout {
gaps 8
center-focused-column "never"
always-center-single-column
empty-workspace-above-first
preset-column-widths {
proportion 0.5
proportion 1.0
}
default-column-width { proportion 0.5; }
focus-ring {
off
}
border {
width 4
active-color "#ffc87f"
inactive-color "#505050"
urgent-color "#9b0000"
}
tab-indicator {
width 4
gap 4
place-within-column
}
}
overview {
zoom 0.65
}
spawn-at-startup "noctalia-shell" "-d"
spawn-at-startup "${lib.getExe pkgs.niri-auto-centre}"
layer-rule {
match namespace="^noctalia-overview*"
place-within-backdrop true
}
hotkey-overlay {
skip-at-startup
}
prefer-no-csd
screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
animations {
slowdown 0.3
}
window-rule {
match app-id="zen"
default-column-width { proportion ${if isRotterdam then "0.5" else "1.0"}; }
}
window-rule {
geometry-corner-radius 12
clip-to-geometry true
}
config-notification {
disable-failed
}
binds {
Alt+Space repeat=false { spawn "vicinae" "toggle"; }
XF86AudioRaiseVolume allow-when-locked=true { spawn "noctalia-shell" "ipc" "call" "volume" "increase"; }
XF86AudioLowerVolume allow-when-locked=true { spawn "noctalia-shell" "ipc" "call" "volume" "decrease"; }
XF86AudioMute allow-when-locked=true { spawn "noctalia-shell" "ipc" "call" "volume" "muteOutput"; }
XF86MonBrightnessUp allow-when-locked=true { spawn "noctalia-shell" "ipc" "call" "brightness" "increase"; }
XF86MonBrightnessDown allow-when-locked=true { spawn "noctalia-shell" "ipc" "call" "brightness" "decrease"; }
XF86AudioPlay allow-when-locked=true { spawn "${lib.getExe pkgs.playerctl}" "play-pause"; }
XF86AudioStop allow-when-locked=true { spawn "${lib.getExe pkgs.playerctl}" "stop"; }
XF86AudioPrev allow-when-locked=true { spawn "${lib.getExe pkgs.playerctl}" "previous"; }
XF86AudioNext allow-when-locked=true { spawn "${lib.getExe pkgs.playerctl}" "next"; }
Mod+V repeat=false { spawn "vicinae" "vicinae://extensions/vicinae/clipboard/history"; }
Mod+Shift+L repeat=false { spawn "noctalia-shell" "ipc" "call" "lockScreen" "lock"; }
Mod+Return { spawn "ghostty"; }
Ctrl+Alt+Shift+A allow-when-locked=true { spawn "toggleaudiosink"; }
Mod+W repeat=false { toggle-overview; }
Mod+Q { close-window; }
Alt+Shift+Q { close-window;}
Mod+Shift+Q { close-window; }
Alt+F4 { close-window; }
Mod+Left { focus-column-left; }
Mod+Down { focus-window-or-workspace-down; }
Mod+Up { focus-window-or-workspace-up; }
Mod+Right { focus-column-right; }
Mod+H { focus-column-left; }
Mod+L { focus-column-right; }
Mod+J { focus-window-or-workspace-down; }
Mod+K { focus-window-or-workspace-up; }
Mod+Ctrl+Left { move-column-left; }
Mod+Ctrl+Down { move-window-down-or-to-workspace-down; }
Mod+Ctrl+Up { move-window-up-or-to-workspace-up; }
Mod+Ctrl+Right { move-column-right; }
Mod+Ctrl+H { move-column-left; }
Mod+Ctrl+J { move-window-down-or-to-workspace-down; }
Mod+Ctrl+K { move-window-up-or-to-workspace-up; }
Mod+Ctrl+L { move-column-right; }
Mod+Home { focus-column-first; }
Mod+End { focus-column-last; }
Mod+Ctrl+Home { move-column-to-first; }
Mod+Ctrl+End { move-column-to-last; }
Mod+Alt+Left { focus-monitor-left; }
Mod+Alt+Down { focus-monitor-down; }
Mod+Alt+Up { focus-monitor-up; }
Mod+Alt+Right { focus-monitor-right; }
Mod+Alt+H { focus-monitor-left; }
Mod+Alt+J { focus-monitor-down; }
Mod+Alt+K { focus-monitor-up; }
Mod+Alt+L { focus-monitor-right; }
Mod+Alt+Ctrl+Left { move-column-to-monitor-left; }
Mod+Alt+Ctrl+Down { move-column-to-monitor-down; }
Mod+Alt+Ctrl+Up { move-column-to-monitor-up; }
Mod+Alt+Ctrl+Right { move-column-to-monitor-right; }
Mod+Alt+Ctrl+H { move-column-to-monitor-left; }
Mod+Alt+Ctrl+J { move-column-to-monitor-down; }
Mod+Alt+Ctrl+K { move-column-to-monitor-up; }
Mod+Alt+Ctrl+L { move-column-to-monitor-right; }
Mod+Ctrl+U { move-workspace-down; }
Mod+Ctrl+I { move-workspace-up; }
Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; }
Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; }
Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; }
Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; }
Mod+Shift+WheelScrollDown { focus-column-right; }
Mod+Shift+WheelScrollUp { focus-column-left; }
Mod+Ctrl+Shift+WheelScrollDown { move-column-right; }
Mod+Ctrl+Shift+WheelScrollUp { move-column-left; }
Mod+BracketLeft { consume-or-expel-window-left; }
Mod+BracketRight { consume-or-expel-window-right; }
Mod+Comma { consume-window-into-column; }
Mod+Period { expel-window-from-column; }
Mod+R { switch-preset-column-width; }
Mod+F { maximize-column; }
Mod+Ctrl+F { fullscreen-window; }
Mod+C { center-visible-columns; }
Mod+Ctrl+C { center-column; }
Mod+Space { toggle-window-floating; }
Mod+Ctrl+Space { switch-focus-between-floating-and-tiling; }
Mod+T { toggle-column-tabbed-display; }
Print { screenshot-screen; }
Mod+Print { screenshot; }
Ctrl+Print { screenshot-window; }
Mod+Backspace allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; }
Mod+Alt+E { spawn "noctalia-shell" "ipc" "call" "sessionMenu" "toggle"; }
Ctrl+Alt+Delete { spawn "noctalia-shell" "ipc" "call" "sessionMenu" "toggle"; }
Mod+Ctrl+P { power-off-monitors; }
}
'';
};
};
}

View file

@ -1,23 +0,0 @@
{ ... }:
{
flake.modules.nixos.office =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
aspell
aspellDicts.de
aspellDicts.en
aspellDicts.en-computers
aspellDicts.pt_BR
glow
papers
presenterm
rnote
];
services.flatpak.packages = [
"com.collabora.Office"
];
};
}

View file

@ -1,22 +0,0 @@
{ ... }:
{
flake.modules.nixos.web =
{
inputs,
pkgs,
...
}:
{
environment.systemPackages = with pkgs; [
inputs.zen-browser.packages."${pkgs.stdenv.hostPlatform.system}".default
beeper
bitwarden-desktop
fragments
nextcloud-client
tor-browser
ungoogled-chromium
vesktop
];
};
}

View file

@ -1,23 +0,0 @@
{ ... }:
{
flake.modules.nixos.dev =
{
config,
lib,
pkgs,
...
}:
{
environment.systemPackages = with pkgs; [
android-tools
lazygit
fd
fzf
nixfmt
nix-init
ripgrep
];
users.users.user.extraGroups = [ "adbusers" ];
};
}

View file

@ -1,139 +0,0 @@
# Ephemeral root aspect - provides automatic btrfs root subvolume rollover
# Exports both a base module with options and a factory function for easy configuration
{ inputs, ... }:
{
# Base module with options (for external flakes or direct use)
flake.modules.nixos.ephemeral =
{ lib, config, ... }:
let
cfg = config.ephemeral;
in
{
options.ephemeral = {
enable = lib.mkEnableOption "ephemeral root with automatic rollback";
rootDevice = lib.mkOption {
type = lib.types.str;
example = "/dev/mapper/cryptroot";
description = "Device path for the root btrfs filesystem";
};
rootSubvolume = lib.mkOption {
type = lib.types.str;
default = "@root";
description = "Name of the root btrfs subvolume";
};
oldRootRetentionDays = lib.mkOption {
type = lib.types.int;
default = 30;
description = "Number of days to keep old root snapshots before deletion";
};
};
config = lib.mkIf cfg.enable {
boot.initrd.systemd.services.recreate-root = {
description = "Rolling over and creating new filesystem root";
requires = [ "initrd-root-device.target" ];
after = [
"local-fs-pre.target"
"initrd-root-device.target"
];
requiredBy = [ "initrd-root-fs.target" ];
before = [ "sysroot.mount" ];
unitConfig = {
AssertPathExists = "/etc/initrd-release";
DefaultDependencies = false;
};
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
set -euo pipefail
mkdir /btrfs_tmp
if ! mount ${cfg.rootDevice} /btrfs_tmp; then
echo "ERROR: Failed to mount ${cfg.rootDevice}"
exit 1
fi
if [[ -e /btrfs_tmp/${cfg.rootSubvolume} ]]; then
mkdir -p /btrfs_tmp/old_roots
timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/${cfg.rootSubvolume})" "+%Y-%m-%-d_%H:%M:%S")
mv /btrfs_tmp/${cfg.rootSubvolume} "/btrfs_tmp/old_roots/$timestamp"
fi
delete_subvolume_recursively() {
IFS=$'\n'
for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
delete_subvolume_recursively "/btrfs_tmp/$i"
done
btrfs subvolume delete "$1"
}
for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +${toString cfg.oldRootRetentionDays}); do
delete_subvolume_recursively "$i"
done
if ! btrfs subvolume create /btrfs_tmp/${cfg.rootSubvolume}; then
echo "ERROR: Failed to create subvolume ${cfg.rootSubvolume}"
umount /btrfs_tmp
exit 1
fi
umount /btrfs_tmp
'';
};
};
};
# Factory function that generates configured modules
flake.factory.ephemeral =
{
rootDevice,
rootSubvolume ? "@root",
retentionDays ? 30,
persistentStoragePath ? "/persistent",
persistentFiles ? [
"/etc/machine-id"
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
"/etc/ssh/ssh_host_rsa_key"
"/etc/ssh/ssh_host_rsa_key.pub"
],
persistentDirectories ? [
"/etc/NetworkManager/system-connections"
"/etc/nixos"
"/var/lib/bluetooth"
"/var/lib/flatpak"
"/var/lib/lxd"
"/var/lib/nixos"
"/var/lib/systemd/coredump"
"/var/lib/systemd/timers"
"/var/lib/tailscale"
"/var/log"
],
}:
{ ... }:
{
imports = [
inputs.impermanence.nixosModules.impermanence
inputs.self.modules.nixos.ephemeral
];
ephemeral = {
enable = true;
inherit rootDevice rootSubvolume;
oldRootRetentionDays = retentionDays;
};
fileSystems."/persistent".neededForBoot = true;
environment.persistence.main = {
inherit persistentStoragePath;
files = persistentFiles;
directories = persistentDirectories;
};
};
}

View file

@ -1,13 +0,0 @@
{ ... }:
{
flake.modules.nixos.fwupd =
{
config,
lib,
pkgs,
...
}:
{
services.fwupd.enable = true;
};
}

View file

@ -1,47 +0,0 @@
{ ... }:
{
flake.modules = {
nixos.mangohud =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
mangohud
];
};
homeManager.mangohud =
{ config, ... }:
{
programs.mangohud = {
enable = true;
enableSessionWide = true;
settings = {
position = "top-left";
fps = true;
frametime = false;
frame_timing = false;
gpu_stats = true;
gpu_temp = true;
gpu_power = true;
cpu_stats = true;
cpu_temp = true;
cpu_power = true;
ram = true;
vram = true;
gamemode = false;
vkbasalt = false;
version = false;
engine_version = false;
vulkan_driver = false;
wine = false;
time = false;
fps_sampling_period = 500;
toggle_hud = "Shift_L+F12";
toggle_logging = "Ctrl_L+F2";
output_folder = "${config.home.homeDirectory}/.local/share/mangohud";
};
};
};
};
}

View file

@ -1,24 +0,0 @@
{ ... }:
{
flake.modules.nixos.steam =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
steam-run
];
programs = {
steam = {
enable = true;
extraCompatPackages = [ pkgs.proton-ge-bin ];
};
gamemode.enable = true;
};
services.flatpak.packages = [
"com.steamgriddb.SGDBoop"
"io.github.Foldex.AdwSteamGtk"
];
};
}

View file

@ -1,49 +0,0 @@
{
config,
lib,
modulesPath,
...
}:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot = {
initrd = {
availableKernelModules = [
"xhci_pci"
"ahci"
"usbhid"
"usb_storage"
"sd_mod"
];
kernelModules = [ ];
};
kernelModules = [ "kvm-intel" ];
extraModulePackages = [ ];
};
fileSystems = {
"/" = {
device = "/dev/disk/by-uuid/31289617-1d84-4432-a833-680b52e88525";
fsType = "ext4";
};
"/boot" = {
device = "/dev/disk/by-uuid/4130-BE54";
fsType = "vfat";
};
};
swapDevices = [
{
device = "/swapfile";
size = 8192;
}
];
networking.useDHCP = lib.mkDefault true;
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,14 +0,0 @@
{ lib, inputs, ... }:
let
mkNginxVHosts = inputs.self.lib.mkNginxVHosts;
in
{
services.jellyfin = {
enable = true;
openFirewall = true;
};
services.nginx.virtualHosts = mkNginxVHosts {
domains."jellyfin.baduhai.dev".locations."/".proxyPass = "http://127.0.0.1:8096/";
};
}

View file

@ -1,95 +0,0 @@
{
config,
inputs,
pkgs,
...
}:
let
mkNginxVHosts = inputs.self.lib.mkNginxVHosts;
in
{
services = {
nextcloud = {
enable = true;
package = pkgs.nextcloud32;
datadir = "/data/nextcloud";
hostName = "cloud.baduhai.dev";
configureRedis = true;
https = true;
secretFile = config.age.secrets."nextcloud-secrets.json".path;
database.createLocally = true;
maxUploadSize = "16G";
extraApps = {
inherit (config.services.nextcloud.package.packages.apps)
calendar
contacts
notes
tasks
user_oidc
;
};
extraAppsEnable = true;
caching = {
apcu = true;
redis = true;
};
settings = {
trusted_proxies = [ "127.0.0.1" ];
default_phone_region = "BR";
maintenance_window_start = "4";
allow_local_remote_servers = true;
enabledPreviewProviders = [
"OC\\Preview\\BMP"
"OC\\Preview\\EMF"
"OC\\Preview\\Font"
"OC\\Preview\\GIF"
"OC\\Preview\\HEIC"
"OC\\Preview\\Illustrator"
"OC\\Preview\\JPEG"
"OC\\Preview\\Krita"
"OC\\Preview\\MarkDown"
"OC\\Preview\\Movie"
"OC\\Preview\\MP3"
"OC\\Preview\\MSOffice2003"
"OC\\Preview\\MSOffice2007"
"OC\\Preview\\MSOfficeDoc"
"OC\\Preview\\OpenDocument"
"OC\\Preview\\PDF"
"OC\\Preview\\Photoshop"
"OC\\Preview\\PNG"
"OC\\Preview\\Postscript"
"OC\\Preview\\SVG"
"OC\\Preview\\TIFF"
"OC\\Preview\\TXT"
"OC\\Preview\\XBitmap"
];
};
config = {
dbtype = "pgsql";
adminpassFile = config.age.secrets.nextcloud-adminpass.path;
};
phpOptions = {
"opcache.interned_strings_buffer" = "16";
};
};
nginx.virtualHosts = mkNginxVHosts {
domains."cloud.baduhai.dev" = { };
};
};
age.secrets = {
"nextcloud-secrets.json" = {
file = "${inputs.self}/secrets/nextcloud-secrets.json.age";
owner = "nextcloud";
group = "nextcloud";
};
nextcloud-adminpass = {
file = "${inputs.self}/secrets/nextcloud-adminpass.age";
owner = "nextcloud";
group = "nextcloud";
};
};
}

View file

@ -1,58 +0,0 @@
{
config,
lib,
inputs,
...
}:
let
services = inputs.self.services;
# Get all unique domains from shared services that have LAN IPs (served by this host)
localDomains = lib.unique (map (s: s.domain) (lib.filter (s: s.host == "alexandria") services));
# Generate ACME cert configs for all local domains
acmeCerts = lib.genAttrs localDomains (domain: {
group = "nginx";
});
in
{
security.acme = {
acceptTerms = true;
defaults = {
email = "baduhai@proton.me";
dnsResolver = "1.1.1.1:53";
dnsProvider = "cloudflare";
credentialsFile = config.age.secrets.cloudflare.path;
};
certs = acmeCerts;
};
services.nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
virtualHosts = {
"_" = {
default = true;
locations."/".return = "444";
};
};
};
users.users.nginx.extraGroups = [ "acme" ];
networking.firewall.allowedTCPPorts = [
80
443
];
age.secrets.cloudflare = {
file = "${inputs.self}/secrets/cloudflare.age";
owner = "nginx";
group = "nginx";
};
}

View file

@ -1,57 +0,0 @@
{ inputs, lib, ... }:
let
services = inputs.self.services;
in
{
services.unbound = {
enable = true;
enableRootTrustAnchor = true;
settings = {
server = {
interface = [
"0.0.0.0"
"::"
];
access-control = [
"127.0.0.0/8 allow"
"192.168.0.0/16 allow"
"::1/128 allow"
];
num-threads = 2;
msg-cache-size = "50m";
rrset-cache-size = "100m";
cache-min-ttl = 300;
cache-max-ttl = 86400;
prefetch = true;
prefetch-key = true;
hide-identity = true;
hide-version = true;
so-rcvbuf = "1m";
so-sndbuf = "1m";
# LAN-only DNS records
local-zone = ''"baduhai.dev." transparent'';
local-data = map (e: ''"${e.domain}. IN A ${e.lanIP}"'') (lib.filter (e: e.lanIP != null) services);
};
forward-zone = [
{
name = ".";
forward-addr = [
"1.1.1.1@853#cloudflare-dns.com"
"1.0.0.1@853#cloudflare-dns.com"
];
forward-tls-upstream = true;
}
];
};
};
networking.firewall = {
allowedTCPPorts = [ 53 ];
allowedUDPPorts = [ 53 ];
};
}

View file

@ -1,25 +0,0 @@
{
config,
lib,
inputs,
...
}:
let
mkNginxVHosts = inputs.self.lib.mkNginxVHosts;
in
{
services.vaultwarden = {
enable = true;
config = {
DOMAIN = "https://pass.baduhai.dev";
SIGNUPS_ALLOWED = false;
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = 58222;
};
};
services.nginx.virtualHosts = mkNginxVHosts {
domains."pass.baduhai.dev".locations."/".proxyPass =
"http://${config.services.vaultwarden.config.ROCKET_ADDRESS}:${toString config.services.vaultwarden.config.ROCKET_PORT}/";
};
}

View file

@ -1,14 +0,0 @@
{
boot = {
# TODO check if future kernel versions fix boot issue with systemd initrd with tpm
initrd.systemd.tpm2.enable = false;
kernelParams = [
"nosgx"
"i915.fastboot=1"
"mem_sleep_default=deep"
];
extraModprobeConfig = ''
options snd-intel-dspcfg dsp_driver=3
'';
};
}

View file

@ -1,79 +0,0 @@
{ inputs, ... }:
{
imports = [ inputs.disko.nixosModules.default ];
disko.devices.disk.main = {
type = "disk";
device = "/dev/disk/by-id/mmc-hDEaP3_0x1041b689";
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
start = "1MiB";
end = "1GiB";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot/efi";
mountOptions = [
"noatime"
"fmask=0077"
"dmask=0077"
];
};
};
cryptroot = {
priority = 2;
name = "root";
size = "100%";
content = {
type = "luks";
name = "cryptroot";
content = {
type = "btrfs";
extraArgs = [ "-f" ];
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = [
"noatime"
"compress=zstd"
"subvol=@root"
];
};
"@home" = {
mountpoint = "/home";
mountOptions = [
"noatime"
"compress=zstd"
"subvol=@home"
];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = [
"noatime"
"compress=zstd"
"subvol=@nix"
];
};
"@persistent" = {
mountpoint = "/persistent";
mountOptions = [
"noatime"
"compress=zstd"
"subvol=@persistent"
];
};
};
};
};
};
};
};
};
}

View file

@ -1,37 +0,0 @@
{
config,
lib,
modulesPath,
inputs,
...
}:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot = {
initrd = {
availableKernelModules = [
"xhci_pci"
"ahci"
"usb_storage"
"sd_mod"
"sdhci_pci"
];
};
kernelModules = [ "kvm-intel" ];
};
zramSwap = {
enable = true;
memoryPercent = 100;
};
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,27 +0,0 @@
{ pkgs, ... }:
let
cml-ucm-conf = pkgs.alsa-ucm-conf.overrideAttrs {
wttsrc = pkgs.fetchFromGitHub {
owner = "WeirdTreeThing";
repo = "chromebook-ucm-conf";
rev = "b6ce2a7";
hash = "sha256-QRUKHd3RQmg1tnZU8KCW0AmDtfw/daOJ/H3XU5qWTCc=";
};
postInstall = ''
echo "v0.4.1" > $out/chromebook.patched
cp -R $wttsrc/{common,codecs,platforms} $out/share/alsa/ucm2
cp -R $wttsrc/{cml,sof-rt5682} $out/share/alsa/ucm2/conf.d
'';
};
in
{
environment = {
systemPackages = with pkgs; [
maliit-keyboard
sof-firmware
];
sessionVariables.ALSA_CONFIG_UCM2 = "${cml-ucm-conf}/share/alsa/ucm2";
};
}

View file

@ -1,61 +0,0 @@
{ pkgs, ... }:
{
services = {
keyd = {
enable = true;
keyboards.main = {
ids = [ "0001:0001" ];
settings = {
main = {
meta = "overload(meta, esc)";
f1 = "back";
f2 = "forward";
f3 = "refresh";
f4 = "M-f11";
f5 = "M-w";
f6 = "brightnessdown";
f7 = "brightnessup";
f8 = "timeout(mute, 200, micmute)";
f9 = "play";
f10 = "timeout(nextsong, 200, previoussong)";
f13 = "delete";
"102nd" = "layer(function)";
};
shift = {
leftshift = "capslock";
rightshift = "capslock";
};
function = {
escape = "f1";
f1 = "f2";
f2 = "f3";
f3 = "f4";
f4 = "f5";
f5 = "f6";
f6 = "f7";
f7 = "f8";
f8 = "f9";
f9 = "f10";
f10 = "f11";
f13 = "f12";
y = "sysrq";
k = "home";
l = "pageup";
"," = "end";
"." = "pagedown";
};
};
};
};
upower.enable = true;
power-profiles-daemon.enable = true;
};
# TODO: remove once gmodena/nix-flatpak/issues/45 fixed
systemd.services."flatpak-managed-install" = {
serviceConfig = {
ExecStartPre = "${pkgs.coreutils}/bin/sleep 5";
};
};
}

View file

@ -1,31 +0,0 @@
{ pkgs, ... }:
let
qubesnsh = pkgs.writeTextFile {
name = "qubes.nsh";
text = "HD1f65535a1:EFI\\qubes\\grubx64.efi";
};
in
{
boot = {
kernelParams = [
"processor.max_cstate=1" # Fixes bug where ryzen cpus freeze when in highest C state
"clearcpuid=514"
"amdgpu.ppfeaturemask=0xfffd3fff" # Fixes amdgpu freezing
];
# QubesOS boot entry
loader.systemd-boot = {
extraFiles = {
"efi/edk2-shell/shell.efi" = "${pkgs.edk2-uefi-shell}/shell.efi";
"qubes.nsh" = qubesnsh;
};
extraEntries."qubes.conf" = ''
title Qubes OS
efi /efi/edk2-shell/shell.efi
options -nointerrupt qubes.nsh
sort-key ab
'';
};
};
}

View file

@ -1,82 +0,0 @@
{
config,
lib,
modulesPath,
...
}:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot = {
initrd = {
availableKernelModules = [
"amdgpu"
"nvme"
"xhci_pci"
"ahci"
"usbhid"
"sd_mod"
];
luks.devices."cryptroot" = {
device = "/dev/disk/by-uuid/f7dd4142-7109-4493-834d-4a831777f08d";
keyFile = "/dev/disk/by-partuuid/add5fc14-e20f-48be-8b2a-0799ef04d3cb";
};
};
kernelModules = [ "kvm-amd" ];
};
fileSystems = {
"/" = {
device = "/dev/disk/by-uuid/3287dbc3-c0fa-4096-a0b3-59b017cfecc8";
fsType = "btrfs";
options = [
"subvol=@root"
"noatime"
"compress=zstd"
];
};
"/home" = {
device = "/dev/disk/by-uuid/3287dbc3-c0fa-4096-a0b3-59b017cfecc8";
fsType = "btrfs";
options = [
"subvol=@home"
"noatime"
"compress=zstd"
];
};
"/boot/efi" = {
device = "/dev/disk/by-uuid/F2A2-CF5A";
fsType = "vfat";
options = [
"noatime"
"fmask=0077"
"dmask=0077"
];
};
"/nix" = {
device = "/dev/disk/by-uuid/3287dbc3-c0fa-4096-a0b3-59b017cfecc8";
fsType = "btrfs";
options = [
"subvol=@nix"
"noatime"
"compress=zstd"
];
};
"/persistent" = {
device = "/dev/disk/by-uuid/3287dbc3-c0fa-4096-a0b3-59b017cfecc8";
fsType = "btrfs";
options = [
"subvol=@persistent"
"noatime"
"compress=zstd"
];
};
};
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,8 +0,0 @@
{ pkgs, ... }:
{
hardware = {
amdgpu.opencl.enable = true;
graphics.extraPackages = with pkgs; [ rocmPackages.clr.icd ];
};
}

View file

@ -1,31 +0,0 @@
{ pkgs, ... }:
let
reboot-into-qubes = pkgs.makeDesktopItem {
name = "reboot-into-qubes";
icon = pkgs.fetchurl {
url = "https://raw.githubusercontent.com/vinceliuice/Qogir-icon-theme/31f267e1f5fd4e9596bfd78dfb41a03d3a9f33ee/src/scalable/apps/distributor-logo-qubes.svg";
sha256 = "sha256-QbHr7s5Wcs7uFtfqZctMyS0iDbMfiiZOKy2nHhDOfn0=";
};
desktopName = "Qubes OS";
genericName = "Reboot into Qubes OS";
categories = [ "System" ];
startupNotify = true;
exec = pkgs.writeShellScript "reboot-into-qubes" ''
${pkgs.yad}/bin/yad --form \
--title="Qubes OS" \
--image distributor-logo-qubes \
--text "Are you sure you want to reboot into Qubes OS?" \
--button="Yes:0" --button="Cancel:1"
if [ $? -eq 0 ]; then
systemctl reboot --boot-loader-entry=qubes.conf
fi
'';
};
in
{
environment.systemPackages = [ reboot-into-qubes ];
programs.steam.dedicatedServer.openFirewall = true;
}

View file

@ -1,11 +0,0 @@
{
services.keyd = {
enable = true;
keyboards.main = {
ids = [ "5653:0001" ];
settings.main = {
esc = "overload(meta, esc)";
};
};
};
}

View file

@ -1,6 +0,0 @@
{
boot = {
initrd.systemd.enable = true;
loader.efi.efiSysMountPoint = "/boot/efi";
};
}

View file

@ -1,64 +0,0 @@
{ inputs, ... }:
{
imports = [ inputs.disko.nixosModules.default ];
disko.devices.disk.main = {
type = "disk";
device = "/dev/disk/by-id/scsi-360b207ed25d84372a95d1ecf842f8e20";
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
start = "1MiB";
end = "512MiB";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot/efi";
mountOptions = [
"noatime"
"fmask=0077"
"dmask=0077"
];
};
};
root = {
priority = 2;
name = "root";
size = "100%";
content = {
type = "btrfs";
extraArgs = [ "-f" ];
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = [
"noatime"
"compress=zstd"
];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = [
"noatime"
"compress=zstd"
];
};
"@persistent" = {
mountpoint = "/persistent";
mountOptions = [
"noatime"
"compress=zstd"
];
};
};
};
};
};
};
};
}

View file

@ -1,23 +0,0 @@
{ config, pkgs, ... }:
{
services.fail2ban = {
enable = true;
maxretry = 5;
ignoreIP = [
"127.0.0.0/8"
"::1"
"10.0.0.0/8"
"172.16.0.0/12"
"192.168.0.0/16"
"100.64.0.0/10"
];
bantime = "1h";
bantime-increment = {
enable = true;
multipliers = "1 2 4 8 16 32 64";
maxtime = "10000h";
overalljails = true;
};
};
}

View file

@ -1,76 +0,0 @@
{
config,
lib,
inputs,
...
}:
let
mkNginxVHosts = inputs.self.lib.mkNginxVHosts;
in
{
services = {
forgejo = {
enable = true;
settings = {
session.COOKIE_SECURE = true;
server = {
PROTOCOL = "http+unix";
DOMAIN = "git.baduhai.dev";
ROOT_URL = "https://git.baduhai.dev";
OFFLINE_MODE = true; # disable use of CDNs
SSH_DOMAIN = "git.baduhai.dev";
SSH_USER = "forgejo";
SSH_PORT = lib.head config.services.openssh.ports;
};
log.LEVEL = "Warn";
mailer.ENABLED = false;
actions.ENABLED = false;
service.DISABLE_REGISTRATION = true;
oauth2_client = {
ENABLE_AUTO_REGISTRATION = true;
UPDATE_AVATAR = true;
ACCOUNT_LINKING = "login";
USERNAME = "preferred_username";
};
};
};
nginx.virtualHosts = mkNginxVHosts {
domains."git.baduhai.dev".locations."/".proxyPass =
"http://unix:${config.services.forgejo.settings.server.HTTP_ADDR}:/";
};
fail2ban.jails.forgejo = {
settings = {
enabled = true;
filter = "forgejo";
maxretry = 3;
findtime = "10m";
bantime = "1h";
};
};
};
environment = {
etc."fail2ban/filter.d/forgejo.conf".text = ''
[Definition]
failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>
ignoreregex =
journalmatch = _SYSTEMD_UNIT=forgejo.service
'';
persistence.main.directories = [
{
directory = config.services.forgejo.stateDir;
inherit (config.services.forgejo) user group;
mode = "0700";
}
];
};
# Disable PrivateMounts to allow LoadCredential to work with bind-mounted directories
systemd.services.forgejo.serviceConfig = {
PrivateMounts = lib.mkForce false;
ProtectSystem = lib.mkForce false;
};
}

View file

@ -1,20 +0,0 @@
{
lib,
modulesPath,
...
}:
{
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
boot.initrd.availableKernelModules = [
"xhci_pci"
"virtio_pci"
"virtio_scsi"
"usbhid"
];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
}

View file

@ -1,8 +0,0 @@
{
networking = {
firewall = {
allowedTCPPorts = [ 25566 ];
allowedUDPPorts = [ 25566 ];
};
};
}

View file

@ -1,56 +0,0 @@
{
config,
lib,
inputs,
...
}:
let
services = inputs.self.services;
localDomains = lib.unique (map (s: s.domain) (lib.filter (s: s.host == "trantor") services));
acmeCerts = lib.genAttrs localDomains (domain: {
group = "nginx";
});
in
{
security.acme = {
acceptTerms = true;
defaults = {
email = "baduhai@proton.me";
dnsResolver = "1.1.1.1:53";
dnsProvider = "cloudflare";
credentialsFile = config.age.secrets.cloudflare.path;
};
certs = acmeCerts;
};
services.nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
virtualHosts = {
"_" = {
default = true;
locations."/".return = "444";
};
};
};
users.users.nginx.extraGroups = [ "acme" ];
networking.firewall.allowedTCPPorts = [
80
443
];
age.secrets.cloudflare = {
file = "${inputs.self}/secrets/cloudflare.age";
owner = "nginx";
group = "nginx";
};
}

View file

@ -1,23 +0,0 @@
{ ... }:
{
services = {
openssh = {
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
};
};
fail2ban.jails.sshd = {
settings = {
enabled = true;
port = "ssh";
filter = "sshd";
logpath = "/var/log/auth.log";
maxretry = 3;
findtime = "10m";
bantime = "1h";
};
};
};
}

View file

@ -1,58 +0,0 @@
{ inputs, lib, ... }:
let
services = inputs.self.services;
in
{
services.unbound = {
enable = true;
enableRootTrustAnchor = true;
settings = {
server = {
interface = [
"0.0.0.0"
"::"
];
access-control = [
"127.0.0.0/8 allow"
"100.64.0.0/10 allow" # Tailscale CGNAT range
"::1/128 allow"
"fd7a:115c:a1e0::/48 allow" # Tailscale IPv6
];
num-threads = 2;
msg-cache-size = "50m";
rrset-cache-size = "100m";
cache-min-ttl = 300;
cache-max-ttl = 86400;
prefetch = true;
prefetch-key = true;
hide-identity = true;
hide-version = true;
so-rcvbuf = "1m";
so-sndbuf = "1m";
# Tailnet DNS records from shared services
local-zone = ''"baduhai.dev." transparent'';
local-data = map (e: ''"${e.domain}. IN A ${e.tailscaleIP}"'') services;
};
forward-zone = [
{
name = ".";
forward-addr = [
"1.1.1.1@853#cloudflare-dns.com"
"1.0.0.1@853#cloudflare-dns.com"
];
forward-tls-upstream = true;
}
];
};
};
networking.firewall = {
allowedTCPPorts = [ 53 ];
allowedUDPPorts = [ 53 ];
};
}

View file

@ -1,19 +0,0 @@
{ inputs, ... }:
let
mkHost = inputs.self.lib.mkHost;
in
{
flake.nixosConfigurations.alexandria = mkHost {
hostname = "alexandria";
nixpkgs = inputs.nixpkgs-stable;
extraModules = with inputs.self.modules.nixos; [
# base aspects
server
# other aspects
fwupd
libvirtd
];
};
}

View file

@ -1,24 +0,0 @@
{ inputs, ... }:
let
mkHost = inputs.self.lib.mkHost;
in
{
flake.nixosConfigurations.io = mkHost {
hostname = "io";
ephemeralRootDev = "/dev/mapper/cryptroot";
extraModules = with inputs.self.modules.nixos; [
# base aspects
desktop
# other aspects
ai
bluetooth
dev
libvirtd
networkmanager
niri
podman
];
};
}

View file

@ -1,26 +0,0 @@
{ inputs, ... }:
let
mkHost = inputs.self.lib.mkHost;
in
{
flake.nixosConfigurations.rotterdam = mkHost {
hostname = "rotterdam";
ephemeralRootDev = "/dev/mapper/cryptroot";
extraModules = with inputs.self.modules.nixos; [
# base aspects
desktop
gaming
# other aspects
ai
bluetooth
dev
fwupd
libvirtd
networkmanager
niri
podman
];
};
}

View file

@ -1,18 +0,0 @@
{ inputs, ... }:
let
mkHost = inputs.self.lib.mkHost;
in
{
flake.nixosConfigurations.trantor = mkHost {
hostname = "trantor";
system = "aarch64-linux";
nixpkgs = inputs.nixpkgs-stable;
ephemeralRootDev = "/dev/disk/by-id/scsi-360b207ed25d84372a95d1ecf842f8e20-part2";
extraModules = with inputs.self.modules.nixos; [
# base aspects
server
];
};
}

View file

@ -1,27 +0,0 @@
{ ... }:
{
flake.modules.nixos.libvirtd =
{
config,
lib,
pkgs,
...
}:
{
virtualisation = {
libvirtd.enable = true;
spiceUSBRedirection.enable = true;
};
programs.virt-manager.enable = true;
environment.systemPackages = with pkgs; [ lima ];
networking.firewall.trustedInterfaces = [ "virbr0" ];
users.users.user.extraGroups = [
"libvirt"
"libvirtd"
];
};
}

View file

@ -1,22 +0,0 @@
{ ... }:
{
flake.modules.nixos.lxc =
{
config,
lib,
pkgs,
...
}:
{
virtualisation = {
lxc = {
enable = true;
unprivilegedContainers = true;
};
incus.enable = true;
};
users.users.user.extraGroups = [ "incus-admin" ];
};
}

View file

@ -1,18 +0,0 @@
{ ... }:
{
flake.modules.nixos.networkmanager =
{
config,
lib,
pkgs,
...
}:
{
networking.networkmanager = {
enable = true;
wifi.backend = "iwd";
};
users.users.user.extraGroups = [ "networkmanager" ];
};
}

View file

@ -1,24 +0,0 @@
{ ... }:
{
flake.modules.nixos.podman =
{
config,
lib,
pkgs,
...
}:
{
virtualisation.podman = {
enable = true;
autoPrune.enable = true;
extraPackages = [ pkgs.podman-compose ];
};
security.unprivilegedUsernsClone = true; # Needed for rootless podman
systemd = {
services.podman-auto-update.enable = true;
timers.podman-auto-update.enable = true;
};
};
}

View file

@ -1,69 +0,0 @@
{ ... }:
{
flake.modules = {
nixos.stylix =
{ inputs, ... }:
{
imports = [ inputs.stylix.nixosModules.stylix ];
};
homeManager.stylix =
{
config,
inputs,
pkgs,
...
}:
{
imports = [ inputs.stylix.homeModules.stylix ];
stylix = {
enable = true;
polarity = "dark";
base16Scheme = "${pkgs.base16-schemes}/share/themes/tokyodark.yaml";
cursor = {
package = pkgs.kdePackages.breeze;
name = "breeze_cursors";
size = 24;
};
icons = {
enable = true;
package = pkgs.morewaita-icon-theme;
light = "MoreWaita";
dark = "MoreWaita";
};
opacity = {
applications = 1.0;
desktop = 1.0;
popups = config.stylix.opacity.desktop;
terminal = 1.0;
};
fonts = {
serif = {
package = pkgs.source-serif;
name = "Source Serif 4 Display";
};
sansSerif = {
package = pkgs.inter;
name = "Inter";
};
monospace = {
package = pkgs.nerd-fonts.fira-code;
name = "FiraCode Nerd Font";
};
emoji = {
package = pkgs.noto-fonts-color-emoji;
name = "Noto Color Emoji";
};
sizes = {
applications = 10;
desktop = config.stylix.fonts.sizes.applications;
popups = config.stylix.fonts.sizes.applications;
terminal = 12;
};
};
};
};
};
}

View file

@ -1,55 +0,0 @@
{ inputs, ... }:
{
flake.modules = {
nixos.base =
{ lib, pkgs, ... }:
{
imports = with inputs.self.modules.nixos; [
boot
console
firewall
fish
locale
nix
security
ssh
];
environment = {
systemPackages = with pkgs; [
git
fastfetch
nixos-firewall-tool
sysz
wget
yazi
];
shellAliases = {
cat = "${lib.getExe pkgs.bat} --paging=never --style=plain";
ls = "${lib.getExe pkgs.eza} --git --icons --group-directories-first";
tree = "ls --tree";
};
};
programs.command-not-found.enable = false;
services = {
dbus.implementation = "broker";
irqbalance.enable = true;
fstrim.enable = true;
tailscale = {
enable = true;
extraUpFlags = [ "--operator=user" ];
};
};
};
homeManager.base =
{ ... }:
{
imports = with inputs.self.modules.homeManager; [
bash
fish
];
};
};
}

View file

@ -1,33 +0,0 @@
{ inputs, ... }:
{
flake.modules = {
nixos.cli =
{ pkgs, ... }:
{
imports = with inputs.self.modules.nixos; [
btop
helix
tmux
];
environment.systemPackages = with pkgs; [
p7zip
rclone
];
};
homeManager.cli =
{ ... }:
{
imports = with inputs.self.modules.homeManager; [
btop
comma
direnv
helix
hm-cli
starship
tmux
];
};
};
}

View file

@ -1,210 +0,0 @@
{
inputs,
...
}:
{
flake.modules = {
nixos.desktop =
{
config,
lib,
pkgs,
...
}:
{
imports = [
inputs.nix-flatpak.nixosModules.nix-flatpak
]
++ (with inputs.self.modules.nixos; [
graphics
media
office
web
]);
boot = {
plymouth.enable = true;
initrd.systemd.enable = true;
loader.efi.efiSysMountPoint = "/boot/efi";
kernelPackages = pkgs.linuxPackages_xanmod_latest;
extraModprobeConfig = ''
options bluetooth disable_ertm=1
'';
kernel.sysctl = {
"net.ipv4.tcp_mtu_probing" = 1;
};
kernelParams = [
"quiet"
"splash"
"i2c-dev"
"i2c-piix4"
"loglevel=3"
"udev.log_priority=3"
"rd.udev.log_level=3"
"rd.systemd.show_status=false"
];
};
nix = {
registry.nixpkgs.flake = inputs.nixpkgs;
nixPath = [
"nixpkgs=${inputs.nixpkgs}"
"/nix/var/nix/profiles/per-user/root/channels"
];
};
environment = {
etc."channels/nixpkgs".source = inputs.nixpkgs.outPath;
sessionVariables = {
KDEHOME = "$XDG_CONFIG_HOME/kde4"; # Stops kde from placing a .kde4 folder in the home dir
NIXOS_OZONE_WL = "1"; # Forces chromium and most electron apps to run in wayland
};
systemPackages = with pkgs; [
adwaita-icon-theme
ghostty
gnome-disk-utility
junction
libfido2
mission-center
nautilus
toggleaudiosink
unrar
];
};
services = {
printing.enable = true;
udev.packages = with pkgs; [ yubikey-personalization ];
keyd = {
enable = true;
keyboards.all = {
ids = [ "*" ];
settings.main.capslock = "overload(meta, esc)";
};
};
pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
wireplumber.enable = true;
};
greetd = {
enable = true;
settings.default_session.user = "greeter";
};
flatpak = {
enable = true;
packages = [
"com.github.tchx84.Flatseal"
"com.rustdesk.RustDesk"
];
uninstallUnmanaged = true;
update.auto.enable = true;
};
gvfs.enable = true;
};
security.rtkit.enable = true; # Needed for pipewire to acquire realtime priority
users = {
users.greeter = {
isSystemUser = true;
group = "greeter";
};
groups.greeter = { };
};
programs = {
kdeconnect = {
enable = true;
package = pkgs.valent;
};
dconf.enable = true;
appimage = {
enable = true;
binfmt = true;
};
};
fonts = {
fontDir.enable = true;
packages = with pkgs; [
corefonts
inter
nerd-fonts.fira-code
noto-fonts-cjk-sans
noto-fonts-color-emoji
roboto
];
};
xdg.portal = {
extraPortals = with pkgs; [
xdg-desktop-portal-gnome
xdg-desktop-portal-gtk
];
config.common.default = "*";
};
};
homeManager.desktop =
{
config,
lib,
pkgs,
inputs,
...
}:
{
imports = [
inputs.vicinae.homeManagerModules.default
]
++ (with inputs.self.modules.homeManager; [ media ]);
fonts.fontconfig.enable = true;
home = {
packages = with pkgs; [ xwayland-satellite ];
sessionVariables.TERMINAL = "ghostty";
};
services.vicinae = {
enable = true;
systemd = {
enable = true;
autoStart = true;
};
};
programs = {
ghostty = {
enable = true;
settings = {
cursor-style = "block";
shell-integration-features = "no-cursor";
cursor-style-blink = false;
custom-shader = "${builtins.fetchurl {
url = "https://raw.githubusercontent.com/hackr-sh/ghostty-shaders/cb6eb4b0d1a3101c869c62e458b25a826f9dcde3/cursor_blaze.glsl";
sha256 = "sha256:0g2lgqjdrn3c51glry7x2z30y7ml0y61arl5ykmf4yj0p85s5f41";
}}";
bell-features = "";
gtk-titlebar-style = "tabs";
keybind = [ "shift+enter=text:\\x1b\\r" ];
};
};
password-store = {
enable = true;
package = pkgs.pass-wayland;
};
};
xdg = {
enable = true;
userDirs.enable = true;
};
};
};
}

View file

@ -1,48 +0,0 @@
{ inputs, ... }:
{
flake.modules = {
nixos.gaming =
{ pkgs, ... }:
{
imports = with inputs.self.modules.nixos; [
mangohud
steam
];
hardware = {
xpadneo.enable = true;
steam-hardware.enable = true; # Allow steam client to manage controllers
graphics.enable32Bit = true; # For OpenGL games
};
services.flatpak.packages = [
"com.github.k4zmu2a.spacecadetpinball"
"io.itch.itch"
"io.mrarm.mcpelauncher"
"net.retrodeck.retrodeck"
"org.freedesktop.Platform.VulkanLayer.MangoHud/x86_64/25.08"
rec {
appId = "com.hypixel.HytaleLauncher";
sha256 = "01307s44bklc1ldcigcn9n4lm8hf8q793v9fv7w4w04xd5zyh4rv";
bundle = "${pkgs.fetchurl {
url = "https://launcher.hytale.com/builds/release/linux/amd64/hytale-launcher-latest.flatpak";
inherit sha256;
}}";
}
];
environment.systemPackages = with pkgs; [
clonehero
heroic
prismlauncher
];
};
homeManager.gaming =
{ ... }:
{
imports = with inputs.self.modules.homeManager; [
mangohud
];
};
};
}

View file

@ -1,36 +0,0 @@
{ inputs, ... }:
{
flake.modules.nixos.server =
{
config,
lib,
pkgs,
...
}:
{
boot = {
kernelPackages = pkgs.linuxPackages_hardened;
kernel.sysctl = {
"net.ipv4.ip_forward" = 1;
"net.ipv6.conf.all.forwarding" = 1;
};
};
environment.etc."channels/nixpkgs".source = inputs.nixpkgs-stable.outPath;
nix = {
registry.nixpkgs.flake = inputs.nixpkgs-stable;
nixPath = [
"nixpkgs=/etc/channels/nixpkgs"
"/nix/var/nix/profiles/per-user/root/channels"
];
};
services.tailscale = {
extraSetFlags = [ "--advertise-exit-node" ];
useRoutingFeatures = "server";
};
};
}

View file

@ -1,17 +0,0 @@
{ ... }:
{
programs = {
git = {
enable = true;
settings.user = {
name = "William";
email = "baduhai@proton.me";
};
};
diff-so-fancy = {
enable = true;
enableGitIntegration = true;
};
};
}

View file

@ -1,12 +0,0 @@
{ ... }:
{
flake.modules.nixos.root =
{ pkgs, ... }:
{
users.users.root = {
shell = pkgs.fish;
hashedPassword = "!";
};
};
}

View file

@ -1,55 +0,0 @@
{ inputs, ... }:
let
mkHomeConfiguration = inputs.self.lib.mkHomeConfiguration;
in
{
flake = {
modules.nixos.user =
{ pkgs, ... }:
{
users.users.user = {
isNormalUser = true;
shell = pkgs.fish;
extraGroups = [
"networkmanager"
"wheel"
];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICQPkAyy+Du9Omc2WtnUF2TV8jFAF4H6mJi2D4IZ1nzg user@himalia"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3Y0PVpGfJHonqDS7qoCFhqzUvqGq9I9sax+F9e/5cs user@io"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1v3+q3EaruiiStWjubEJWvtejam/r41uoOpCdwJtLL user@rotterdam"
];
hashedPassword = "$6$Pj7v/CpstyuWQQV0$cNujVDhfMBdwlGVEnnd8t71.kZPixbo0u25cd.874iaqLTH4V5fa1f98V5zGapjQCz5JyZmsR94xi00sUrntT0";
};
};
homeConfigurations = {
"user@rotterdam" = mkHomeConfiguration {
user = "user";
hostname = "rotterdam";
userModules = with inputs.self.modules.homeManager; [
# system aspects
desktop
gaming
# other aspects
stylix
niri
];
};
"user@io" = mkHomeConfiguration {
user = "user";
hostname = "io";
userModules = with inputs.self.modules.homeManager; [
# system aspects
desktop
# other aspects
stylix
niri
];
};
};
};
}

View file

@ -1,42 +0,0 @@
# Shared service and host definitions
# This file can be imported directly (unlike aspects which use flake-parts)
{
hosts = {
alexandria = {
lanIP = "192.168.15.142";
tailscaleIP = "100.76.19.50";
};
trantor = {
tailscaleIP = "100.108.5.90";
};
};
services = [
{
name = "kanidm";
domain = "auth.baduhai.dev";
host = "alexandria";
}
{
name = "vaultwarden";
domain = "pass.baduhai.dev";
host = "alexandria";
}
{
name = "forgejo";
domain = "git.baduhai.dev";
host = "trantor";
public = true;
}
{
name = "nextcloud";
domain = "cloud.baduhai.dev";
host = "alexandria";
}
{
name = "jellyfin";
domain = "jellyfin.baduhai.dev";
host = "alexandria";
}
];
}

586
flake.lock generated
View file

@ -10,11 +10,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1770165109,
"narHash": "sha256-9VnK6Oqai65puVJ4WYtCTvlJeXxMzAp/69HhQuTdl/I=",
"lastModified": 1762618334,
"narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=",
"owner": "ryantm",
"repo": "agenix",
"rev": "b027ee29d959fda4b60b57566d64c98a202e0feb",
"rev": "fcdea223397448d35d9b31f798479227e80183f6",
"type": "github"
},
"original": {
@ -97,14 +97,14 @@
"nix-ai-tools",
"nixpkgs"
],
"systems": "systems_2"
"systems": "systems_3"
},
"locked": {
"lastModified": 1771437256,
"narHash": "sha256-bLqwib+rtyBRRVBWhMuBXPCL/OThfokA+j6+uH7jDGU=",
"lastModified": 1767386128,
"narHash": "sha256-BJDu7dIMauO2nYRSL4aI8wDNtEm2KOb7lDKP3hxdrpo=",
"owner": "numtide",
"repo": "blueprint",
"rev": "06ee7190dc2620ea98af9eb225aa9627b68b0e33",
"rev": "0ed984d51a3031065925ab08812a5434f40b93d4",
"type": "github"
},
"original": {
@ -135,16 +135,36 @@
"type": "github"
}
},
"disko": {
"deploy-rs": {
"inputs": {
"nixpkgs": "nixpkgs"
"flake-compat": "flake-compat",
"nixpkgs": "nixpkgs",
"utils": "utils"
},
"locked": {
"lastModified": 1769524058,
"narHash": "sha256-zygdD6X1PcVNR2PsyK4ptzrVEiAdbMqLos7utrMDEWE=",
"lastModified": 1766051518,
"narHash": "sha256-znKOwPXQnt3o7lDb3hdf19oDo0BLP4MfBOYiWkEHoik=",
"owner": "serokell",
"repo": "deploy-rs",
"rev": "d5eff7f948535b9c723d60cd8239f8f11ddc90fa",
"type": "github"
},
"original": {
"owner": "serokell",
"repo": "deploy-rs",
"type": "github"
}
},
"disko": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1768923567,
"narHash": "sha256-GVJ0jKsyXLuBzRMXCDY6D5J8wVdwP1DuQmmvYL/Vw/Q=",
"owner": "nix-community",
"repo": "disko",
"rev": "71a3fc97d80881e91710fe721f1158d3b96ae14d",
"rev": "00395d188e3594a1507f214a2f15d4ce5c07cb28",
"type": "github"
},
"original": {
@ -170,6 +190,22 @@
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1733328505,
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1767039857,
@ -185,7 +221,7 @@
"type": "github"
}
},
"flake-compat_2": {
"flake-compat_3": {
"flake": false,
"locked": {
"lastModified": 1747046372,
@ -206,11 +242,11 @@
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1769996383,
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
"lastModified": 1768135262,
"narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
"rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac",
"type": "github"
},
"original": {
@ -342,11 +378,11 @@
]
},
"locked": {
"lastModified": 1770915843,
"narHash": "sha256-ZwU5wXKNqpOQvjNz6aBp1j5peiBZow1++6pLnk5VAhs=",
"lastModified": 1768927746,
"narHash": "sha256-zyMpWHqcpKVmRc1W2NEK7DAuyVJZV62Jdjqudg70b1k=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "6a1f7101d2c3ee87d485a87880d73b4665c6a4bd",
"rev": "63a87808f5f9b6e4195a1d33f6ea25d23f4aa0df",
"type": "github"
},
"original": {
@ -385,11 +421,11 @@
]
},
"locked": {
"lastModified": 1769872935,
"narHash": "sha256-07HMIGQ/WJeAQJooA7Kkg1SDKxhAiV6eodvOwTX6WKI=",
"lastModified": 1768434960,
"narHash": "sha256-cJbFn17oyg6qAraLr+NVeNJrXsrzJdrudkzI4H2iTcg=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "f4ad5068ee8e89e4a7c2e963e10dd35cd77b37b7",
"rev": "b4d88c9ac42ae1a745283f6547701da43b6e9f9b",
"type": "github"
},
"original": {
@ -401,14 +437,14 @@
"impermanence": {
"inputs": {
"home-manager": "home-manager_3",
"nixpkgs": "nixpkgs_2"
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1769548169,
"narHash": "sha256-03+JxvzmfwRu+5JafM0DLbxgHttOQZkUtDWBmeUkN8Y=",
"lastModified": 1768835187,
"narHash": "sha256-6nY0ixjGjPQCL+/sUC1B1MRiO1LOI3AkRSIywm3i3bE=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "7b1d382faf603b6d264f58627330f9faa5cba149",
"rev": "0d633a69480bb3a3e2f18c080d34a8fa81da6395",
"type": "github"
},
"original": {
@ -417,33 +453,94 @@
"type": "github"
}
},
"import-tree": {
"niri": {
"inputs": {
"nixpkgs": "nixpkgs_4",
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1763762820,
"narHash": "sha256-ZvYKbFib3AEwiNMLsejb/CWs/OL/srFQ8AogkebEPF0=",
"owner": "vic",
"repo": "import-tree",
"rev": "3c23749d8013ec6daa1d7255057590e9ca726646",
"lastModified": 1760963745,
"narHash": "sha256-FVf9YFw2wQnMAxvMxEk+vFakXhPQUSapDpGmlLzAxjg=",
"owner": "baduhai",
"repo": "niri",
"rev": "dd3e3d1009991ecd87ab7253c9e7696acf2bc943",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "import-tree",
"owner": "baduhai",
"ref": "auto-center-when-space-available",
"repo": "niri",
"type": "github"
}
},
"niri-flake": {
"inputs": {
"niri-stable": "niri-stable",
"niri-unstable": "niri-unstable",
"nixpkgs": "nixpkgs_5",
"nixpkgs-stable": "nixpkgs-stable",
"xwayland-satellite-stable": "xwayland-satellite-stable",
"xwayland-satellite-unstable": "xwayland-satellite-unstable"
},
"locked": {
"lastModified": 1768877436,
"narHash": "sha256-ct4qxmFJeJbaJKiOnXOZmRmVmk7TpT+lohuTgTr+kYQ=",
"owner": "sodiboo",
"repo": "niri-flake",
"rev": "6581f5458309233622c1b73c8902dcaea7be16eb",
"type": "github"
},
"original": {
"owner": "sodiboo",
"repo": "niri-flake",
"type": "github"
}
},
"niri-stable": {
"flake": false,
"locked": {
"lastModified": 1756556321,
"narHash": "sha256-RLD89dfjN0RVO86C/Mot0T7aduCygPGaYbog566F0Qo=",
"owner": "YaLTeR",
"repo": "niri",
"rev": "01be0e65f4eb91a9cd624ac0b76aaeab765c7294",
"type": "github"
},
"original": {
"owner": "YaLTeR",
"ref": "v25.08",
"repo": "niri",
"type": "github"
}
},
"niri-unstable": {
"flake": false,
"locked": {
"lastModified": 1768678265,
"narHash": "sha256-Ub8eed4DsfIDWyg30xEe+8bSxL/z5Af/gCjmvJ0V/Hs=",
"owner": "YaLTeR",
"repo": "niri",
"rev": "d7184a04b904e07113f4623610775ae78d32394c",
"type": "github"
},
"original": {
"owner": "YaLTeR",
"repo": "niri",
"type": "github"
}
},
"nix-ai-tools": {
"inputs": {
"blueprint": "blueprint",
"nixpkgs": "nixpkgs_3",
"nixpkgs": "nixpkgs_6",
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1771816560,
"narHash": "sha256-q5Wsb1573qDfIPJctG9CBZP0NMniejoB7SmBLZIVAHg=",
"lastModified": 1768922080,
"narHash": "sha256-gFoGvnW2YDWsxKD56kdiXbhh9vBPAU3yusssbXF0UMo=",
"owner": "numtide",
"repo": "llm-agents.nix",
"rev": "db94a329058a1a37b49d3209af85708b3338559a",
"rev": "78f3fdc13ef903475aa5bfc0f85eeefaa36af837",
"type": "github"
},
"original": {
@ -475,11 +572,11 @@
]
},
"locked": {
"lastModified": 1770315571,
"narHash": "sha256-hy0gcAgAcxrnSWKGuNO+Ob0x6jQ2xkR6hoaR0qJBHYs=",
"lastModified": 1765267181,
"narHash": "sha256-d3NBA9zEtBu2JFMnTBqWj7Tmi7R5OikoU2ycrdhQEws=",
"owner": "nix-community",
"repo": "nix-index-database",
"rev": "2684bb8080a6f2ca5f9d494de5ef875bc1c4ecdb",
"rev": "82befcf7dc77c909b0f2a09f5da910ec95c5b78f",
"type": "github"
},
"original": {
@ -490,17 +587,17 @@
},
"nixos-cli": {
"inputs": {
"flake-compat": "flake-compat",
"flake-compat": "flake-compat_2",
"flake-parts": "flake-parts_2",
"nixpkgs": "nixpkgs_4",
"nixpkgs": "nixpkgs_7",
"optnix": "optnix"
},
"locked": {
"lastModified": 1770862985,
"narHash": "sha256-TFRhwVzPg3ly388J3CYYvjrma/dWjsBVpNE437bWeHk=",
"lastModified": 1768778579,
"narHash": "sha256-6w1Mhg6+46LlaheCa1O/jIk02ukerZ7DdUf9GlQVGxc=",
"owner": "nix-community",
"repo": "nixos-cli",
"rev": "9a2e97e8832b211df22c5cb21a55ebf1c3eb2be1",
"rev": "5e79001c7a8b556c3c61d4ef38f0f0fa1187ee90",
"type": "github"
},
"original": {
@ -511,11 +608,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1769330179,
"narHash": "sha256-yxgb4AmkVHY5OOBrC79Vv6EVd4QZEotqv+6jcvA212M=",
"lastModified": 1743014863,
"narHash": "sha256-jAIUqsiN2r3hCuHji80U7NNEafpIMBXiwKlSrjWMlpg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "48698d12cc10555a4f3e3222d9c669b884a49dfe",
"rev": "bd3bac8bfb542dbde7ffffb6987a1a1f9d41699f",
"type": "github"
},
"original": {
@ -527,11 +624,11 @@
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1769909678,
"narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=",
"lastModified": 1765674936,
"narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "72716169fe93074c333e8d0173151350670b824c",
"rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
"type": "github"
},
"original": {
@ -557,11 +654,27 @@
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1770770419,
"narHash": "sha256-iKZMkr6Cm9JzWlRYW/VPoL0A9jVKtZYiU4zSrVeetIs=",
"lastModified": 1768773494,
"narHash": "sha256-XsM7GP3jHlephymxhDE+/TKKO1Q16phz/vQiLBGhpF4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "77ef7a29d276c6d8303aece3444d61118ef71ac2",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable_2": {
"locked": {
"lastModified": 1768773494,
"narHash": "sha256-XsM7GP3jHlephymxhDE+/TKKO1Q16phz/vQiLBGhpF4=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "6c5e707c6b5339359a9a9e215c5e66d6d802fd7a",
"rev": "77ef7a29d276c6d8303aece3444d61118ef71ac2",
"type": "github"
},
"original": {
@ -571,87 +684,7 @@
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1768564909,
"narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1771207753,
"narHash": "sha256-b9uG8yN50DRQ6A7JdZBfzq718ryYrlmGgqkRm9OOwCE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d1c15b7d5806069da59e819999d70e1cec0760bf",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1767151656,
"narHash": "sha256-ujL2AoYBnJBN262HD95yer7QYUmYp5kFZGYbyCCKxq8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f665af0cdb70ed27e1bd8f9fdfecaf451260fc55",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_5": {
"locked": {
"lastModified": 1759070547,
"narHash": "sha256-JVZl8NaVRYb0+381nl7LvPE+A774/dRpif01FKLrYFQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "647e5c14cbd5067f44ac86b74f014962df460840",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_6": {
"locked": {
"lastModified": 1770562336,
"narHash": "sha256-ub1gpAONMFsT/GU2hV6ZWJjur8rJ6kKxdm9IlCT0j84=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "d6c71932130818840fc8fe9509cf50be8c64634f",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_7": {
"nixpkgs_10": {
"locked": {
"lastModified": 1767767207,
"narHash": "sha256-Mj3d3PfwltLmukFal5i3fFt27L6NiKXdBezC1EBuZs4=",
@ -667,7 +700,7 @@
"type": "github"
}
},
"nixpkgs_8": {
"nixpkgs_11": {
"locked": {
"lastModified": 1762111121,
"narHash": "sha256-4vhDuZ7OZaZmKKrnDpxLZZpGIJvAeMtK6FKLJYUtAdw=",
@ -683,13 +716,141 @@
"type": "github"
}
},
"nixpkgs_9": {
"nixpkgs_12": {
"locked": {
"lastModified": 1769461804,
"narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
"lastModified": 1768127708,
"narHash": "sha256-1Sm77VfZh3mU0F5OqKABNLWxOuDeHIlcFjsXeeiPazs=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
"rev": "ffbc9f8cbaacfb331b6017d5a5abb21a492c9a38",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1768661221,
"narHash": "sha256-MJwOjrIISfOpdI9x4C+5WFQXvHtOuj5mqLZ4TMEtk1M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "3327b113f2ef698d380df83fbccefad7e83d7769",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1768564909,
"narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1757967192,
"narHash": "sha256-/aA9A/OBmnuOMgwfzdsXRusqzUpd8rQnQY8jtrHK+To=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0d7c15863b251a7a50265e57c1dca1a7add2e291",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_5": {
"locked": {
"lastModified": 1768564909,
"narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_6": {
"locked": {
"lastModified": 1768783163,
"narHash": "sha256-tLj4KcRDLakrlpvboTJDKsrp6z2XLwyQ4Zmo+w8KsY4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "bde09022887110deb780067364a0818e89258968",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_7": {
"locked": {
"lastModified": 1767151656,
"narHash": "sha256-ujL2AoYBnJBN262HD95yer7QYUmYp5kFZGYbyCCKxq8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f665af0cdb70ed27e1bd8f9fdfecaf451260fc55",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_8": {
"locked": {
"lastModified": 1759070547,
"narHash": "sha256-JVZl8NaVRYb0+381nl7LvPE+A774/dRpif01FKLrYFQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "647e5c14cbd5067f44ac86b74f014962df460840",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_9": {
"locked": {
"lastModified": 1768564909,
"narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f",
"type": "github"
},
"original": {
@ -706,11 +867,11 @@
]
},
"locked": {
"lastModified": 1770922006,
"narHash": "sha256-xg40mnp5KKBepACmvlPzmn5iPyUBxktfv50saSVUn0M=",
"lastModified": 1768924718,
"narHash": "sha256-T4H/VMjGwBuHEIrPYWfXQ73XV0foCuFGgH7k3SNSJDo=",
"owner": "noctalia-dev",
"repo": "noctalia-shell",
"rev": "d87364964948b9d691f8363f85a5e23bee154df9",
"rev": "1ef5c0eb307e8a4f30dfa6bcc75cf90ae8c6af46",
"type": "github"
},
"original": {
@ -746,8 +907,8 @@
},
"optnix": {
"inputs": {
"flake-compat": "flake-compat_2",
"nixpkgs": "nixpkgs_5"
"flake-compat": "flake-compat_3",
"nixpkgs": "nixpkgs_8"
},
"locked": {
"lastModified": 1765418479,
@ -766,17 +927,19 @@
"root": {
"inputs": {
"agenix": "agenix",
"deploy-rs": "deploy-rs",
"disko": "disko",
"flake-parts": "flake-parts",
"home-manager": "home-manager_2",
"impermanence": "impermanence",
"import-tree": "import-tree",
"niri": "niri",
"niri-flake": "niri-flake",
"nix-ai-tools": "nix-ai-tools",
"nix-flatpak": "nix-flatpak",
"nix-index-database": "nix-index-database",
"nixos-cli": "nixos-cli",
"nixpkgs": "nixpkgs_6",
"nixpkgs-stable": "nixpkgs-stable",
"nixpkgs": "nixpkgs_9",
"nixpkgs-stable": "nixpkgs-stable_2",
"noctalia": "noctalia",
"stylix": "stylix",
"terranix": "terranix",
@ -784,6 +947,27 @@
"zen-browser": "zen-browser"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
"niri",
"nixpkgs"
]
},
"locked": {
"lastModified": 1757989933,
"narHash": "sha256-9cpKYWWPCFhgwQTww8S94rTXgg8Q8ydFv9fXM6I8xQM=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "8249aa3442fb9b45e615a35f39eca2fe5510d7c3",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"stylix": {
"inputs": {
"base16": "base16",
@ -793,9 +977,9 @@
"firefox-gnome-theme": "firefox-gnome-theme",
"flake-parts": "flake-parts_3",
"gnome-shell": "gnome-shell",
"nixpkgs": "nixpkgs_7",
"nixpkgs": "nixpkgs_10",
"nur": "nur",
"systems": "systems_3",
"systems": "systems_4",
"tinted-foot": "tinted-foot",
"tinted-kitty": "tinted-kitty",
"tinted-schemes": "tinted-schemes",
@ -803,11 +987,11 @@
"tinted-zed": "tinted-zed"
},
"locked": {
"lastModified": 1770914701,
"narHash": "sha256-QHFYyngohNhih4w+3IqQty5DV+p1txsx1kkk6XJWar8=",
"lastModified": 1768744881,
"narHash": "sha256-3+h7OxqfrPIB/tRsiZXWE9sCbTm7NQN5Ie428p+S6BA=",
"owner": "danth",
"repo": "stylix",
"rev": "db03fed72e5ca02be34e1d24789345a943329738",
"rev": "06684f00cfbee14da96fd4307b966884de272d3a",
"type": "github"
},
"original": {
@ -891,13 +1075,28 @@
"type": "github"
}
},
"systems_6": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"terranix": {
"inputs": {
"flake-parts": "flake-parts_4",
"nixpkgs": [
"nixpkgs"
],
"systems": "systems_4"
"systems": "systems_5"
},
"locked": {
"lastModified": 1762472226,
@ -1002,11 +1201,11 @@
]
},
"locked": {
"lastModified": 1770228511,
"narHash": "sha256-wQ6NJSuFqAEmIg2VMnLdCnUc0b7vslUohqqGGD+Fyxk=",
"lastModified": 1768158989,
"narHash": "sha256-67vyT1+xClLldnumAzCTBvU0jLZ1YBcf4vANRWP3+Ak=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "337a4fe074be1042a35086f15481d763b8ddc0e7",
"rev": "e96d59dff5c0d7fddb9d113ba108f03c3ef99eca",
"type": "github"
},
"original": {
@ -1015,17 +1214,35 @@
"type": "github"
}
},
"vicinae": {
"utils": {
"inputs": {
"nixpkgs": "nixpkgs_8",
"systems": "systems_5"
"systems": "systems_2"
},
"locked": {
"lastModified": 1770912475,
"narHash": "sha256-21lurBRyHgJbVD3E0/i7Fhxi4rBUxyznGfKpdGVtEdc=",
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"vicinae": {
"inputs": {
"nixpkgs": "nixpkgs_11",
"systems": "systems_6"
},
"locked": {
"lastModified": 1768856963,
"narHash": "sha256-u5bWDuwk6oieTnvm1YjNotcYK8iJSddH5+S68+X4TSc=",
"owner": "vicinaehq",
"repo": "vicinae",
"rev": "0c70267ab7e07d7972012fcf8ae58808a32a2e86",
"rev": "934bc0ad47be6dbd6498a0dac655c4613fd0ab27",
"type": "github"
},
"original": {
@ -1034,17 +1251,50 @@
"type": "github"
}
},
"xwayland-satellite-stable": {
"flake": false,
"locked": {
"lastModified": 1755491097,
"narHash": "sha256-m+9tUfsmBeF2Gn4HWa6vSITZ4Gz1eA1F5Kh62B0N4oE=",
"owner": "Supreeeme",
"repo": "xwayland-satellite",
"rev": "388d291e82ffbc73be18169d39470f340707edaa",
"type": "github"
},
"original": {
"owner": "Supreeeme",
"ref": "v0.7",
"repo": "xwayland-satellite",
"type": "github"
}
},
"xwayland-satellite-unstable": {
"flake": false,
"locked": {
"lastModified": 1768765571,
"narHash": "sha256-C1JbyJ3ftogmN3vmLNfyPtnJw2wY64TiUTIhFtk1Leg=",
"owner": "Supreeeme",
"repo": "xwayland-satellite",
"rev": "ed1cef792b4def3321ff9ab5479df09609f17a69",
"type": "github"
},
"original": {
"owner": "Supreeeme",
"repo": "xwayland-satellite",
"type": "github"
}
},
"zen-browser": {
"inputs": {
"home-manager": "home-manager_4",
"nixpkgs": "nixpkgs_9"
"nixpkgs": "nixpkgs_12"
},
"locked": {
"lastModified": 1771000521,
"narHash": "sha256-5UDaXr770MaDac9HcFvGlUjsqyOoNbFdHArmjmtHcVk=",
"lastModified": 1768919538,
"narHash": "sha256-w10iy/aqd5LtD78NDWWG+eKGzkb+cGhAAo7PVciLbWE=",
"owner": "0xc000022070",
"repo": "zen-browser-flake",
"rev": "80ce62fd26af1934454f405bcb2510ceeea8d3a2",
"rev": "37149a5b77e8fd2b5332e8cec9edf39ca5b8e8bc",
"type": "github"
},
"original": {

View file

@ -2,57 +2,57 @@
description = "My nix hosts";
inputs = {
# nix tools
flake-parts.url = "github:hercules-ci/flake-parts";
import-tree.url = "github:vic/import-tree";
# nixos/hm
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-25.11";
home-manager = {
url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs";
};
# nixos/hm functionality modules
agenix = {
url = "github:ryantm/agenix";
inputs.nixpkgs.follows = "nixpkgs-stable";
};
disko.url = "github:nix-community/disko";
impermanence.url = "github:nix-community/impermanence";
nixos-cli.url = "github:nix-community/nixos-cli";
nix-flatpak.url = "github:gmodena/nix-flatpak/main";
stylix.url = "github:danth/stylix";
# nixos/hm program modules
nix-ai-tools.url = "github:numtide/llm-agents.nix";
nix-index-database = {
url = "github:nix-community/nix-index-database";
inputs.nixpkgs.follows = "nixpkgs";
};
disko.url = "github:nix-community/disko";
noctalia = {
url = "github:noctalia-dev/noctalia-shell";
inputs.nixpkgs.follows = "nixpkgs";
};
vicinae.url = "github:vicinaehq/vicinae";
nixos-cli.url = "github:nix-community/nixos-cli";
nix-flatpak.url = "github:gmodena/nix-flatpak/main";
zen-browser.url = "github:0xc000022070/zen-browser-flake";
# stand-alone tools
impermanence.url = "github:nix-community/impermanence";
deploy-rs.url = "github:serokell/deploy-rs";
niri-flake.url = "github:sodiboo/niri-flake";
nix-index-database = {
url = "github:nix-community/nix-index-database";
inputs.nixpkgs.follows = "nixpkgs";
};
terranix = {
url = "github:terranix/terranix";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-ai-tools.url = "github:numtide/llm-agents.nix";
vicinae.url = "github:vicinaehq/vicinae";
};
outputs =
inputs@{ flake-parts, import-tree, ... }:
let
aspectsModules = import-tree ./aspects;
packagesModules = import-tree ./packages;
shellsModules = import-tree ./shells;
terranixModules = import-tree ./terranix;
in
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [
"x86_64-linux"
@ -60,12 +60,14 @@
];
imports = [
flake-parts.flakeModules.modules
inputs.terranix.flakeModule
]
++ aspectsModules.imports
++ packagesModules.imports
++ shellsModules.imports
++ terranixModules.imports;
./deploy.nix
./devShells.nix
./homeConfigurations.nix
./nixosConfigurations.nix
./nixosModules.nix
./overlays.nix
./packages.nix
./terranixConfigurations.nix
];
};
}

37
modules/nix/agenix.nix Normal file
View file

@ -0,0 +1,37 @@
{
self,
inputs,
...
}:
{
flake-file.inputs = {
agenix = {
url = "github:ryantm/agenix";
inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
};
secrets = {
url = "path:./secrets";
flake = false;
};
};
flake.modules = {
nixos.secrets =
{ pkgs, ... }:
{
imports = [
inputs.agenix.nixosModules.default
];
environment.systemPackages = [ inputs.agenix.packages.${pkgs.stdenv.hostPlatform.system}.default ];
};
# homeManager.secrets =
# { pkgs, ... }:
# {
# imports = [
# inputs.agenix.homeManagerModules.default
# ];
# };
};
}

View file

@ -0,0 +1,25 @@
{
inputs,
...
}:
{
flake-file.inputs = {
flake-parts.url = "github:hercules-ci/flake-parts";
flake-file.url = "github:vic/flake-file";
import-tree.url = "github:vic/import-tree";
};
imports = [
inputs.flake-parts.flakeModules.modules
inputs.flake-file.flakeModules.default
];
flake-file.outputs = ''
inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } (inputs.import-tree ./modules)
'';
systems = [
"aarch64-linux"
"x86_64-linux"
];
}

12
modules/nix/factory.nix Normal file
View file

@ -0,0 +1,12 @@
{
lib,
...
}:
{
# factory: storage for factory aspect functions
options.flake.factory = lib.mkOption {
type = lib.types.attrsOf lib.types.unspecified;
default = { };
};
}

View file

@ -0,0 +1,36 @@
{
inputs,
config,
...
}:
let
home-manager-config =
{ lib, ... }:
{
home-manager = {
verbose = false;
useUserPackages = true;
useGlobalPkgs = true;
backupFileExtension = "backup";
backupCommand = "rm";
overwriteBackup = true;
};
};
in
{
flake-file.inputs = {
home-manager = {
url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs";
};
};
flake.modules.nixos.home-manager = {
imports = [
inputs.home-manager.nixosModules.home-manager
home-manager-config
];
};
}

View file

@ -0,0 +1,54 @@
{ inputs, ... }:
{
flake-file.inputs = {
impermanence.url = "github:nix-community/impermanence";
};
# convenience function to set persistence settings only, if impermanence module was imported
flake.lib = {
mkIfPersistence =
config: settings:
if config ? home then
(if config.home ? persistence then settings else { })
else
(if config.environment ? persistence then settings else { });
};
flake.modules.nixos.impermanence =
{ config, ... }:
{
imports = [
inputs.impermanence.nixosModules.impermanence
];
environment.persistence."/persistent" = {
hideMounts = true;
directories = [
"/var/log"
"/var/lib/nixos"
"/var/lib/systemd/coredump"
"/etc/NetworkManager/system-connections"
];
files = [
"/etc/machine-id"
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
"/etc/ssh/ssh_host_rsa_key"
"/etc/ssh/ssh_host_rsa_key.pub"
];
};
# home-manager.sharedModules = [
# {
# home.persistence."/persistent" = {
# };
# }
# ];
fileSystems."/persistent".neededForBoot = true;
programs.fuse.userAllowOther = true;
};
}

34
modules/nix/lib.nix Normal file
View file

@ -0,0 +1,34 @@
{
inputs,
lib,
...
}:
{
# Helper functions for creating system & home-manager configurations
options.flake.lib = lib.mkOption {
type = lib.types.attrsOf lib.types.unspecified;
default = { };
};
config.flake.lib = {
mkNixos = system: name: {
${name} = inputs.nixpkgs.lib.nixosSystem {
modules = [
inputs.self.modules.nixos.${name}
{ nixpkgs.hostPlatform = lib.mkDefault system; }
];
};
};
mkHomeManager = system: name: {
${name} = inputs.home-manager.lib.homeManagerConfiguration {
pkgs = inputs.nixpkgs.legacyPackages.${system};
modules = [
inputs.self.modules.homeManager.${name}
{ nixpkgs.config.allowUnfree = true; }
];
};
};
};
}

View file

@ -0,0 +1,42 @@
{
inputs,
withSystem,
...
}:
{
flake-file.inputs = {
pkgs-by-name-for-flake-parts.url = "github:drupol/pkgs-by-name-for-flake-parts";
packages = {
url = "path:./packages";
flake = false;
};
};
imports = [
inputs.pkgs-by-name-for-flake-parts.flakeModule
];
perSystem =
{ system, ... }:
{
pkgsDirectory = inputs.packages;
};
flake = {
overlays.default = _final: prev: {
local = withSystem prev.stdenv.hostPlatform.system ({ config, ... }: config.packages);
};
modules.generic.pkgs-by-name =
{ pkgs, ... }:
{
nixpkgs.overlays = [
inputs.self.overlays.default
];
nixpkgs-stable.overlays = [
inputs.self.overlays.default
];
};
};
}

View file

@ -1,35 +0,0 @@
{ ... }:
{
perSystem =
{ pkgs, ... }:
{
packages.base16-schemes = pkgs.stdenv.mkDerivation (finalAttrs: {
pname = "base16-schemes";
version = "0-unstable-2025-06-04";
src = pkgs.fetchFromGitHub {
owner = "tinted-theming";
repo = "schemes";
rev = "317a5e10c35825a6c905d912e480dfe8e71c7559";
hash = "sha256-d4km8W7w2zCUEmPAPUoLk1NlYrGODuVa3P7St+UrqkM=";
};
installPhase = ''
runHook preInstall
mkdir -p $out/share/themes/
install base16/*.yaml $out/share/themes/
runHook postInstall
'';
meta = {
description = "All the color schemes for use in base16 packages";
homepage = "https://github.com/tinted-theming/schemes";
maintainers = [ pkgs.lib.maintainers.DamienCassou ];
license = pkgs.lib.licenses.mit;
};
});
};
}

View file

@ -1,84 +0,0 @@
{ ... }:
{
perSystem =
{ pkgs, lib, ... }:
let
fastfetch-logo = pkgs.fetchurl {
url = "https://discourse.nixos.org/uploads/default/original/3X/3/6/36954e6d6aa32c8b00f50ca43f142d898c1ff535.png";
hash = "sha256-aLHz8jSAFocrn+Pb4vRq0wtkYFJpBpZRevd+VoZC/PQ=";
};
fastfetch-config = pkgs.writeText "fastfetch-config.json" (
builtins.toJSON {
"$schema" = "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json";
modules = [
"title"
"separator"
{
type = "os";
keyWidth = 9;
}
{
type = "kernel";
keyWidth = 9;
}
{
type = "uptime";
keyWidth = 9;
}
{
type = "shell";
keyWidth = 9;
}
"break"
{
type = "cpu";
keyWidth = 11;
}
{
type = "memory";
keyWidth = 11;
}
{
type = "swap";
keyWidth = 11;
}
{
type = "disk";
folders = "/";
keyWidth = 11;
}
{
type = "command";
key = "Systemd";
keyWidth = 11;
text = "echo \"$(systemctl list-units --state=failed --no-legend | wc -l) failed units, $(systemctl list-jobs --no-legend | wc -l) queued jobs\"";
}
"break"
{
type = "command";
key = "Public IP";
keyWidth = 15;
text = "curl -s -4 ifconfig.me 2>/dev/null || echo 'N/A'";
}
{
type = "command";
key = "Tailscale IP";
keyWidth = 15;
text = "tailscale ip -4 2>/dev/null || echo 'N/A'";
}
{
type = "command";
key = "Local IP";
keyWidth = 15;
text = "ip -4 addr show scope global | grep inet | head -n1 | awk '{print $2}' | cut -d/ -f1";
}
];
}
);
in
{
packages.fastfetch = pkgs.writeShellScriptBin "fastfetch" ''exec ${lib.getExe pkgs.fastfetch} --config ${fastfetch-config} --logo-type kitty --logo ${fastfetch-logo} --logo-padding-right 1 --logo-width 36 "$@" '';
};
}

View file

@ -1,107 +0,0 @@
{ ... }:
{
perSystem =
{ pkgs, ... }:
{
packages.hm-cli = pkgs.writeShellScriptBin "hm" ''
HM="${pkgs.lib.getExe pkgs.home-manager}"
FLAKE_PATH="''${HM_PATH:-$HOME/.config/home-manager}"
FLAKE_OUTPUT="''${HM_USER:-$(whoami)@$(hostname)}"
show_usage() {
cat <<EOF
Usage: hm <command> [args]
Commands:
apply Switch to a new generation
generation list List all generations
generation delete ID... Delete specified generation(s)
generation rollback Rollback to the previous generation
generation switch ID Switch to the specified generation
generation cleanup Delete all but the current generation
Environment Variables:
HM_PATH Override default flake path (~/.config/home-manager)
Currently set to "''${HM_PATH:-<not set>}"
HM_USER Override default user output ("$(whoami)@$(hostname)")
Currently set to "''${HM_USER:-<not set>}"
EOF
}
if [[ $# -eq 0 ]]; then
show_usage
exit 1
fi
case "$1" in
apply)
"$HM" switch --flake "$FLAKE_PATH#$FLAKE_OUTPUT" -b bkp
;;
generation)
if [[ $# -lt 2 ]]; then
echo "Error: generation command requires a subcommand"
show_usage
exit 1
fi
case "$2" in
list)
"$HM" generations
;;
delete)
if [[ $# -lt 3 ]]; then
echo "Error: delete requires at least one generation ID"
exit 1
fi
shift 2
"$HM" remove-generations "$@"
;;
rollback)
PREV_GEN=$("$HM" generations | \
sed -n 's/^[[:space:]]*id \([0-9]\+\).*/\1/p' | \
head -n 2 | tail -n 1)
if [[ -z "$PREV_GEN" ]]; then
echo "Error: could not determine previous generation (possibly only one generation exists)"
exit 1
fi
"$HM" switch --flake "$FLAKE_PATH" --switch-generation "$PREV_GEN" -b bkp
;;
switch)
if [[ $# -ne 3 ]]; then
echo "Error: switch requires exactly one generation ID"
exit 1
fi
"$HM" switch --flake "$FLAKE_PATH" --switch-generation "$3" -b bkp
;;
cleanup)
CURRENT_GEN=$("$HM" generations | sed -n 's/^.*id \([0-9]\+\) .* (current)$/\1/p')
if [[ -z "$CURRENT_GEN" ]]; then
echo "Error: could not determine current generation"
exit 1
fi
OLD_GENS=$("$HM" generations | sed -n 's/^.*id \([0-9]\+\) .*/\1/p' | grep -v "^$CURRENT_GEN$")
if [[ -z "$OLD_GENS" ]]; then
echo "No old generations to delete"
else
echo "Deleting generations: $(echo $OLD_GENS | tr '\n' ' ')"
echo "$OLD_GENS" | xargs "$HM" remove-generations
echo "Cleanup complete. Current generation $CURRENT_GEN preserved."
fi
;;
*)
echo "Error: unknown generation subcommand '$2'"
show_usage
exit 1
;;
esac
;;
*)
echo "Error: unknown command '$1'"
show_usage
exit 1
;;
esac
'';
};
}

View file

@ -1,21 +1,15 @@
{ ... }:
{ pkgs }:
{
perSystem =
{ pkgs, ... }:
{
packages.kwrite = pkgs.symlinkJoin {
name = "kwrite";
paths = [ pkgs.kdePackages.kate ];
postBuild = ''
rm -rf $out/bin/kate \
$out/bin/.kate-wrapped \
$out/share/applications/org.kde.kate.desktop \
$out/share/man \
$out/share/icons/hicolor/*/apps/kate.png \
$out/share/icons/hicolor/scalable/apps/kate.svg \
$out/share/appdata/org.kde.kate.appdata.xml
'';
};
};
pkgs.symlinkJoin {
name = "kwrite";
paths = [ pkgs.kdePackages.kate ];
postBuild = ''
rm -rf $out/bin/kate \
$out/bin/.kate-wrapped \
$out/share/applications/org.kde.kate.desktop \
$out/share/man \
$out/share/icons/hicolor/*/apps/kate.png \
$out/share/icons/hicolor/scalable/apps/kate.svg \
$out/share/appdata/org.kde.kate.appdata.xml
'';
}

View file

@ -1,32 +0,0 @@
{ ... }:
{
perSystem =
{ pkgs, ... }:
{
packages.niri-auto-centre = pkgs.writeShellApplication {
name = "niri-auto-centre";
runtimeInputs = [ pkgs.jq ];
text = ''
while true; do
ACTIVE_WORKSPACE=$(niri msg --json workspaces | jq -r '.[] | select(.is_active == true)')
WORKSPACE_ID=$(echo "$ACTIVE_WORKSPACE" | jq -r '.id')
OUTPUT_NAME=$(echo "$ACTIVE_WORKSPACE" | jq -r '.output')
MONITOR_WIDTH=$(niri msg --json outputs | jq -r ".\"$OUTPUT_NAME\".logical.width")
SUMMED_TILE_WIDTH=$(niri msg --json windows | jq --argjson wid "$WORKSPACE_ID" -r '
[.[] | select(.workspace_id == $wid) | {col: .layout.pos_in_scrolling_layout[0], width: .layout.tile_size[0]}]
| group_by(.col) | map(first.width) | add
')
if awk "BEGIN {exit !($SUMMED_TILE_WIDTH < $MONITOR_WIDTH)}"; then
niri msg action center-visible-columns
fi
sleep 0.1
done
'';
};
};
}

View file

@ -1,23 +0,0 @@
{ inputs, ... }:
let
packageDir = builtins.readDir ./.;
# Filter to .nix files, excluding overlays.nix
isPackageFile = name: name != "overlays.nix" && builtins.match ".*\\.nix$" name != null;
# Extract package name from filename (e.g., "foo-bar.nix" -> "foo-bar")
toPackageName = filename: builtins.head (builtins.match "(.+)\\.nix$" filename);
packageNames = map toPackageName (builtins.filter isPackageFile (builtins.attrNames packageDir));
in
{
flake.overlays.default =
final: prev:
builtins.listToAttrs (
map (name: {
inherit name;
value = inputs.self.packages.${final.system}.${name};
}) packageNames
);
}

View file

@ -1,52 +1,48 @@
{ ... }:
{
perSystem =
{ pkgs, ... }:
{
packages.toggleaudiosink = pkgs.writeShellScriptBin "toggleaudiosink" ''
#!/usr/bin/env bash
pkgs ? import <nixpkgs> { },
}:
sound_server="pipewire"
pkgs.writeShellScriptBin "toggleaudiosink" ''
#!/usr/bin/env bash
# Grab a count of how many audio sinks we have
sink_count=$(${pkgs.pulseaudio}/bin/pactl list sinks | grep -c "Sink #[[:digit:]]")
# Create an array of the actual sink IDs
sinks=()
mapfile -t sinks < <(${pkgs.pulseaudio}/bin/pactl list sinks | grep 'Sink #[[:digit:]]' | sed -n -e 's/.*Sink #\([[:digit:]]\)/\1/p')
# Get the ID of the active sink
active_sink_name=$(${pkgs.pulseaudio}/bin/pactl info | grep 'Default Sink:' | sed -n -e 's/.*Default Sink:[[:space:]]\+\(.*\)/\1/p')
active_sink=$(${pkgs.pulseaudio}/bin/pactl list sinks | grep -B 2 "$active_sink_name" | sed -n -e 's/Sink #\([[:digit:]]\)/\1/p' | head -n 1)
sound_server="pipewire"
# Get the ID of the last sink in the array
final_sink=''${sinks[$((sink_count - 1))]}
# Grab a count of how many audio sinks we have
sink_count=$(${pkgs.pulseaudio}/bin/pactl list sinks | grep -c "Sink #[[:digit:]]")
# Create an array of the actual sink IDs
sinks=()
mapfile -t sinks < <(${pkgs.pulseaudio}/bin/pactl list sinks | grep 'Sink #[[:digit:]]' | sed -n -e 's/.*Sink #\([[:digit:]]\)/\1/p')
# Get the ID of the active sink
active_sink_name=$(${pkgs.pulseaudio}/bin/pactl info | grep 'Default Sink:' | sed -n -e 's/.*Default Sink:[[:space:]]\+\(.*\)/\1/p')
active_sink=$(${pkgs.pulseaudio}/bin/pactl list sinks | grep -B 2 "$active_sink_name" | sed -n -e 's/Sink #\([[:digit:]]\)/\1/p' | head -n 1)
# Find the index of the active sink
for index in "''${!sinks[@]}"; do
if [[ "''${sinks[$index]}" == "$active_sink" ]]; then
active_sink_index=$index
fi
done
# Get the ID of the last sink in the array
final_sink=''${sinks[$((sink_count - 1))]}
# Default to the first sink in the list
next_sink=''${sinks[0]}
next_sink_index=0
# Find the index of the active sink
for index in "''${!sinks[@]}"; do
if [[ "''${sinks[$index]}" == "$active_sink" ]]; then
active_sink_index=$index
fi
done
# If we're not at the end of the list, move up the list
if [[ $active_sink -ne $final_sink ]]; then
next_sink_index=$((active_sink_index + 1))
next_sink=''${sinks[$next_sink_index]}
fi
# Default to the first sink in the list
next_sink=''${sinks[0]}
next_sink_index=0
# Change the default sink
# Get the name of the next sink
next_sink_name=$(${pkgs.pulseaudio}/bin/pactl list sinks | grep -C 2 "Sink #$next_sink" | sed -n -e 's/.*Name:[[:space:]]\+\(.*\)/\1/p' | head -n 1)
${pkgs.pulseaudio}/bin/pactl set-default-sink "$next_sink_name"
# If we're not at the end of the list, move up the list
if [[ $active_sink -ne $final_sink ]]; then
next_sink_index=$((active_sink_index + 1))
next_sink=''${sinks[$next_sink_index]}
fi
# Move all inputs to the new sink
for app in $(${pkgs.pulseaudio}/bin/pactl list sink-inputs | sed -n -e 's/.*Sink Input #\([[:digit:]]\)/\1/p'); do
${pkgs.pulseaudio}/bin/pactl "move-sink-input $app $next_sink"
done
'';
};
}
# Change the default sink
# Get the name of the next sink
next_sink_name=$(${pkgs.pulseaudio}/bin/pactl list sinks | grep -C 2 "Sink #$next_sink" | sed -n -e 's/.*Name:[[:space:]]\+\(.*\)/\1/p' | head -n 1)
${pkgs.pulseaudio}/bin/pactl set-default-sink "$next_sink_name"
# Move all inputs to the new sink
for app in $(${pkgs.pulseaudio}/bin/pactl list sink-inputs | sed -n -e 's/.*Sink Input #\([[:digit:]]\)/\1/p'); do
${pkgs.pulseaudio}/bin/pactl "move-sink-input $app $next_sink"
done
''

View file

@ -1,73 +0,0 @@
# NixOS Flake Configuration
Modular NixOS configuration using flake-parts with the [dendritic](https://github.com/gytis-ivaskevicius/dendritic) pattern.
## Structure
```
.
├── aspects/ # Reusable NixOS/home-manager modules (dendritic)
│ ├── base/ # Base system configuration
│ ├── hosts/ # Host-specific configurations
│ │ ├── _alexandria/
│ │ ├── _io/
│ │ ├── _rotterdam/
│ │ └── _trantor/
│ ├── systems/ # System type modules (desktop, server, cli, gaming)
│ └── users/ # User account configurations
├── data/ # Shared host/service definitions
├── packages/ # Custom packages and overlays
├── shells/ # Shell configurations
└── terranix/ # Terraform configurations for cloud resources
```
## Hosts
| Host | Architecture | Type | Description |
|------|--------------|------|-------------|
| trantor | aarch64-linux | server | ARM server running Forgejo |
| alexandria | x86_64-linux | server | x86 server (Kanidm, Vaultwarden, Nextcloud, Jellyfin) |
| rotterdam | x86_64-linux | desktop | Main workstation setup for gaming |
| io | x86_64-linux | desktop | Workstation |
## Services
- **git.baduhai.dev** (Forgejo) - Publicly accessible on trantor
Other services (LAN/Tailscale only): Vaultwarden, Nextcloud, Jellyfin
## Features
- **Ephemeral root**: Automatic btrfs subvolume rollover with impermanence
- **Secrets**: Managed via agenix with age encryption
- **Disk management**: disko for declarative disk partitioning
- **Modular architecture**: Each aspect is a separate module imported via import-tree
- **Dendritic pattern**: Aspects are imported as a unified flake module
## Building
```bash
# Build specific host
nix build .#nixosConfigurations.trantor.config.system.build.toplevel
# Rebuild host (if using nixos-cli on the host)
sudo nixos apply
```
## Terranix
Terraform configurations for cloud infrastructure managed via terranix:
- baduhai.dev DNS on CloudFlare
- VPS provisioning on OCI
- Tailscale subnet routers
## Key Dependencies
- nixpkgs (nixos-unstable for workstations, nixos for servers)
- home-manager
- agenix
- disko
- impermanence
- nix-flatpak
- nixos-cli

View file

@ -1,15 +0,0 @@
{ inputs, ... }:
{
perSystem =
{ pkgs, system, ... }:
{
devShells.default = pkgs.mkShell {
packages = with pkgs; [
inputs.agenix.packages.${stdenv.hostPlatform.system}.default
nil
nixfmt
];
};
};
}

View file

@ -1,113 +0,0 @@
# Required environment variables:
# CLOUDFLARE_API_TOKEN - API token with "Edit zone DNS" permissions
# AWS_ACCESS_KEY_ID - Cloudflare R2 access key for state storage
# AWS_SECRET_ACCESS_KEY - Cloudflare R2 secret key for state storage
{ ... }:
{
perSystem =
{ pkgs, ... }:
{
terranix.terranixConfigurations.cloudflare-baduhaidev = {
terraformWrapper.package = pkgs.opentofu;
modules = [
(
{ config, lib, ... }:
let
sharedData = import ../data/services.nix;
# Enrich services with host IPs
services = map (
svc:
let
hostInfo = sharedData.hosts.${svc.host} or { };
in
svc
// {
lanIP = hostInfo.lanIP or null;
tailscaleIP = hostInfo.tailscaleIP or null;
}
) sharedData.services;
# Helper to extract subdomain from full domain (e.g., "git.baduhai.dev" -> "git")
getSubdomain = domain: lib.head (lib.splitString "." domain);
# Generate DNS records for services
# Public services point to trantor's public IP
# Private services point to their tailscale IP
mkServiceRecords = lib.listToAttrs (
lib.imap0 (
i: svc:
let
subdomain = getSubdomain svc.domain;
targetIP =
if svc.public or false then
config.data.terraform_remote_state.trantor "outputs.instance_public_ip"
else
svc.tailscaleIP;
in
{
name = "service_${toString i}";
value = {
zone_id = config.variable.zone_id.default;
name = subdomain;
type = "A";
content = targetIP;
proxied = false;
ttl = 3600;
};
}
) services
);
in
{
terraform.required_providers.cloudflare = {
source = "cloudflare/cloudflare";
version = "~> 5.0";
};
terraform.backend.s3 = {
bucket = "terraform-state";
key = "cloudflare/baduhai.dev.tfstate";
region = "auto";
endpoint = "https://fcdf920bde00c3d013ee541f984da70e.r2.cloudflarestorage.com";
skip_credentials_validation = true;
skip_metadata_api_check = true;
skip_region_validation = true;
skip_requesting_account_id = true;
use_path_style = true;
};
variable = {
zone_id = {
default = "c63a8332fdddc4a8e5612ddc54557044";
type = "string";
};
};
data = {
terraform_remote_state.trantor = {
backend = "s3";
config = {
bucket = "terraform-state";
key = "oci/trantor.tfstate";
region = "auto";
endpoint = "https://fcdf920bde00c3d013ee541f984da70e.r2.cloudflarestorage.com";
skip_credentials_validation = true;
skip_metadata_api_check = true;
skip_region_validation = true;
skip_requesting_account_id = true;
use_path_style = true;
};
};
};
resource.cloudflare_dns_record = mkServiceRecords;
}
)
];
};
};
}

View file

@ -1,20 +0,0 @@
# Cloudflare kernelpanic.space configuration placeholder
{ ... }:
{
perSystem =
{ pkgs, ... }:
{
terranix.terranixConfigurations.cloudflare-kernelpanicspace = {
terraformWrapper.package = pkgs.opentofu;
modules = [
(
{ config, ... }:
{
# Terraform config goes here
}
)
];
};
};
}

View file

@ -1,57 +0,0 @@
# Required environment variables:
# TAILSCALE_API_KEY - Tailscale API key with appropriate permissions
# TAILSCALE_TAILNET - Your tailnet name (e.g., "user@example.com" or "example.org.github")
# AWS_ACCESS_KEY_ID - Cloudflare R2 access key for state storage
# AWS_SECRET_ACCESS_KEY - Cloudflare R2 secret key for state storage
{ ... }:
{
perSystem =
{ pkgs, ... }:
{
terranix.terranixConfigurations.tailscale-tailnet = {
terraformWrapper.package = pkgs.opentofu;
modules = [
(
{ config, ... }:
{
terraform.required_providers.tailscale = {
source = "tailscale/tailscale";
version = "~> 0.17";
};
terraform.backend.s3 = {
bucket = "terraform-state";
key = "tailscale/tailnet.tfstate";
region = "auto";
endpoint = "https://fcdf920bde00c3d013ee541f984da70e.r2.cloudflarestorage.com";
skip_credentials_validation = true;
skip_metadata_api_check = true;
skip_region_validation = true;
skip_requesting_account_id = true;
use_path_style = true;
};
variable = {
trantor_tailscale_ip = {
default = "100.108.5.90";
type = "string";
};
};
resource = {
tailscale_dns_nameservers.global = {
nameservers = [
config.variable.trantor_tailscale_ip.default
"1.1.1.1"
"1.0.0.1"
];
};
};
}
)
];
};
};
}

View file

@ -1,20 +0,0 @@
# OCI Terminus configuration placeholder
{ ... }:
{
perSystem =
{ pkgs, ... }:
{
terranix.terranixConfigurations.oci-terminus = {
terraformWrapper.package = pkgs.opentofu;
modules = [
(
{ config, ... }:
{
# Terraform config goes here
}
)
];
};
};
}

View file

@ -1,272 +0,0 @@
# Required environment variables:
# instead of OCI variables, ~/.oci/config may also be used
# OCI_TENANCY_OCID - Oracle tenancy OCID (or use TF_VAR_* to override variables)
# OCI_USER_OCID - Oracle user OCID
# OCI_FINGERPRINT - API key fingerprint
# OCI_PRIVATE_KEY_PATH - Path to OCI API private key
# AWS variables are required
# AWS_ACCESS_KEY_ID - Cloudflare R2 access key for state storage
# AWS_SECRET_ACCESS_KEY - Cloudflare R2 secret key for state storage
{ ... }:
{
perSystem =
{ pkgs, ... }:
{
terranix.terranixConfigurations.oci-trantor = {
terraformWrapper.package = pkgs.opentofu;
modules = [
(
{ config, ... }:
{
terraform.required_providers.oci = {
source = "oracle/oci";
version = "~> 7.0";
};
provider.oci.region = "sa-saopaulo-1";
terraform.backend.s3 = {
bucket = "terraform-state";
key = "oci/trantor.tfstate";
region = "auto";
endpoint = "https://fcdf920bde00c3d013ee541f984da70e.r2.cloudflarestorage.com";
skip_credentials_validation = true;
skip_metadata_api_check = true;
skip_region_validation = true;
skip_requesting_account_id = true;
use_path_style = true;
};
variable = {
tenancy_ocid = {
default = "ocid1.tenancy.oc1..aaaaaaaap3vfdz4piygqza6e6zqunbcuso43ddqfo3ydmpmnomidyghh7rvq";
type = "string";
};
compartment_name = {
default = "trantor";
type = "string";
};
vcn_cidr = {
default = "10.0.0.0/24";
type = "string";
};
instance_name = {
default = "trantor";
type = "string";
};
ssh_public_keys = {
default = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICQPkAyy+Du9Omc2WtnUF2TV8jFAF4H6mJi2D4IZ1nzg user@himalia"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3Y0PVpGfJHonqDS7qoCFhqzUvqGq9I9sax+F9e/5cs user@io"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA1v3+q3EaruiiStWjubEJWvtejam/r41uoOpCdwJtLL user@rotterdam"
];
type = "list(string)";
};
};
data = {
oci_identity_availability_domains.ads = {
compartment_id = config.variable.tenancy_ocid.default;
};
oci_core_images.ubuntu_arm = {
compartment_id = config.variable.tenancy_ocid.default;
operating_system = "Canonical Ubuntu";
operating_system_version = "24.04";
shape = "VM.Standard.A1.Flex";
sort_by = "TIMECREATED";
sort_order = "DESC";
};
};
resource = {
oci_identity_compartment.trantor = {
compartment_id = config.variable.tenancy_ocid.default;
description = "trantor infrastructure compartment";
name = config.variable.compartment_name.default;
};
oci_core_vcn.vcn = {
compartment_id = config.resource.oci_identity_compartment.trantor "id";
cidr_blocks = [ config.variable.vcn_cidr.default ];
display_name = "trantor-vcn";
dns_label = "trantor";
};
oci_core_internet_gateway.ig = {
compartment_id = config.resource.oci_identity_compartment.trantor "id";
vcn_id = config.resource.oci_core_vcn.vcn "id";
display_name = "trantor-ig";
enabled = true;
};
oci_core_route_table.rt = {
compartment_id = config.resource.oci_identity_compartment.trantor "id";
vcn_id = config.resource.oci_core_vcn.vcn "id";
display_name = "trantor-rt";
route_rules = [
{
network_entity_id = config.resource.oci_core_internet_gateway.ig "id";
destination = "0.0.0.0/0";
destination_type = "CIDR_BLOCK";
}
];
};
oci_core_security_list.sl = {
compartment_id = config.resource.oci_identity_compartment.trantor "id";
vcn_id = config.resource.oci_core_vcn.vcn "id";
display_name = "trantor-sl";
egress_security_rules = [
{
destination = "0.0.0.0/0";
protocol = "all";
stateless = false;
}
];
ingress_security_rules = [
{
protocol = "6"; # TCP
source = "0.0.0.0/0";
stateless = false;
tcp_options = {
min = 22;
max = 22;
};
}
{
protocol = "6"; # TCP
source = "0.0.0.0/0";
stateless = false;
tcp_options = {
min = 80;
max = 80;
};
}
{
protocol = "6"; # TCP
source = "0.0.0.0/0";
stateless = false;
tcp_options = {
min = 443;
max = 443;
};
}
{
protocol = "6"; # TCP
source = "0.0.0.0/0";
stateless = false;
tcp_options = {
min = 25565;
max = 25565;
};
}
{
protocol = "6"; # TCP
source = "0.0.0.0/0";
stateless = false;
tcp_options = {
min = 19132;
max = 19133;
};
}
{
protocol = "17"; # UDP
source = "0.0.0.0/0";
stateless = false;
udp_options = {
min = 19132;
max = 19133;
};
}
];
};
oci_core_subnet.subnet = {
compartment_id = config.resource.oci_identity_compartment.trantor "id";
vcn_id = config.resource.oci_core_vcn.vcn "id";
cidr_block = config.variable.vcn_cidr.default;
display_name = "trantor-subnet";
dns_label = "subnet";
route_table_id = config.resource.oci_core_route_table.rt "id";
security_list_ids = [ (config.resource.oci_core_security_list.sl "id") ];
prohibit_public_ip_on_vnic = false;
};
oci_core_instance.trantor = {
availability_domain = config.data.oci_identity_availability_domains.ads "availability_domains[0].name";
compartment_id = config.resource.oci_identity_compartment.trantor "id";
display_name = config.variable.instance_name.default;
shape = "VM.Standard.A1.Flex";
shape_config = {
ocpus = 2;
memory_in_gbs = 12;
};
source_details = {
source_type = "image";
source_id = config.data.oci_core_images.ubuntu_arm "images[0].id";
boot_volume_size_in_gbs = 100;
};
create_vnic_details = {
subnet_id = config.resource.oci_core_subnet.subnet "id";
display_name = "trantor-vnic";
assign_public_ip = true;
hostname_label = config.variable.instance_name.default;
};
metadata = {
ssh_authorized_keys = builtins.concatStringsSep "\n" config.variable.ssh_public_keys.default;
};
preserve_boot_volume = false;
};
oci_budget_budget.trantor_budget = {
compartment_id = config.variable.tenancy_ocid.default;
targets = [ (config.resource.oci_identity_compartment.trantor "id") ];
amount = 1;
reset_period = "MONTHLY";
display_name = "trantor-budget";
description = "Monthly budget for trantor compartment";
target_type = "COMPARTMENT";
};
oci_budget_alert_rule.daily_spend_alert = {
budget_id = config.resource.oci_budget_budget.trantor_budget "id";
type = "ACTUAL";
threshold = 5;
threshold_type = "PERCENTAGE";
display_name = "daily-spend-alert";
recipients = "baduhai@proton.me";
description = "Alert when daily spending exceeds $0.05";
message = "Daily spending has exceeded $0.05 in the trantor compartment";
};
};
output = {
compartment_id = {
value = config.resource.oci_identity_compartment.trantor "id";
};
instance_public_ip = {
value = config.resource.oci_core_instance.trantor "public_ip";
};
};
}
)
];
};
};
}