feat: migrate from modules to features

This commit is contained in:
2026-03-26 23:10:56 +01:00
parent 76e74f4939
commit 8c6fefb95b
52 changed files with 657 additions and 871 deletions

22
features/calibre.nix Normal file
View File

@@ -0,0 +1,22 @@
{
nixos =
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.calibre ];
# udev rules for kindle and mtp device access
# NOTE:(@janezicmatej) uses services.udev.packages instead of extraRules
# because extraRules writes to 99-local.rules which is too late for uaccess
# see https://github.com/NixOS/nixpkgs/issues/308681
services.udev.packages = [
pkgs.libmtp
(pkgs.writeTextFile {
name = "kindle-udev-rules";
text = ''
ACTION!="remove", SUBSYSTEM=="usb", ATTRS{idVendor}=="1949", TAG+="uaccess"
'';
destination = "/etc/udev/rules.d/70-kindle.rules";
})
];
};
}

10
features/claude.nix Normal file
View File

@@ -0,0 +1,10 @@
{
home =
{ pkgs, ... }:
{
home.packages = [
pkgs.claude-code
pkgs.mcp-nixos
];
};
}

85
features/desktop.nix Normal file
View File

@@ -0,0 +1,85 @@
{
nixos =
{ pkgs, inputs, ... }:
{
imports = [ inputs.stylix.nixosModules.stylix ];
# audio
services.pipewire = {
enable = true;
pulse.enable = true;
};
# bluetooth
hardware.bluetooth.enable = true;
services.blueman.enable = true;
security.polkit.enable = true;
services.dbus.enable = true;
services.playerctld.enable = true;
xdg.portal = {
enable = true;
xdgOpenUsePortal = true;
extraPortals = [
pkgs.xdg-desktop-portal-wlr
pkgs.xdg-desktop-portal-gtk
];
};
fonts.packages = with pkgs; [
font-awesome
nerd-fonts.jetbrains-mono
];
# theming
stylix = {
enable = true;
polarity = "dark";
image = "${inputs.assets}/wallpaper.png";
base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-material-dark-medium.yaml";
};
programs.thunderbird.enable = true;
programs._1password.enable = true;
programs._1password-gui.enable = true;
environment.systemPackages = with pkgs; [
easyeffects
ghostty
google-chrome
zathura
pavucontrol
bolt-launcher
libnotify
bibata-cursors
vesktop
rocketchat-desktop
telegram-desktop
slack
jellyfin-media-player
cider-2
mpv
ffmpeg
wf-recorder
wl-mirror
protonmail-bridge
ledger-live-desktop
];
# internal CA
security.pki.certificateFiles = [
inputs.self.outputs.packages.${pkgs.stdenv.hostPlatform.system}.ca-matheo-si
];
xdg.mime.defaultApplications = {
"application/pdf" = "org.pwmt.zathura.desktop";
};
};
home =
{ inputs, ... }:
{
home.file.".assets".source = inputs.assets;
};
}

30
features/dev.nix Normal file
View File

@@ -0,0 +1,30 @@
{
home =
{ pkgs, inputs, ... }:
let
packages = inputs.self.outputs.packages.${pkgs.stdenv.hostPlatform.system};
in
{
home.packages = [
pkgs.git
packages.git-linearize
packages.ggman
pkgs.go
pkgs.python3
pkgs.mdbook
pkgs.marksman
pkgs.mdformat
pkgs.google-cloud-sdk
pkgs.google-cloud-sql-proxy
packages.ahab
pkgs.just
pkgs.presenterm
pkgs.osc
];
programs.direnv = {
enable = true;
nix-direnv.enable = true;
};
};
}

12
features/docker.nix Normal file
View File

@@ -0,0 +1,12 @@
{
nixos =
{ user, ... }:
{
virtualisation.docker = {
enable = true;
logDriver = "json-file";
};
users.users.${user}.extraGroups = [ "docker" ];
};
}

9
features/gnupg.nix Normal file
View File

@@ -0,0 +1,9 @@
{
nixos = _: {
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
enableExtraSocket = true;
};
};
}

28
features/greeter.nix Normal file
View File

@@ -0,0 +1,28 @@
{
nixos =
{ lib, inputs, ... }:
{
programs.regreet = {
enable = true;
# single output to avoid stretching across monitors
cageArgs = [
"-s"
"-m"
"last"
];
font = {
name = lib.mkForce "JetBrainsMono Nerd Font";
size = lib.mkForce 14;
};
settings = {
background = {
path = lib.mkForce "${inputs.assets}/wallpaper.png";
fit = lib.mkForce "Cover";
};
GTK = {
application_prefer_dark_theme = lib.mkForce true;
};
};
};
};
}

75
features/initrd-ssh.nix Normal file
View File

@@ -0,0 +1,75 @@
{
nixos =
{ lib, config, ... }:
let
keyDir = "/etc/secrets/initrd";
mkIpString =
{
address,
gateway,
netmask,
interface,
...
}:
"${address}::${gateway}:${netmask}::${interface}:none";
in
{
options = {
initrd-ssh = {
ip = {
enable = lib.mkEnableOption "static IP for initrd (otherwise DHCP)";
address = lib.mkOption {
type = lib.types.str;
};
gateway = lib.mkOption {
type = lib.types.str;
};
netmask = lib.mkOption {
type = lib.types.str;
default = "255.255.255.0";
};
interface = lib.mkOption {
type = lib.types.str;
};
};
authorizedKeys = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
networkModule = lib.mkOption {
type = lib.types.str;
};
};
};
config = {
boot.initrd.kernelModules = [ config.initrd-ssh.networkModule ];
boot.kernelParams = lib.mkIf config.initrd-ssh.ip.enable [
"ip=${mkIpString config.initrd-ssh.ip}"
];
boot.initrd.network = {
enable = true;
ssh = {
enable = true;
port = 22;
hostKeys = [
"${keyDir}/ssh_host_rsa_key"
"${keyDir}/ssh_host_ed25519_key"
];
inherit (config.initrd-ssh) authorizedKeys;
};
postCommands = ''
echo 'cryptsetup-askpass' >> /root/.profile
'';
};
};
};
}

25
features/localisation.nix Normal file
View File

@@ -0,0 +1,25 @@
{
nixos =
{ lib, config, ... }:
{
options = {
localisation = {
timeZone = lib.mkOption {
type = lib.types.str;
};
defaultLocale = lib.mkOption {
type = lib.types.str;
};
};
};
config = {
time.timeZone = config.localisation.timeZone;
i18n.defaultLocale = config.localisation.defaultLocale;
# NOTE:(@janezicmatej) some apps (e.g. java) need TZ env var explicitly
environment.variables.TZ = config.localisation.timeZone;
};
};
}

66
features/neovim.nix Normal file
View File

@@ -0,0 +1,66 @@
{
home =
{
config,
options,
lib,
pkgs,
inputs,
...
}:
{
options = {
neovim.dotfiles = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
};
};
config = {
# only disable when stylix is present (loaded by desktop feature)
stylix.targets.neovim.enable = lib.mkIf (options ? stylix) false;
xdg.configFile."nvim" = lib.mkIf (config.neovim.dotfiles != null) {
source = config.neovim.dotfiles;
};
programs.neovim = {
enable = true;
vimAlias = true;
defaultEditor = true;
package = inputs.neovim-nightly-overlay.packages.${pkgs.stdenv.hostPlatform.system}.default;
extraPackages = with pkgs; [
gcc
luajit
nodejs_22
tree-sitter
gnumake
osc
fd
ripgrep
bat
delta
pyright
typescript-language-server
lua-language-server
gopls
nil
nixd
nixpkgs-fmt
stylua
];
extraWrapperArgs = [
"--suffix"
"LD_LIBRARY_PATH"
":"
"${lib.makeLibraryPath [ pkgs.stdenv.cc.cc.lib ]}"
];
};
};
};
}

View File

@@ -0,0 +1,9 @@
{
nixos = _: {
networking.networkmanager.enable = true;
networking.nameservers = [
"1.1.1.1"
"8.8.8.8"
];
};
}

5
features/nix-ld.nix Normal file
View File

@@ -0,0 +1,5 @@
{
nixos = _: {
programs.nix-ld.enable = true;
};
}

25
features/openssh.nix Normal file
View File

@@ -0,0 +1,25 @@
{
nixos =
{ lib, config, ... }:
{
options = {
openssh.port = lib.mkOption {
type = lib.types.port;
default = 22;
};
};
config = {
services.openssh = {
enable = true;
ports = [ config.openssh.port ];
settings = {
PasswordAuthentication = false;
AllowUsers = null;
PermitRootLogin = "no";
StreamLocalBindUnlink = "yes";
};
};
};
};
}

10
features/printing.nix Normal file
View File

@@ -0,0 +1,10 @@
{
nixos = _: {
services.printing.enable = true;
services.avahi = {
enable = true;
nssmdns4 = true;
openFirewall = true;
};
};
}

25
features/shell.nix Normal file
View File

@@ -0,0 +1,25 @@
{
nixos = _: {
programs.zsh.enable = true;
environment.etc."zshenv".text = ''
export ZDOTDIR=$HOME/.config/zsh
'';
};
home =
{ pkgs, ... }:
{
home.packages = with pkgs; [
starship
fzf
htop
jc
jq
openssl
pv
ripgrep
fd
tmux
];
};
}

10
features/steam.nix Normal file
View File

@@ -0,0 +1,10 @@
{
nixos = _: {
programs.steam = {
enable = true;
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = true;
localNetworkGameTransfers.openFirewall = true;
};
};
}

38
features/sway.nix Normal file
View File

@@ -0,0 +1,38 @@
{
nixos =
{ pkgs, ... }:
{
programs.sway = {
enable = true;
package = pkgs.swayfx;
wrapperFeatures.gtk = true;
extraSessionCommands = ''
# fix for java awt apps not rendering
export _JAVA_AWT_WM_NONREPARENTING=1
'';
};
environment.systemPackages = with pkgs; [
waybar
mako
wob
playerctl
brightnessctl
foot
grim
pulseaudio
swayidle
swaylock-effects
jq
slurp
wl-clipboard
pamixer
wlsunset
satty
wayland-pipewire-idle-inhibit
fuzzel
cliphist
zenity
];
};
}

8
features/tailscale.nix Normal file
View File

@@ -0,0 +1,8 @@
{
nixos = _: {
services.tailscale = {
enable = true;
useRoutingFeatures = "both";
};
};
}

33
features/user-matej.nix Normal file
View File

@@ -0,0 +1,33 @@
let
sshKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICQGLdINKzs+sEy62Pefng0bcedgU396+OryFgeH99/c janezicmatej"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDk00+Km03epQXQs+xEwwH3zcurACzkEH+kDOPBw6RQe openpgp:0xB095D449"
];
in
{
keys = {
sshAuthorizedKeys = sshKeys;
};
nixos =
{ pkgs, ... }:
{
users.users.matej = {
uid = 1000;
isNormalUser = true;
home = "/home/matej";
shell = pkgs.zsh;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = sshKeys;
};
users.groups.matej = {
gid = 1000;
members = [ "matej" ];
};
};
home = _: {
home.stateVersion = "24.11";
};
}

View File

@@ -0,0 +1,72 @@
{
nixos =
{
pkgs,
lib,
config,
...
}:
let
inherit (config.vm-9p-automount) user;
inherit (config.users.users.${user}) home group;
in
{
options = {
vm-9p-automount = {
user = lib.mkOption {
type = lib.types.str;
};
prefix = lib.mkOption {
type = lib.types.str;
default = "m_";
};
basePath = lib.mkOption {
type = lib.types.str;
default = "${home}/mnt";
};
};
};
config = {
systemd.services.vm-9p-automount = {
description = "Auto-discover and mount 9p shares";
after = [
"local-fs.target"
"nss-user-lookup.target"
"systemd-modules-load.service"
];
wants = [ "systemd-modules-load.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = pkgs.writeShellScript "vm-9p-automount" ''
BASE="${config.vm-9p-automount.basePath}"
PREFIX="${config.vm-9p-automount.prefix}"
mkdir -p "$BASE"
chown ${user}:${group} "$BASE"
for tagfile in $(find /sys/devices -name mount_tag 2>/dev/null); do
[ -f "$tagfile" ] || continue
tag=$(tr -d '\0' < "$tagfile")
case "$tag" in
"$PREFIX"*) ;;
*) continue ;;
esac
name="''${tag#"$PREFIX"}"
target="$BASE/$name"
mkdir -p "$target"
${pkgs.util-linux}/bin/mount -t 9p "$tag" "$target" \
-o trans=virtio,version=9p2000.L || continue
done
'';
};
};
};
};
}

47
features/vm-guest.nix Normal file
View File

@@ -0,0 +1,47 @@
{
nixos =
{
pkgs,
lib,
config,
...
}:
{
options = {
vm-guest.headless = lib.mkOption {
type = lib.types.bool;
default = false;
};
};
config = {
services.qemuGuest.enable = true;
services.spice-vdagentd.enable = lib.mkIf (!config.vm-guest.headless) true;
boot.kernelParams = lib.mkIf config.vm-guest.headless [ "console=ttyS0,115200" ];
boot.initrd.availableKernelModules = [
"9p"
"9pnet_virtio"
];
boot.kernelModules = [
"9p"
"9pnet_virtio"
];
networking = {
useDHCP = true;
firewall.allowedTCPPorts = [ 22 ];
};
security.sudo.wheelNeedsPassword = false;
environment.systemPackages = with pkgs; [
curl
wget
htop
sshfs
];
};
};
}

12
features/yubikey.nix Normal file
View File

@@ -0,0 +1,12 @@
{
nixos =
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
yubikey-personalization
yubikey-manager
];
services.pcscd.enable = true;
};
}