Compare commits
106 Commits
552196c3f9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
6772afb845
|
|||
|
e9755d41c6
|
|||
|
68411d9459
|
|||
|
7fd5b790ff
|
|||
|
37bca1fdd1
|
|||
|
75ca09949c
|
|||
|
2fcdee5d81
|
|||
|
c01f797e79
|
|||
|
59a2bfa126
|
|||
|
e486bb28b0
|
|||
|
d33fd60ce4
|
|||
|
37428d922b
|
|||
|
b1cfe1e31b
|
|||
|
df2bc27f54
|
|||
|
77236af589
|
|||
|
f71d156ea8
|
|||
|
0c517e0957
|
|||
|
37620c76fe
|
|||
|
ac76b8c842
|
|||
|
df7c4cec83
|
|||
|
5b52e41496
|
|||
|
a60b40eeac
|
|||
|
b341f7f4fc
|
|||
|
571fb2ff99
|
|||
|
2204b12fad
|
|||
|
df2ee459a1
|
|||
|
f7d86e7718
|
|||
|
2e5eb92e32
|
|||
|
f30b03cc04
|
|||
|
c7fb218511
|
|||
|
3caace87d3
|
|||
|
8793f97a04
|
|||
|
b8509196d5
|
|||
|
e1d136bd2f
|
|||
|
898751576d
|
|||
|
6770bc76a2
|
|||
|
3ff4583017
|
|||
|
f85980190e
|
|||
|
8e5557921d
|
|||
|
216328927d
|
|||
|
86e8fe7397
|
|||
|
0fa91d4f40
|
|||
|
07334db7ee
|
|||
|
a08f824d0e
|
|||
|
dd4fc4eff3
|
|||
|
89e36c5096
|
|||
|
c29f4d0624
|
|||
|
cffd90db69
|
|||
|
7faddd053b
|
|||
|
71cd268f79
|
|||
|
5a37795151
|
|||
|
36106c37fd
|
|||
|
3b80f90b99
|
|||
|
35d0db6bf0
|
|||
|
cba2f63f01
|
|||
|
4f901d4367
|
|||
|
7d18c2713f
|
|||
|
18105107a6
|
|||
|
36630d98a3
|
|||
|
27b7b2abf2
|
|||
|
29053f4ec2
|
|||
|
b50c574342
|
|||
|
666f7f35a6
|
|||
|
50533cc737
|
|||
|
42c2a1604c
|
|||
|
e696417e63
|
|||
|
94198293ff
|
|||
|
16eb3dcf00
|
|||
|
21a757232d
|
|||
|
99fea4e9db
|
|||
|
dc2e7bf1aa
|
|||
|
baeb10a48e
|
|||
|
315de3696a
|
|||
|
38cdcebddd
|
|||
|
c40fbaec57
|
|||
|
4b43196c0e
|
|||
|
404b6431ce
|
|||
|
8c6fefb95b
|
|||
|
76e74f4939
|
|||
|
6208614f30
|
|||
|
ded1963dd7
|
|||
|
90312f4c8b
|
|||
|
fae966b17e
|
|||
|
59270fdcd5
|
|||
|
d8ab6207d5
|
|||
|
7fcd8b2ec8
|
|||
|
9f7728a95c
|
|||
|
ad2c79e113
|
|||
|
b19305f198
|
|||
|
1975659715
|
|||
|
b2ad5a8be5
|
|||
|
c964d42635
|
|||
|
e49a91b7c8
|
|||
|
3011898b28
|
|||
|
760a0d367e
|
|||
|
db9e82119d
|
|||
|
a6cc138507
|
|||
|
1543878dda
|
|||
|
9575e785fa
|
|||
|
38ba80c08b
|
|||
|
d0413239cd
|
|||
|
36684b93ef
|
|||
|
c5afcb10f7
|
|||
|
53ddba4457
|
|||
|
aaee9558a7
|
|||
|
842479d4e7
|
@@ -1,6 +1,8 @@
|
||||
# nix fmt & statix
|
||||
f011c8d71ba09bd94ab04b8d771858b90a03fbf9
|
||||
3aff25b4486a143cd6282f8845c16216598e1c7e
|
||||
2204b12fadf27886058e6945806ce93a547f5278
|
||||
77236af5896524218605badcd3cdfc2267b213da
|
||||
|
||||
# host rename
|
||||
cfe4c43887a41e52be4e6472474c0fc3788f86e8
|
||||
|
||||
@@ -12,3 +12,13 @@ repos:
|
||||
language: system
|
||||
files: \.nix$
|
||||
pass_filenames: false
|
||||
- repo: https://github.com/koalaman/shellcheck-precommit
|
||||
rev: v0.11.0
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
args: [-x, -P, scripts]
|
||||
- repo: https://github.com/scop/pre-commit-shfmt
|
||||
rev: v3.12.0-2
|
||||
hooks:
|
||||
- id: shfmt
|
||||
args: [-d]
|
||||
|
||||
36
.sops.yaml
Normal file
36
.sops.yaml
Normal file
@@ -0,0 +1,36 @@
|
||||
keys:
|
||||
- &matej AF349EECC849D87B790E88FF6318FFB7DB374B7D
|
||||
|
||||
# host age keys (via: ssh-keyscan <host> | ssh-to-age)
|
||||
- &tower age1frwe9fpt9vh969aqnggvq8pfypp6hl98guwfmgttucp7gr55r42sqy2t65
|
||||
- &fw16 age19qj2aaryx869cvcqp77gs9x5hcv4dqjxunkmyre78upsxda6ss7s5vquz4
|
||||
- &floo age1hksdq2lc89thnpth49sw44f0pmkp950plrhhnttj4petvnfy04tsydz6fl
|
||||
- &cube age15cktenavt5v7zm84se36jtly740syca5nw8em8edx404n5x2ddws8jn29g
|
||||
|
||||
creation_rules:
|
||||
# per-host secrets
|
||||
- path_regex: ^secrets/tower\.yaml$
|
||||
key_groups:
|
||||
- pgp: [*matej]
|
||||
age: [*tower]
|
||||
|
||||
- path_regex: ^secrets/fw16\.yaml$
|
||||
key_groups:
|
||||
- pgp: [*matej]
|
||||
age: [*fw16]
|
||||
|
||||
- path_regex: ^secrets/floo\.yaml$
|
||||
key_groups:
|
||||
- pgp: [*matej]
|
||||
age: [*floo]
|
||||
|
||||
- path_regex: ^secrets/cube\.yaml$
|
||||
key_groups:
|
||||
- pgp: [*matej]
|
||||
age: [*cube]
|
||||
|
||||
# shared secrets (all hosts)
|
||||
- path_regex: ^secrets/common\.yaml$
|
||||
key_groups:
|
||||
- pgp: [*matej]
|
||||
age: [*tower, *fw16, *floo, *cube]
|
||||
73
features/bootloader.nix
Normal file
73
features/bootloader.nix
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.bootloader;
|
||||
in
|
||||
{
|
||||
imports = [ inputs.lanzaboote.nixosModules.lanzaboote ];
|
||||
|
||||
options.features.bootloader = {
|
||||
enable = lib.mkEnableOption "bootloader";
|
||||
|
||||
mode = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"systemd-boot"
|
||||
"lanzaboote"
|
||||
];
|
||||
default = "systemd-boot";
|
||||
};
|
||||
|
||||
plymouth.enable = lib.mkEnableOption "plymouth boot splash";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
{
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
# request the largest framebuffer uefi offers; plymouth inherits it
|
||||
boot.loader.systemd-boot.consoleMode = "max";
|
||||
}
|
||||
|
||||
(lib.mkIf (cfg.mode == "systemd-boot") {
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
})
|
||||
|
||||
(lib.mkIf (cfg.mode == "lanzaboote") {
|
||||
boot.loader.systemd-boot.enable = lib.mkForce false;
|
||||
boot.lanzaboote = {
|
||||
enable = true;
|
||||
pkiBundle = "/var/lib/sbctl";
|
||||
};
|
||||
})
|
||||
|
||||
(lib.mkIf cfg.plymouth.enable {
|
||||
# plymouth needs systemd-initrd to render the luks prompt cleanly
|
||||
boot.initrd.systemd.enable = true;
|
||||
|
||||
# host is responsible for early-KMS so plymouth lands on the gpu driver,
|
||||
# not simpledrm (e.g. hardware.amdgpu.initrd.enable on amd hosts)
|
||||
boot.plymouth.enable = true;
|
||||
stylix.targets.plymouth.logoAnimated = false;
|
||||
|
||||
boot.kernelParams = [
|
||||
"quiet"
|
||||
"splash"
|
||||
"loglevel=3"
|
||||
"rd.systemd.show_status=false"
|
||||
"rd.udev.log_level=3"
|
||||
"udev.log_priority=3"
|
||||
"plymouth.force-scale=1"
|
||||
];
|
||||
boot.consoleLogLevel = 0;
|
||||
boot.initrd.verbose = false;
|
||||
})
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
28
features/claude.nix
Normal file
28
features/claude.nix
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
nixos =
|
||||
{ lib, ... }:
|
||||
{
|
||||
options.features.claude.enable = lib.mkEnableOption "claude";
|
||||
};
|
||||
|
||||
home =
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
osConfig,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = osConfig.features.claude;
|
||||
packages = inputs.self.outputs.packages.${pkgs.stdenv.hostPlatform.system};
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
home.packages = [
|
||||
packages.claude-code
|
||||
pkgs.mcp-nixos
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
273
features/desktop.nix
Normal file
273
features/desktop.nix
Normal file
@@ -0,0 +1,273 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.desktop;
|
||||
in
|
||||
{
|
||||
options.features.desktop = {
|
||||
enable = lib.mkEnableOption "desktop environment";
|
||||
|
||||
audio.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
bluetooth.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
apps.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
theme = {
|
||||
wallpaper = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "${inputs.assets}/wallpaper.png";
|
||||
};
|
||||
|
||||
scheme = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "gruvbox-material-dark-medium";
|
||||
};
|
||||
|
||||
polarity = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"dark"
|
||||
"light"
|
||||
];
|
||||
default = "dark";
|
||||
};
|
||||
};
|
||||
|
||||
internalCA.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
# base desktop
|
||||
{
|
||||
security.polkit.enable = true;
|
||||
services.dbus.enable = true;
|
||||
services.playerctld.enable = true;
|
||||
|
||||
xdg.portal = {
|
||||
enable = true;
|
||||
extraPortals = with pkgs; [
|
||||
xdg-desktop-portal-wlr
|
||||
xdg-desktop-portal-gtk
|
||||
];
|
||||
};
|
||||
|
||||
# honor persist_mode so electron apps don't re-prompt for screencast every login
|
||||
systemd.user.services.xdg-desktop-portal-wlr.environment.XDPW_PERSIST_MODE = "permanent";
|
||||
|
||||
# enable ozone/wayland for electron apps so idle detection works
|
||||
environment.sessionVariables.NIXOS_OZONE_WL = "1";
|
||||
|
||||
fonts.packages = with pkgs; [
|
||||
font-awesome
|
||||
nerd-fonts.jetbrains-mono
|
||||
];
|
||||
|
||||
stylix = {
|
||||
enable = true;
|
||||
inherit (cfg.theme) polarity;
|
||||
image = cfg.theme.wallpaper;
|
||||
base16Scheme = "${pkgs.base16-schemes}/share/themes/${cfg.theme.scheme}.yaml";
|
||||
};
|
||||
}
|
||||
|
||||
# audio
|
||||
(lib.mkIf cfg.audio.enable {
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
pavucontrol
|
||||
easyeffects
|
||||
];
|
||||
})
|
||||
|
||||
# bluetooth
|
||||
(lib.mkIf cfg.bluetooth.enable {
|
||||
hardware.bluetooth.enable = true;
|
||||
services.blueman.enable = true;
|
||||
})
|
||||
|
||||
# apps
|
||||
(lib.mkIf cfg.apps.enable {
|
||||
programs.thunderbird.enable = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
ghostty
|
||||
google-chrome
|
||||
zathura
|
||||
calibre
|
||||
bolt-launcher
|
||||
libnotify
|
||||
bibata-cursors
|
||||
discord
|
||||
rocketchat-desktop
|
||||
telegram-desktop
|
||||
slack
|
||||
jellyfin-media-player
|
||||
cider-2
|
||||
mpv
|
||||
ffmpeg
|
||||
wf-recorder
|
||||
wl-mirror
|
||||
protonmail-bridge
|
||||
ledger-live-desktop
|
||||
imv
|
||||
yazi
|
||||
nemo
|
||||
file-roller
|
||||
libreoffice-still
|
||||
];
|
||||
|
||||
# kindle udev rules for calibre
|
||||
features.udev.kindle.enable = lib.mkDefault true;
|
||||
})
|
||||
|
||||
# internal CA
|
||||
(lib.mkIf cfg.internalCA.enable {
|
||||
security.pki.certificateFiles = [
|
||||
inputs.self.outputs.packages.${pkgs.stdenv.hostPlatform.system}.ca-matheo-si
|
||||
];
|
||||
})
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
home =
|
||||
{
|
||||
lib,
|
||||
inputs,
|
||||
osConfig,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = osConfig.features.desktop;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
{
|
||||
home.file.".assets".source = inputs.assets;
|
||||
}
|
||||
|
||||
(lib.mkIf cfg.apps.enable {
|
||||
# TODO:(@janezicmatej) consider moving nvim desktop entry to neovim feature
|
||||
xdg.desktopEntries.nvim = {
|
||||
name = "Neovim";
|
||||
exec = "ghostty -e nvim %F";
|
||||
terminal = false;
|
||||
mimeType = [
|
||||
"text/plain"
|
||||
"application/json"
|
||||
"text/markdown"
|
||||
];
|
||||
};
|
||||
|
||||
xdg.mimeApps = {
|
||||
enable = true;
|
||||
defaultApplications = {
|
||||
# text
|
||||
"text/plain" = "nvim.desktop";
|
||||
"application/json" = "nvim.desktop";
|
||||
"text/markdown" = "nvim.desktop";
|
||||
|
||||
# web
|
||||
"text/html" = "google-chrome.desktop";
|
||||
"application/xhtml+xml" = "google-chrome.desktop";
|
||||
"x-scheme-handler/http" = "google-chrome.desktop";
|
||||
"x-scheme-handler/https" = "google-chrome.desktop";
|
||||
"x-scheme-handler/ftp" = "google-chrome.desktop";
|
||||
"x-scheme-handler/about" = "google-chrome.desktop";
|
||||
"x-scheme-handler/unknown" = "google-chrome.desktop";
|
||||
|
||||
# mail and calendar
|
||||
"x-scheme-handler/mailto" = "thunderbird.desktop";
|
||||
"message/rfc822" = "thunderbird.desktop";
|
||||
"text/calendar" = "thunderbird.desktop";
|
||||
|
||||
# documents
|
||||
"application/pdf" = "org.pwmt.zathura.desktop";
|
||||
"application/postscript" = "org.pwmt.zathura.desktop";
|
||||
"image/vnd.djvu" = "org.pwmt.zathura.desktop";
|
||||
"application/epub+zip" = "org.pwmt.zathura.desktop";
|
||||
|
||||
# office
|
||||
"application/msword" = "libreoffice-writer.desktop";
|
||||
"application/vnd.ms-excel" = "libreoffice-calc.desktop";
|
||||
"application/vnd.ms-powerpoint" = "libreoffice-impress.desktop";
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document" =
|
||||
"libreoffice-writer.desktop";
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" = "libreoffice-calc.desktop";
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation" =
|
||||
"libreoffice-impress.desktop";
|
||||
"application/vnd.oasis.opendocument.text" = "libreoffice-writer.desktop";
|
||||
"application/vnd.oasis.opendocument.spreadsheet" = "libreoffice-calc.desktop";
|
||||
"application/vnd.oasis.opendocument.presentation" = "libreoffice-impress.desktop";
|
||||
"text/csv" = "libreoffice-calc.desktop";
|
||||
|
||||
# images
|
||||
"image/png" = "imv-dir.desktop";
|
||||
"image/jpeg" = "imv-dir.desktop";
|
||||
"image/gif" = "imv-dir.desktop";
|
||||
"image/webp" = "imv-dir.desktop";
|
||||
"image/tiff" = "imv-dir.desktop";
|
||||
"image/bmp" = "imv-dir.desktop";
|
||||
"image/svg+xml" = "google-chrome.desktop";
|
||||
|
||||
# video
|
||||
"video/mp4" = "mpv.desktop";
|
||||
"video/x-matroska" = "mpv.desktop";
|
||||
"video/webm" = "mpv.desktop";
|
||||
"video/quicktime" = "mpv.desktop";
|
||||
"video/x-msvideo" = "mpv.desktop";
|
||||
|
||||
# audio
|
||||
"audio/mpeg" = "mpv.desktop";
|
||||
"audio/flac" = "mpv.desktop";
|
||||
"audio/ogg" = "mpv.desktop";
|
||||
"audio/wav" = "mpv.desktop";
|
||||
"audio/aac" = "mpv.desktop";
|
||||
|
||||
# archives
|
||||
"application/zip" = "org.gnome.FileRoller.desktop";
|
||||
"application/x-tar" = "org.gnome.FileRoller.desktop";
|
||||
"application/gzip" = "org.gnome.FileRoller.desktop";
|
||||
"application/x-rar-compressed" = "org.gnome.FileRoller.desktop";
|
||||
"application/x-7z-compressed" = "org.gnome.FileRoller.desktop";
|
||||
"application/x-bzip2" = "org.gnome.FileRoller.desktop";
|
||||
"application/x-xz" = "org.gnome.FileRoller.desktop";
|
||||
|
||||
# file manager
|
||||
"inode/directory" = "nemo.desktop";
|
||||
|
||||
# app deep links
|
||||
"x-scheme-handler/tg" = "org.telegram.desktop.desktop";
|
||||
"x-scheme-handler/discord" = "discord.desktop";
|
||||
"x-scheme-handler/slack" = "slack.desktop";
|
||||
};
|
||||
};
|
||||
})
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
36
features/dev.nix
Normal file
36
features/dev.nix
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
nixos =
|
||||
{ lib, ... }:
|
||||
{
|
||||
options.features.dev.enable = lib.mkEnableOption "development tools";
|
||||
};
|
||||
|
||||
home =
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
osConfig,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = osConfig.features.dev;
|
||||
packages = inputs.self.outputs.packages.${pkgs.stdenv.hostPlatform.system};
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
home.packages = [
|
||||
pkgs.python3
|
||||
pkgs.osc
|
||||
|
||||
pkgs.google-cloud-sdk
|
||||
pkgs.google-cloud-sql-proxy
|
||||
|
||||
packages.ahab
|
||||
pkgs.just
|
||||
pkgs.presenterm
|
||||
pkgs.qemu
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
45
features/direnv/default.nix
Normal file
45
features/direnv/default.nix
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.direnv;
|
||||
in
|
||||
{
|
||||
options.features.direnv.enable = lib.mkEnableOption "direnv";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
nix.registry.dev = {
|
||||
from = {
|
||||
type = "indirect";
|
||||
id = "dev";
|
||||
};
|
||||
to = {
|
||||
type = "path";
|
||||
path = inputs.self.outPath;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
home =
|
||||
{ lib, osConfig, ... }:
|
||||
let
|
||||
cfg = osConfig.features.direnv;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
programs.direnv = {
|
||||
enable = true;
|
||||
nix-direnv.enable = true;
|
||||
config.global.hide_env_diff = true;
|
||||
};
|
||||
|
||||
xdg.configFile."direnv/lib/use_dev.sh".source = ./use_dev.sh;
|
||||
};
|
||||
};
|
||||
}
|
||||
92
features/direnv/use_dev.sh
Normal file
92
features/direnv/use_dev.sh
Normal file
@@ -0,0 +1,92 @@
|
||||
# shellcheck shell=bash
|
||||
# composable nix devshell from matej.nix
|
||||
# usage in .envrc: use dev uv_14 pg_18 --extra cairo pkg-config
|
||||
|
||||
# generates a flake and delegates to use_flake at the calling scope
|
||||
use_dev() {
|
||||
local nix_list="" extra_list="" in_extra=0
|
||||
for c in "$@"; do
|
||||
if [[ "$c" == "--extra" ]]; then
|
||||
in_extra=1
|
||||
continue
|
||||
fi
|
||||
if [[ $in_extra -eq 1 ]]; then
|
||||
if [[ ! "$c" =~ ^[a-zA-Z_][a-zA-Z0-9_-]*$ ]]; then
|
||||
log_error "use_dev: invalid package name: $c"
|
||||
return 1
|
||||
fi
|
||||
extra_list="$extra_list pkgs.$c"
|
||||
else
|
||||
if [[ ! "$c" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]]; then
|
||||
log_error "use_dev: invalid component name: $c"
|
||||
return 1
|
||||
fi
|
||||
nix_list="$nix_list \"$c\""
|
||||
fi
|
||||
done
|
||||
|
||||
local system
|
||||
case "$(uname -s)-$(uname -m)" in
|
||||
Linux-x86_64) system="x86_64-linux" ;;
|
||||
Linux-aarch64) system="aarch64-linux" ;;
|
||||
Darwin-x86_64) system="x86_64-darwin" ;;
|
||||
Darwin-arm64) system="aarch64-darwin" ;;
|
||||
esac
|
||||
|
||||
if [[ -z "$system" ]]; then
|
||||
log_error "use_dev: unsupported platform: $(uname -s)-$(uname -m)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local dev_path nixpkgs_path registry_filter
|
||||
# shellcheck disable=SC2016 # $id is a jq variable, not shell
|
||||
registry_filter='.flakes[] | select(.from.id == $id) | .to.path'
|
||||
|
||||
local registry_file="${XDG_CONFIG_HOME:-$HOME/.config}/nix/registry.json"
|
||||
if [[ ! -f "$registry_file" ]]; then
|
||||
registry_file="/etc/nix/registry.json"
|
||||
fi
|
||||
|
||||
dev_path="$(jq -re --arg id dev "$registry_filter" "$registry_file" 2>/dev/null)"
|
||||
nixpkgs_path="$(jq -re --arg id nixpkgs "$registry_filter" "$registry_file" 2>/dev/null)"
|
||||
|
||||
if [[ -z "$dev_path" ]]; then
|
||||
log_error "use_dev: 'dev' not found in nix registry"
|
||||
return 1
|
||||
fi
|
||||
if [[ -z "$nixpkgs_path" ]]; then
|
||||
log_error "use_dev: 'nixpkgs' not found in nix registry"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local components_hash project_hash cache_dir
|
||||
components_hash="$(sha256sum "$dev_path/flake/dev-components.nix" 2>/dev/null | cut -c1-16)"
|
||||
project_hash="$(echo "$PWD" | sha256sum | cut -c1-16)"
|
||||
cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/dev-flakes/$project_hash"
|
||||
mkdir -p "$cache_dir"
|
||||
|
||||
cat >"$cache_dir/flake.nix.tmp" <<DEVFLAKE
|
||||
# dev-components: $components_hash
|
||||
{
|
||||
inputs.dev = { url = "path:${dev_path}"; flake = false; };
|
||||
inputs.nixpkgs.url = "path:${nixpkgs_path}";
|
||||
outputs = { dev, nixpkgs, ... }:
|
||||
let
|
||||
system = "${system}";
|
||||
pkgs = nixpkgs.legacyPackages.\${system};
|
||||
devLib = import "\${dev}/flake/dev-components.nix" { inherit pkgs; lib = nixpkgs.lib; };
|
||||
in {
|
||||
devShells.\${system}.default = devLib.mkComponentShell [$nix_list ] [${extra_list} ];
|
||||
};
|
||||
}
|
||||
DEVFLAKE
|
||||
|
||||
if ! cmp -s "$cache_dir/flake.nix.tmp" "$cache_dir/flake.nix" 2>/dev/null; then
|
||||
mv "$cache_dir/flake.nix.tmp" "$cache_dir/flake.nix"
|
||||
rm -f "$cache_dir/flake.lock"
|
||||
else
|
||||
rm "$cache_dir/flake.nix.tmp"
|
||||
fi
|
||||
|
||||
use_flake "path:$cache_dir"
|
||||
}
|
||||
24
features/docker.nix
Normal file
24
features/docker.nix
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
user,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.docker;
|
||||
in
|
||||
{
|
||||
options.features.docker.enable = lib.mkEnableOption "docker";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
virtualisation.docker = {
|
||||
enable = true;
|
||||
logDriver = "json-file";
|
||||
};
|
||||
|
||||
users.users.${user}.extraGroups = [ "docker" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
61
features/filedrop.nix
Normal file
61
features/filedrop.nix
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
userKeys,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.filedrop;
|
||||
in
|
||||
{
|
||||
options.features.filedrop = {
|
||||
enable = lib.mkEnableOption "filedrop sftp service";
|
||||
|
||||
sopsFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
sops.secrets.filedrop-authorized-keys = {
|
||||
inherit (cfg) sopsFile;
|
||||
mode = "0444";
|
||||
};
|
||||
|
||||
users.groups.filedrop = {
|
||||
members = [ "matej" ];
|
||||
};
|
||||
|
||||
users.users.filedrop = {
|
||||
isSystemUser = true;
|
||||
group = "filedrop";
|
||||
home = "/home/filedrop";
|
||||
shell = "/run/current-system/sw/bin/nologin";
|
||||
openssh.authorizedKeys.keys = userKeys.sshAuthorizedKeys;
|
||||
};
|
||||
|
||||
# chroot dir must be root-owned; incoming is writable by filedrop
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /home/filedrop 0755 root root -"
|
||||
"d /home/filedrop/incoming 2775 filedrop filedrop -"
|
||||
"a+ /home/filedrop/incoming - - - - group:filedrop:rwx"
|
||||
"a+ /home/filedrop/incoming - - - - default:group:filedrop:rwx"
|
||||
"a+ /home/filedrop/incoming - - - - default:mask::rwx"
|
||||
"L /home/matej/filedrop - - - - /home/filedrop/incoming"
|
||||
];
|
||||
|
||||
# relaxed umask so default acl takes full effect
|
||||
services.openssh.extraConfig = ''
|
||||
Match User filedrop
|
||||
ForceCommand internal-sftp -u 0002
|
||||
ChrootDirectory /home/filedrop
|
||||
AuthorizedKeysFile /etc/ssh/authorized_keys.d/filedrop %h/.ssh/authorized_keys ${config.sops.secrets.filedrop-authorized-keys.path}
|
||||
AllowTcpForwarding no
|
||||
X11Forwarding no
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
26
features/gaming.nix
Normal file
26
features/gaming.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.gaming;
|
||||
in
|
||||
{
|
||||
options.features.gaming.enable = lib.mkEnableOption "gaming";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
programs.steam = {
|
||||
enable = true;
|
||||
remotePlay.openFirewall = true;
|
||||
dedicatedServer.openFirewall = true;
|
||||
localNetworkGameTransfers.openFirewall = true;
|
||||
};
|
||||
|
||||
environment.systemPackages = [ pkgs.prismlauncher ];
|
||||
};
|
||||
};
|
||||
}
|
||||
29
features/git.nix
Normal file
29
features/git.nix
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
nixos =
|
||||
{ lib, ... }:
|
||||
{
|
||||
options.features.git.enable = lib.mkEnableOption "git";
|
||||
};
|
||||
|
||||
home =
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
osConfig,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = osConfig.features.git;
|
||||
packages = inputs.self.outputs.packages.${pkgs.stdenv.hostPlatform.system};
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
home.packages = [
|
||||
pkgs.git
|
||||
packages.git-linearize
|
||||
packages.ggman
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
43
features/gnupg.nix
Normal file
43
features/gnupg.nix
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.gnupg;
|
||||
in
|
||||
{
|
||||
options.features.gnupg = {
|
||||
enable = lib.mkEnableOption "gnupg";
|
||||
|
||||
yubikey.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
{
|
||||
programs.gnupg.agent = {
|
||||
enable = true;
|
||||
enableSSHSupport = true;
|
||||
enableExtraSocket = true;
|
||||
};
|
||||
}
|
||||
|
||||
(lib.mkIf cfg.yubikey.enable {
|
||||
environment.systemPackages = with pkgs; [
|
||||
yubikey-personalization
|
||||
yubikey-manager
|
||||
];
|
||||
|
||||
services.pcscd.enable = true;
|
||||
})
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
32
features/harmonia/cache-builder.sh
Normal file
32
features/harmonia/cache-builder.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
set -uo pipefail
|
||||
|
||||
build() {
|
||||
local name="$1" ref="$2" link="$3"
|
||||
echo "building $name..." >&2
|
||||
if nix build "$ref" --out-link "$link"; then
|
||||
return 0
|
||||
else
|
||||
echo "FAILED: $name" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
mkdir -p "$GC_ROOT_DIR"
|
||||
local failed=0
|
||||
|
||||
for host in $HOSTS; do
|
||||
build "$host" \
|
||||
"$FLAKE_REF#nixosConfigurations.$host.config.system.build.toplevel" \
|
||||
"$GC_ROOT_DIR/$host" || failed=1
|
||||
done
|
||||
|
||||
build "ephvm-image" \
|
||||
"$FLAKE_REF#nixosConfigurations.ephvm.config.system.build.images.qemu" \
|
||||
"$GC_ROOT_DIR/ephvm-image" || failed=1
|
||||
|
||||
return $failed
|
||||
}
|
||||
|
||||
main "$@"
|
||||
52
features/harmonia/default.nix
Normal file
52
features/harmonia/default.nix
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.harmonia;
|
||||
hosts = [
|
||||
"fw16"
|
||||
"tower"
|
||||
"cube"
|
||||
"floo"
|
||||
"ephvm"
|
||||
];
|
||||
flakeRef = inputs.self.outPath;
|
||||
in
|
||||
{
|
||||
options.features.harmonia.enable = lib.mkEnableOption "harmonia";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.harmonia.cache = {
|
||||
enable = true;
|
||||
signKeyPaths = [ config.sops.secrets.nix-signing-key.path ];
|
||||
};
|
||||
|
||||
networking.firewall.interfaces."tailscale0".allowedTCPPorts = [ 5000 ];
|
||||
|
||||
systemd.services.cache-builder = {
|
||||
description = "Build all host closures for binary cache";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.bash}/bin/bash ${./cache-builder.sh}";
|
||||
};
|
||||
environment = {
|
||||
FLAKE_REF = flakeRef;
|
||||
HOSTS = builtins.concatStringsSep " " hosts;
|
||||
GC_ROOT_DIR = "/nix/var/nix/gcroots/cache-builder";
|
||||
};
|
||||
path = [ config.nix.package ];
|
||||
};
|
||||
|
||||
# restart cache-builder after every nixos switch (non-blocking)
|
||||
system.activationScripts.cache-builder = lib.stringAfter [ "specialfs" ] ''
|
||||
${config.systemd.package}/bin/systemctl restart --no-block cache-builder.service || true
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
90
features/initrd-ssh.nix
Normal file
90
features/initrd-ssh.nix
Normal file
@@ -0,0 +1,90 @@
|
||||
{
|
||||
nixos =
|
||||
{ lib, config, ... }:
|
||||
let
|
||||
cfg = config.features.initrd-ssh;
|
||||
keyDir = "/etc/secrets/initrd";
|
||||
|
||||
mkIpString =
|
||||
{
|
||||
address,
|
||||
gateway,
|
||||
netmask,
|
||||
interface,
|
||||
...
|
||||
}:
|
||||
"${address}::${gateway}:${netmask}::${interface}:none";
|
||||
in
|
||||
{
|
||||
options.features.initrd-ssh = {
|
||||
enable = lib.mkEnableOption "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 = lib.mkIf cfg.enable {
|
||||
boot.initrd.availableKernelModules = [ cfg.networkModule ];
|
||||
boot.initrd.kernelModules = [ cfg.networkModule ];
|
||||
boot.kernelParams = lib.mkIf cfg.ip.enable [
|
||||
"ip=${mkIpString cfg.ip}"
|
||||
];
|
||||
|
||||
boot.initrd.systemd.enable = true;
|
||||
|
||||
# remote unlock may take a while; don't let device units give up
|
||||
boot.initrd.systemd.settings.Manager.DefaultDeviceTimeoutSec = "infinity";
|
||||
|
||||
boot.initrd.network = {
|
||||
enable = true;
|
||||
ssh = {
|
||||
enable = true;
|
||||
port = 22;
|
||||
hostKeys = [
|
||||
"${keyDir}/ssh_host_rsa_key"
|
||||
"${keyDir}/ssh_host_ed25519_key"
|
||||
];
|
||||
inherit (cfg) authorizedKeys;
|
||||
};
|
||||
};
|
||||
|
||||
# systemd-networkd retries DHCP indefinitely, unlike udhcpc
|
||||
boot.initrd.systemd.network.networks = lib.mkIf (!cfg.ip.enable) {
|
||||
"10-initrd" = {
|
||||
matchConfig.Driver = cfg.networkModule;
|
||||
networkConfig.DHCP = "yes";
|
||||
};
|
||||
};
|
||||
|
||||
# forward LUKS password prompt to the SSH session
|
||||
boot.initrd.systemd.users.root.shell = "/bin/systemd-tty-ask-password-agent";
|
||||
};
|
||||
};
|
||||
}
|
||||
30
features/localisation.nix
Normal file
30
features/localisation.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
nixos =
|
||||
{ lib, config, ... }:
|
||||
let
|
||||
cfg = config.features.localisation;
|
||||
in
|
||||
{
|
||||
options.features.localisation = {
|
||||
enable = lib.mkEnableOption "localisation";
|
||||
|
||||
timeZone = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Europe/Ljubljana";
|
||||
};
|
||||
|
||||
defaultLocale = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "en_US.UTF-8";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
time.timeZone = cfg.timeZone;
|
||||
i18n.defaultLocale = cfg.defaultLocale;
|
||||
|
||||
# NOTE:(@janezicmatej) some apps (e.g. java) need TZ env var explicitly
|
||||
environment.variables.TZ = cfg.timeZone;
|
||||
};
|
||||
};
|
||||
}
|
||||
82
features/neovim.nix
Normal file
82
features/neovim.nix
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
nixos =
|
||||
{ lib, ... }:
|
||||
{
|
||||
options.features.neovim = {
|
||||
enable = lib.mkEnableOption "neovim";
|
||||
|
||||
dotfiles = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
home =
|
||||
{
|
||||
config,
|
||||
options,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
osConfig,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = osConfig.features.neovim;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
(lib.optionalAttrs (options ? stylix) {
|
||||
# disable stylix neovim target when stylix is present
|
||||
stylix.targets.neovim.enable = false;
|
||||
})
|
||||
{
|
||||
xdg.configFile."nvim" = lib.mkIf (cfg.dotfiles != null) {
|
||||
source = cfg.dotfiles;
|
||||
};
|
||||
|
||||
programs.neovim = {
|
||||
enable = true;
|
||||
sideloadInitLua = 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 ]}"
|
||||
];
|
||||
};
|
||||
}
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
18
features/networkmanager.nix
Normal file
18
features/networkmanager.nix
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
nixos =
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.features.networkmanager;
|
||||
in
|
||||
{
|
||||
options.features.networkmanager.enable = lib.mkEnableOption "networkmanager";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
networking.networkmanager.enable = true;
|
||||
networking.nameservers = [
|
||||
"1.1.1.1"
|
||||
"8.8.8.8"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
14
features/nix-ld.nix
Normal file
14
features/nix-ld.nix
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
nixos =
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.features.nix-ld;
|
||||
in
|
||||
{
|
||||
options.features.nix-ld.enable = lib.mkEnableOption "nix-ld";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
programs.nix-ld.enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
71
features/nix-settings.nix
Normal file
71
features/nix-settings.nix
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
nixos =
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.features.nix-settings;
|
||||
in
|
||||
{
|
||||
options.features.nix-settings = {
|
||||
enable = lib.mkEnableOption "nix settings";
|
||||
|
||||
towerCache.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
|
||||
};
|
||||
|
||||
gc = {
|
||||
dates = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "monthly";
|
||||
};
|
||||
|
||||
olderThan = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "30d";
|
||||
};
|
||||
};
|
||||
|
||||
optimise.dates = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ "monthly" ];
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
nix = {
|
||||
settings = {
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
download-buffer-size = 2 * 1024 * 1024 * 1024;
|
||||
download-attempts = 3;
|
||||
fallback = true;
|
||||
warn-dirty = false;
|
||||
substituters = [
|
||||
"https://cache.nixos.org"
|
||||
"https://nix-community.cachix.org?priority=45"
|
||||
]
|
||||
++ lib.optional cfg.towerCache.enable "http://tower:5000?priority=50";
|
||||
trusted-public-keys = [
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
]
|
||||
++ lib.optional cfg.towerCache.enable "matej.nix-1:TdbemLVYblvAxqJcwb3mVKmmr3cfzXbMcZHE5ILnZDE=";
|
||||
};
|
||||
|
||||
gc = {
|
||||
automatic = true;
|
||||
inherit (cfg.gc) dates;
|
||||
options = "--delete-older-than ${cfg.gc.olderThan}";
|
||||
};
|
||||
|
||||
optimise = {
|
||||
automatic = true;
|
||||
inherit (cfg.optimise) dates;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
23
features/onepassword.nix
Normal file
23
features/onepassword.nix
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
user,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.onepassword;
|
||||
in
|
||||
{
|
||||
options.features.onepassword.enable = lib.mkEnableOption "1password";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
programs._1password.enable = true;
|
||||
programs._1password-gui = {
|
||||
enable = true;
|
||||
polkitPolicyOwners = [ user ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
30
features/openssh.nix
Normal file
30
features/openssh.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
nixos =
|
||||
{ lib, config, ... }:
|
||||
let
|
||||
cfg = config.features.openssh;
|
||||
in
|
||||
{
|
||||
options.features.openssh = {
|
||||
enable = lib.mkEnableOption "openssh";
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 22;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
ports = [ cfg.port ];
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
AllowUsers = null;
|
||||
PermitRootLogin = "no";
|
||||
StreamLocalBindUnlink = "yes";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
57
features/power.nix
Normal file
57
features/power.nix
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
nixos =
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.features.power;
|
||||
in
|
||||
{
|
||||
options.features.power = {
|
||||
enable = lib.mkEnableOption "laptop power management";
|
||||
|
||||
resumeDevice = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
};
|
||||
|
||||
lidSwitch = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "suspend-then-hibernate";
|
||||
};
|
||||
|
||||
powerKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "suspend-then-hibernate";
|
||||
};
|
||||
|
||||
idleAction = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "suspend-then-hibernate";
|
||||
};
|
||||
|
||||
idleActionSec = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "15min";
|
||||
};
|
||||
|
||||
hibernateDelaySec = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "30min";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
boot.resumeDevice = lib.mkIf (cfg.resumeDevice != null) cfg.resumeDevice;
|
||||
|
||||
services.logind.settings.Login = {
|
||||
HandleLidSwitch = cfg.lidSwitch;
|
||||
HandlePowerKey = cfg.powerKey;
|
||||
IdleAction = cfg.idleAction;
|
||||
IdleActionSec = cfg.idleActionSec;
|
||||
};
|
||||
|
||||
systemd.sleep.settings.Sleep = {
|
||||
HibernateDelaySec = cfg.hibernateDelaySec;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
19
features/printing.nix
Normal file
19
features/printing.nix
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
nixos =
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.features.printing;
|
||||
in
|
||||
{
|
||||
options.features.printing.enable = lib.mkEnableOption "printing";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.printing.enable = true;
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
nssmdns4 = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
25
features/remote-base.nix
Normal file
25
features/remote-base.nix
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
user,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.remote-base;
|
||||
in
|
||||
{
|
||||
options.features.remote-base.enable = lib.mkEnableOption "remote-base";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
sops.secrets.user-password = {
|
||||
sopsFile = ../secrets/common.yaml;
|
||||
neededForUsers = true;
|
||||
};
|
||||
|
||||
users.mutableUsers = false;
|
||||
users.users.${user}.hashedPasswordFile = config.sops.secrets.user-password.path;
|
||||
};
|
||||
};
|
||||
}
|
||||
33
features/shell.nix
Normal file
33
features/shell.nix
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
nixos =
|
||||
{ lib, ... }:
|
||||
{
|
||||
options.features.shell.enable = lib.mkEnableOption "shell extras";
|
||||
};
|
||||
|
||||
home =
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
osConfig,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = osConfig.features.shell;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
home.packages = with pkgs; [
|
||||
fzf
|
||||
htop
|
||||
jc
|
||||
jq
|
||||
openssl
|
||||
pv
|
||||
ripgrep
|
||||
fd
|
||||
tmux
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
100
features/sway.nix
Normal file
100
features/sway.nix
Normal file
@@ -0,0 +1,100 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.sway;
|
||||
desktopCfg = config.features.desktop;
|
||||
in
|
||||
{
|
||||
options.features.sway = {
|
||||
enable = lib.mkEnableOption "sway window manager";
|
||||
|
||||
greeter.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
{
|
||||
# soft dependency
|
||||
features.desktop.enable = lib.mkDefault true;
|
||||
|
||||
# hard dependency
|
||||
assertions = [
|
||||
{
|
||||
assertion = desktopCfg.enable;
|
||||
message = "features.sway requires features.desktop";
|
||||
}
|
||||
];
|
||||
|
||||
programs.sway = {
|
||||
enable = true;
|
||||
package = pkgs.swayfx;
|
||||
wrapperFeatures.gtk = true;
|
||||
extraSessionCommands = ''
|
||||
# fix for java awt apps not rendering
|
||||
export _JAVA_AWT_WM_NONREPARENTING=1
|
||||
# propagate XDG_DATA_DIRS to dbus/systemd for d-bus activated apps
|
||||
dbus-update-activation-environment --systemd XDG_DATA_DIRS
|
||||
'';
|
||||
};
|
||||
|
||||
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
|
||||
];
|
||||
}
|
||||
|
||||
# greeter
|
||||
(lib.mkIf cfg.greeter.enable {
|
||||
programs.regreet = {
|
||||
enable = true;
|
||||
cageArgs = [
|
||||
"-s"
|
||||
"-m"
|
||||
"last"
|
||||
];
|
||||
font = {
|
||||
name = lib.mkForce "JetBrainsMono Nerd Font";
|
||||
size = lib.mkForce 14;
|
||||
};
|
||||
settings = {
|
||||
background = {
|
||||
path = lib.mkForce (toString desktopCfg.theme.wallpaper);
|
||||
fit = lib.mkForce "Cover";
|
||||
};
|
||||
GTK = {
|
||||
application_prefer_dark_theme = lib.mkForce true;
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
17
features/tailscale.nix
Normal file
17
features/tailscale.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
nixos =
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.features.tailscale;
|
||||
in
|
||||
{
|
||||
options.features.tailscale.enable = lib.mkEnableOption "tailscale";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
useRoutingFeatures = "both";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
59
features/udev.nix
Normal file
59
features/udev.nix
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.udev;
|
||||
in
|
||||
{
|
||||
options.features.udev = {
|
||||
enable = lib.mkEnableOption "custom udev rules";
|
||||
|
||||
kindle.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
ledger.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
keyboard-zsa.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
(lib.mkIf cfg.kindle.enable {
|
||||
# NOTE:(@janezicmatej) uses services.udev.packages instead of extraRules
|
||||
# because extraRules writes to 99-local.rules which is too late for uaccess
|
||||
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";
|
||||
})
|
||||
];
|
||||
})
|
||||
|
||||
(lib.mkIf cfg.ledger.enable {
|
||||
hardware.ledger.enable = true;
|
||||
})
|
||||
|
||||
(lib.mkIf cfg.keyboard-zsa.enable {
|
||||
hardware.keyboard.zsa.enable = true;
|
||||
})
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
30
features/user-matej.nix
Normal file
30
features/user-matej.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
let
|
||||
sshKeys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICQGLdINKzs+sEy62Pefng0bcedgU396+OryFgeH99/c janezicmatej"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDk00+Km03epQXQs+xEwwH3zcurACzkEH+kDOPBw6RQe openpgp:0xB095D449"
|
||||
];
|
||||
in
|
||||
{
|
||||
keys = {
|
||||
sshAuthorizedKeys = sshKeys;
|
||||
};
|
||||
|
||||
nixos = _: {
|
||||
users.users.matej = {
|
||||
uid = 1000;
|
||||
isNormalUser = true;
|
||||
home = "/home/matej";
|
||||
extraGroups = [ "wheel" ];
|
||||
openssh.authorizedKeys.keys = sshKeys;
|
||||
};
|
||||
|
||||
users.groups.matej = {
|
||||
gid = 1000;
|
||||
members = [ "matej" ];
|
||||
};
|
||||
};
|
||||
|
||||
home = _: {
|
||||
home.stateVersion = "26.05";
|
||||
};
|
||||
}
|
||||
112
features/vm-guest.nix
Normal file
112
features/vm-guest.nix
Normal file
@@ -0,0 +1,112 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.vm-guest;
|
||||
autoUser = cfg.automount.user;
|
||||
autoHome = config.users.users.${autoUser}.home;
|
||||
autoGroup = config.users.users.${autoUser}.group;
|
||||
in
|
||||
{
|
||||
options.features.vm-guest = {
|
||||
enable = lib.mkEnableOption "qemu vm guest";
|
||||
|
||||
headless = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
|
||||
automount = {
|
||||
enable = lib.mkEnableOption "9p share 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 = "${autoHome}/mnt";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
{
|
||||
services.spice-vdagentd.enable = lib.mkIf (!cfg.headless) true;
|
||||
|
||||
boot.kernelParams = lib.mkIf cfg.headless [ "console=ttyS0,115200" ];
|
||||
|
||||
# 9p autoloads on first mount
|
||||
boot.initrd.availableKernelModules = [
|
||||
"9p"
|
||||
"9pnet_virtio"
|
||||
];
|
||||
|
||||
networking = {
|
||||
useDHCP = true;
|
||||
firewall.allowedTCPPorts = [ 22 ];
|
||||
};
|
||||
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
curl
|
||||
wget
|
||||
htop
|
||||
];
|
||||
}
|
||||
|
||||
(lib.mkIf cfg.automount.enable {
|
||||
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="${cfg.automount.basePath}"
|
||||
PREFIX="${cfg.automount.prefix}"
|
||||
mkdir -p "$BASE"
|
||||
chown ${autoUser}:${autoGroup} "$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
|
||||
'';
|
||||
};
|
||||
};
|
||||
})
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
55
features/zsh.nix
Normal file
55
features/zsh.nix
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
nixos =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
user,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.features.zsh;
|
||||
in
|
||||
{
|
||||
options.features.zsh = {
|
||||
enable = lib.mkEnableOption "zsh";
|
||||
|
||||
loginShell.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
{
|
||||
programs.zsh.enable = true;
|
||||
environment.etc."zshenv".text = ''
|
||||
export ZDOTDIR=$HOME/.config/zsh
|
||||
'';
|
||||
}
|
||||
|
||||
(lib.mkIf cfg.loginShell.enable {
|
||||
users.users.${user}.shell = pkgs.zsh;
|
||||
})
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
home =
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
osConfig,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = osConfig.features.zsh;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
home.packages = [ pkgs.starship ];
|
||||
};
|
||||
};
|
||||
}
|
||||
302
flake.lock
generated
302
flake.lock
generated
@@ -84,24 +84,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"claude-code-overlay": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772252606,
|
||||
"narHash": "sha256-SiIhFq4XbD3LmODQ2mTtakRBnjBn/KoSgAOId1cL1Ks=",
|
||||
"owner": "ryoppippi",
|
||||
"repo": "claude-code-overlay",
|
||||
"rev": "b1ebf027412136bbbe4202741c3d48721644bc4b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ryoppippi",
|
||||
"repo": "claude-code-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
"lastModified": 1765145449,
|
||||
@@ -117,14 +99,34 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"disko": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1776613567,
|
||||
"narHash": "sha256-gC9Cp5ibBmGD5awCA9z7xy6MW6iJufhazTYJOiGlCUI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "32f4236bfc141ae930b5ba2fb604f561fed5219d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"firefox-gnome-theme": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1764873433,
|
||||
"narHash": "sha256-1XPewtGMi+9wN9Ispoluxunw/RwozuTRVuuQOmxzt+A=",
|
||||
"lastModified": 1775176642,
|
||||
"narHash": "sha256-2veEED0Fg7Fsh81tvVDNYR6SzjqQxa7hbi18Jv4LWpM=",
|
||||
"owner": "rafaelmardojai",
|
||||
"repo": "firefox-gnome-theme",
|
||||
"rev": "f7ffd917ac0d253dbd6a3bf3da06888f57c69f92",
|
||||
"rev": "179704030c5286c729b5b0522037d1d51341022c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -151,17 +153,14 @@
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"neovim-nightly-overlay",
|
||||
"nixpkgs"
|
||||
]
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772408722,
|
||||
"narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=",
|
||||
"lastModified": 1775087534,
|
||||
"narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3",
|
||||
"rev": "3107b77cd68437b9a76194f0f7f9c55f2329ca5b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -173,16 +172,16 @@
|
||||
"flake-parts_2": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"stylix",
|
||||
"neovim-nightly-overlay",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767609335,
|
||||
"narHash": "sha256-feveD98mQpptwrAEggBQKJTYbvwwglSbOv53uCfH9PY=",
|
||||
"lastModified": 1775087534,
|
||||
"narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "250481aafeb741edfe23d29195671c19b36b6dca",
|
||||
"rev": "3107b77cd68437b9a76194f0f7f9c55f2329ca5b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -191,21 +190,24 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"flake-parts_3": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
"nixpkgs-lib": [
|
||||
"stylix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"lastModified": 1775087534,
|
||||
"narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "3107b77cd68437b9a76194f0f7f9c55f2329ca5b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
@@ -250,20 +252,18 @@
|
||||
"gnome-shell": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.gnome.org",
|
||||
"lastModified": 1767737596,
|
||||
"narHash": "sha256-eFujfIUQDgWnSJBablOuG+32hCai192yRdrNHTv0a+s=",
|
||||
"owner": "GNOME",
|
||||
"repo": "gnome-shell",
|
||||
"rev": "ef02db02bf0ff342734d525b5767814770d85b49",
|
||||
"type": "gitlab"
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"host": "gitlab.gnome.org",
|
||||
"owner": "GNOME",
|
||||
"ref": "gnome-49",
|
||||
"repo": "gnome-shell",
|
||||
"type": "gitlab"
|
||||
"rev": "ef02db02bf0ff342734d525b5767814770d85b49",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
@@ -273,16 +273,15 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772380125,
|
||||
"narHash": "sha256-8C+y46xA9bxcchj9GeDPJaRUDApaA3sy2fhJr1bTbUw=",
|
||||
"lastModified": 1776777932,
|
||||
"narHash": "sha256-0R3Yow/NzSeVGUke5tL7CCkqmss4Vmi6BbV6idHzq/8=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "a07a44a839eb036e950bf397d9b782916f8dcab3",
|
||||
"rev": "5d5640599a0050b994330328b9fd45709c909720",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "release-25.11",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -313,16 +312,16 @@
|
||||
},
|
||||
"neovim-nightly-overlay": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"flake-parts": "flake-parts_2",
|
||||
"neovim-src": "neovim-src",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772409903,
|
||||
"narHash": "sha256-yue9XaZ7WHOFJmm3DMEmrF536pHwGxTxh/xr0f1MzNU=",
|
||||
"lastModified": 1776729909,
|
||||
"narHash": "sha256-wGu/N42PJqrj8ju9GoXdppg4rwaKzZqdAjsgxJbCvfY=",
|
||||
"owner": "nix-community",
|
||||
"repo": "neovim-nightly-overlay",
|
||||
"rev": "28962d176db883e4fda4b808e220051f376969da",
|
||||
"rev": "ff21a18bde28b4c8ca0bc1f9a5b7186a1b89a3d1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -334,11 +333,11 @@
|
||||
"neovim-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1772353308,
|
||||
"narHash": "sha256-k/3msPgpWW9CRFIp3nz6hJzV+GArXw4m35c0t6fKJK4=",
|
||||
"lastModified": 1776727374,
|
||||
"narHash": "sha256-iP5SviNXW5W+ay4ZmwjDFsfQjfM+fYlUxRlLPHjpwWI=",
|
||||
"owner": "neovim",
|
||||
"repo": "neovim",
|
||||
"rev": "563f9ef7994a35686419b4524cd772c97960dac1",
|
||||
"rev": "901b3f0c394a53961781ebeee682e64ad690a242",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -349,11 +348,11 @@
|
||||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1771969195,
|
||||
"narHash": "sha256-qwcDBtrRvJbrrnv1lf/pREQi8t2hWZxVAyeMo7/E9sw=",
|
||||
"lastModified": 1775490113,
|
||||
"narHash": "sha256-2ZBhDNZZwYkRmefK5XLOusCJHnoeKkoN95hoSGgMxWM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "41c6b421bdc301b2624486e11905c9af7b8ec68e",
|
||||
"rev": "c775c2772ba56e906cbeb4e0b2db19079ef11ff7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -365,27 +364,42 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1768127708,
|
||||
"narHash": "sha256-1Sm77VfZh3mU0F5OqKABNLWxOuDeHIlcFjsXeeiPazs=",
|
||||
"lastModified": 1776329215,
|
||||
"narHash": "sha256-a8BYi3mzoJ/AcJP8UldOx8emoPRLeWqALZWu4ZvjPXw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ffbc9f8cbaacfb331b6017d5a5abb21a492c9a38",
|
||||
"rev": "b86751bc4085f48661017fa226dee99fab6c651b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1774748309,
|
||||
"narHash": "sha256-+U7gF3qxzwD5TZuANzZPeJTZRHS29OFQgkQ2kiTJBIQ=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "333c4e0545a6da976206c74db8773a1645b5870a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-master": {
|
||||
"locked": {
|
||||
"lastModified": 1772461137,
|
||||
"narHash": "sha256-5MFNMLcDmaXQbdGJVITwFTqJq3IVok4TSR/Oa/DbJys=",
|
||||
"lastModified": 1776807375,
|
||||
"narHash": "sha256-LDnHG0T54OEHyRydmGUlAND8ham0KrRNWjgoS+6GUd4=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "388c66870001909259d1879acd2e3e1108c1854d",
|
||||
"rev": "553ecb1686a2edb75dee44c9f72e1674e6adc26a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -395,50 +409,34 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1772419343,
|
||||
"narHash": "sha256-QU3Cd5DJH7dHyMnGEFfPcZDaCAsJQ6tUD+JuUsYqnKU=",
|
||||
"owner": "nixos",
|
||||
"lastModified": 1776560675,
|
||||
"narHash": "sha256-p68udKWWh7+V4ZPpcMDq0gTHWNZJnr4JPI+kHPPE40o=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "93178f6a00c22fcdee1c6f5f9ab92f2072072ea9",
|
||||
"rev": "e07580dae39738e46609eaab8b154de2488133ce",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-25.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1772173633,
|
||||
"narHash": "sha256-MOH58F4AIbCkh6qlQcwMycyk5SWvsqnS/TCfnqDlpj4=",
|
||||
"lastModified": 1776548001,
|
||||
"narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c0f3d81a7ddbc2b1332be0d8481a672b4f6004d6",
|
||||
"rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1772047000,
|
||||
"narHash": "sha256-7DaQVv4R97cii/Qdfy4tmDZMB2xxtyIvNGSwXBBhSmo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "1267bb4920d0fc06ea916734c11b0bf004bbe17e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-25.11",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -455,11 +453,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767886815,
|
||||
"narHash": "sha256-pB2BBv6X9cVGydEV/9Y8+uGCvuYJAlsprs1v1QHjccA=",
|
||||
"lastModified": 1775228139,
|
||||
"narHash": "sha256-ebbeHmg+V7w8050bwQOuhmQHoLOEOfqKzM1KgCTexK4=",
|
||||
"owner": "nix-community",
|
||||
"repo": "NUR",
|
||||
"rev": "4ff84374d77ff62e2e13a46c33bfeb73590f9fef",
|
||||
"rev": "601971b9c89e0304561977f2c28fa25e73aa7132",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -468,6 +466,22 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nvim": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1773783263,
|
||||
"narHash": "sha256-lZG4VERlfCwEJpW6C5irkwUxB+JoPVmuV3qOYD9WNYY=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "a95f1be85c858cb7d1bc0a8506dc9cb01161a3e7",
|
||||
"revCount": 93,
|
||||
"type": "git",
|
||||
"url": "https://git.janezic.dev/janezicmatej/nvim.git"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.janezic.dev/janezicmatej/nvim.git"
|
||||
}
|
||||
},
|
||||
"pre-commit": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
@@ -494,15 +508,17 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"assets": "assets",
|
||||
"claude-code-overlay": "claude-code-overlay",
|
||||
"flake-utils": "flake-utils",
|
||||
"disko": "disko",
|
||||
"flake-parts": "flake-parts",
|
||||
"home-manager": "home-manager",
|
||||
"lanzaboote": "lanzaboote",
|
||||
"neovim-nightly-overlay": "neovim-nightly-overlay",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"nixpkgs-master": "nixpkgs-master",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||
"nixpkgs-stable": "nixpkgs-stable",
|
||||
"nvim": "nvim",
|
||||
"sops-nix": "sops-nix",
|
||||
"stylix": "stylix"
|
||||
}
|
||||
},
|
||||
@@ -527,6 +543,26 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"sops-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1776771786,
|
||||
"narHash": "sha256-DRFGPfFV6hbrfO9a1PH1FkCi7qR5FgjSqsQGGvk1rdI=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "bef289e2248991f7afeb95965c82fbcd8ff72598",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"stylix": {
|
||||
"inputs": {
|
||||
"base16": "base16",
|
||||
@@ -534,30 +570,28 @@
|
||||
"base16-helix": "base16-helix",
|
||||
"base16-vim": "base16-vim",
|
||||
"firefox-gnome-theme": "firefox-gnome-theme",
|
||||
"flake-parts": "flake-parts_2",
|
||||
"flake-parts": "flake-parts_3",
|
||||
"gnome-shell": "gnome-shell",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nur": "nur",
|
||||
"systems": "systems_2",
|
||||
"tinted-foot": "tinted-foot",
|
||||
"systems": "systems",
|
||||
"tinted-kitty": "tinted-kitty",
|
||||
"tinted-schemes": "tinted-schemes",
|
||||
"tinted-tmux": "tinted-tmux",
|
||||
"tinted-zed": "tinted-zed"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1771788390,
|
||||
"narHash": "sha256-RzBpBwn93GWxLjacTte+ngwwg0L/BVOg4G/sSIeK3Rw=",
|
||||
"lastModified": 1776170745,
|
||||
"narHash": "sha256-Tl1aZVP5EIlT+k0+iAKH018GLHJpLz3hhJ0LNQOWxCc=",
|
||||
"owner": "danth",
|
||||
"repo": "stylix",
|
||||
"rev": "ebb238f14d6f930068be4718472da3105fd5d3bf",
|
||||
"rev": "e3861617645a43c9bbefde1aa6ac54dd0a44bfa9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "danth",
|
||||
"ref": "release-25.11",
|
||||
"repo": "stylix",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -577,38 +611,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tinted-foot": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1726913040,
|
||||
"narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-foot",
|
||||
"rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-foot",
|
||||
"rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tinted-kitty": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
@@ -628,11 +630,11 @@
|
||||
"tinted-schemes": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767817087,
|
||||
"narHash": "sha256-eGE8OYoK6HzhJt/7bOiNV2cx01IdIrHL7gXgjkHRdNo=",
|
||||
"lastModified": 1772661346,
|
||||
"narHash": "sha256-4eu3LqB9tPqe0Vaqxd4wkZiBbthLbpb7llcoE/p5HT0=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "schemes",
|
||||
"rev": "bd99656235aab343e3d597bf196df9bc67429507",
|
||||
"rev": "13b5b0c299982bb361039601e2d72587d6846294",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -644,11 +646,11 @@
|
||||
"tinted-tmux": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767489635,
|
||||
"narHash": "sha256-e6nnFnWXKBCJjCv4QG4bbcouJ6y3yeT70V9MofL32lU=",
|
||||
"lastModified": 1772934010,
|
||||
"narHash": "sha256-x+6+4UvaG+RBRQ6UaX+o6DjEg28u4eqhVRM9kpgJGjQ=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-tmux",
|
||||
"rev": "3c32729ccae99be44fe8a125d20be06f8d7d8184",
|
||||
"rev": "c3529673a5ab6e1b6830f618c45d9ce1bcdd829d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -660,11 +662,11 @@
|
||||
"tinted-zed": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767488740,
|
||||
"narHash": "sha256-wVOj0qyil8m+ouSsVZcNjl5ZR+1GdOOAooAatQXHbuU=",
|
||||
"lastModified": 1772909925,
|
||||
"narHash": "sha256-jx/5+pgYR0noHa3hk2esin18VMbnPSvWPL5bBjfTIAU=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "base16-zed",
|
||||
"rev": "11abb0b282ad3786a2aae088d3a01c60916f2e40",
|
||||
"rev": "b4d3a1b3bcbd090937ef609a0a3b37237af974df",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
135
flake.nix
135
flake.nix
@@ -2,30 +2,26 @@
|
||||
description = "matej's nix setup";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
|
||||
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.11";
|
||||
nixpkgs-master.url = "github:nixos/nixpkgs/master";
|
||||
|
||||
# dotfiles = {
|
||||
# url = "git+https://git.janezic.dev/janezicmatej/.dotfiles.git";
|
||||
# flake = false;
|
||||
# };
|
||||
# nvim = {
|
||||
# url = "git+https://git.janezic.dev/janezicmatej/nvim.git?ref=rewrite";
|
||||
# flake = false;
|
||||
# };
|
||||
nvim = {
|
||||
url = "git+https://git.janezic.dev/janezicmatej/nvim.git";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
|
||||
home-manager = {
|
||||
url = "github:nix-community/home-manager/release-25.11";
|
||||
url = "github:nix-community/home-manager";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
stylix = {
|
||||
url = "github:danth/stylix/release-25.11";
|
||||
url = "github:danth/stylix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
@@ -40,91 +36,48 @@
|
||||
};
|
||||
|
||||
neovim-nightly-overlay.url = "github:nix-community/neovim-nightly-overlay";
|
||||
claude-code-overlay.url = "github:ryoppippi/claude-code-overlay";
|
||||
|
||||
disko = {
|
||||
url = "github:nix-community/disko";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
sops-nix = {
|
||||
url = "github:Mic92/sops-nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
outputs =
|
||||
inputs@{
|
||||
flake-parts,
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
self,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
my-lib = import ./lib { inherit (nixpkgs) lib; };
|
||||
|
||||
overlays = [ ];
|
||||
|
||||
mkHost = my-lib.mkHost {
|
||||
inherit
|
||||
nixpkgs
|
||||
overlays
|
||||
inputs
|
||||
;
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
lib = my-lib;
|
||||
|
||||
nixosConfigurations = {
|
||||
fw16 = mkHost "fw16" {
|
||||
system = "x86_64-linux";
|
||||
user = "matej";
|
||||
};
|
||||
tower = mkHost "tower" {
|
||||
system = "x86_64-linux";
|
||||
user = "matej";
|
||||
};
|
||||
|
||||
# nixos-rebuild build-image --image-variant install-iso --flake .#iso
|
||||
iso = mkHost "iso" {
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
};
|
||||
|
||||
nixosModules = import ./modules/nixos {
|
||||
inherit my-lib;
|
||||
inherit (nixpkgs) lib;
|
||||
} { };
|
||||
|
||||
homeManagerModules = import ./modules/home-manager {
|
||||
inherit my-lib;
|
||||
inherit (nixpkgs) lib;
|
||||
} { };
|
||||
|
||||
nixosProfiles = import ./profiles {
|
||||
inherit my-lib;
|
||||
inherit (nixpkgs) lib;
|
||||
} { };
|
||||
}
|
||||
// flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in
|
||||
{
|
||||
packages =
|
||||
import ./packages
|
||||
{
|
||||
inherit my-lib;
|
||||
inherit (nixpkgs) lib;
|
||||
}
|
||||
{
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
pkgs-unstable = inputs.nixpkgs-unstable.legacyPackages.${system};
|
||||
pkgs-master = inputs.nixpkgs-master.legacyPackages.${system};
|
||||
};
|
||||
|
||||
formatter = pkgs.nixfmt-tree;
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = [
|
||||
pkgs.pre-commit
|
||||
pkgs.statix
|
||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
imports = [
|
||||
./flake/overlays.nix
|
||||
./flake/packages.nix
|
||||
./flake/devshell.nix
|
||||
./flake/hosts.nix
|
||||
];
|
||||
|
||||
systems = [ "x86_64-linux" ];
|
||||
|
||||
perSystem =
|
||||
{ system, ... }:
|
||||
{
|
||||
_module.args.pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ self.overlays.default ];
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
};
|
||||
|
||||
flake = {
|
||||
lib = import ./lib { inherit (nixpkgs) lib; };
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
89
flake/dev-components.nix
Normal file
89
flake/dev-components.nix
Normal file
@@ -0,0 +1,89 @@
|
||||
# composable dev environment components
|
||||
# imported by generated per-project flakes via use_dev
|
||||
{ pkgs, lib }:
|
||||
let
|
||||
# libraries needed by python native extensions
|
||||
pythonLibraries = [
|
||||
pkgs.stdenv.cc.cc.lib
|
||||
pkgs.zlib
|
||||
pkgs.openssl
|
||||
pkgs.curl
|
||||
pkgs.libffi
|
||||
];
|
||||
|
||||
mkNode = nodejs: {
|
||||
packages = [
|
||||
nodejs
|
||||
pkgs.corepack
|
||||
];
|
||||
env = {
|
||||
COREPACK_ENABLE_STRICT = "0";
|
||||
};
|
||||
};
|
||||
|
||||
mkUv = python: {
|
||||
packages = [
|
||||
python
|
||||
pkgs.uv
|
||||
pkgs.pkg-config
|
||||
];
|
||||
libraries = pythonLibraries;
|
||||
env = {
|
||||
UV_PYTHON_DOWNLOADS = "never";
|
||||
UV_PYTHON_PREFERENCE = "only-system";
|
||||
};
|
||||
shellHook = ''
|
||||
unset PYTHONPATH
|
||||
export UV_PROJECT_ENVIRONMENT="''${XDG_DATA_HOME:-$HOME/.local/share}/dev-venvs/$(basename "$PWD")-$(echo "$PWD" | sha256sum | cut -c1-8)"
|
||||
'';
|
||||
};
|
||||
|
||||
components = {
|
||||
uv_10 = mkUv pkgs.python310;
|
||||
uv_11 = mkUv pkgs.python311;
|
||||
uv_12 = mkUv pkgs.python312;
|
||||
uv_13 = mkUv pkgs.python313;
|
||||
uv_14 = mkUv pkgs.python314;
|
||||
|
||||
node_20 = mkNode pkgs.nodejs_20;
|
||||
node_22 = mkNode pkgs.nodejs_22;
|
||||
node_24 = mkNode pkgs.nodejs_24;
|
||||
|
||||
rust = {
|
||||
packages = [
|
||||
pkgs.rustc
|
||||
pkgs.cargo
|
||||
pkgs.rust-analyzer
|
||||
pkgs.openssl
|
||||
pkgs.pkg-config
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
# build a single mkShell from one or more component names
|
||||
mkComponentShell =
|
||||
names: extraPackages:
|
||||
let
|
||||
selected = map (n: components.${n}) names;
|
||||
allPackages = lib.concatMap (c: c.packages or [ ]) selected ++ extraPackages;
|
||||
allLibraries = lib.concatMap (c: c.libraries or [ ]) selected;
|
||||
allHooks = lib.concatMapStrings (c: c.shellHook or "") selected;
|
||||
allEnvs = lib.foldl' (acc: c: acc // (c.env or { })) { } selected;
|
||||
libPath = lib.makeLibraryPath allLibraries;
|
||||
in
|
||||
pkgs.mkShell (
|
||||
{
|
||||
packages = allPackages;
|
||||
shellHook =
|
||||
(lib.optionalString (allLibraries != [ ]) ''
|
||||
export LD_LIBRARY_PATH="${libPath}''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
||||
'')
|
||||
+ allHooks;
|
||||
}
|
||||
// lib.optionalAttrs (allEnvs != { }) { env = allEnvs; }
|
||||
);
|
||||
in
|
||||
{
|
||||
inherit components mkComponentShell;
|
||||
}
|
||||
21
flake/devshell.nix
Normal file
21
flake/devshell.nix
Normal file
@@ -0,0 +1,21 @@
|
||||
_: {
|
||||
perSystem =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
formatter = pkgs.nixfmt-tree;
|
||||
|
||||
devShells = {
|
||||
default = pkgs.mkShell {
|
||||
packages = [
|
||||
pkgs.pre-commit
|
||||
pkgs.statix
|
||||
pkgs.shellcheck
|
||||
pkgs.shfmt
|
||||
pkgs.qemu
|
||||
pkgs.sops
|
||||
pkgs.ssh-to-age
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
152
flake/hosts.nix
Normal file
152
flake/hosts.nix
Normal file
@@ -0,0 +1,152 @@
|
||||
{ inputs, self, ... }:
|
||||
|
||||
let
|
||||
inherit (inputs) nixpkgs;
|
||||
my-lib = import ../lib { inherit (nixpkgs) lib; };
|
||||
|
||||
mkHost = my-lib.mkHost {
|
||||
inherit nixpkgs inputs;
|
||||
overlays = [ self.overlays.default ];
|
||||
};
|
||||
in
|
||||
{
|
||||
flake.nixosConfigurations = {
|
||||
fw16 = mkHost "fw16" {
|
||||
system = "x86_64-linux";
|
||||
user = "matej";
|
||||
features = [
|
||||
"bootloader"
|
||||
"claude"
|
||||
"desktop"
|
||||
"dev"
|
||||
"direnv"
|
||||
"docker"
|
||||
"gaming"
|
||||
"git"
|
||||
"gnupg"
|
||||
"localisation"
|
||||
"neovim"
|
||||
"networkmanager"
|
||||
"nix-ld"
|
||||
"nix-settings"
|
||||
"onepassword"
|
||||
"openssh"
|
||||
"power"
|
||||
"printing"
|
||||
"shell"
|
||||
"sway"
|
||||
"tailscale"
|
||||
"udev"
|
||||
"zsh"
|
||||
];
|
||||
};
|
||||
|
||||
tower = mkHost "tower" {
|
||||
system = "x86_64-linux";
|
||||
user = "matej";
|
||||
features = [
|
||||
"bootloader"
|
||||
"claude"
|
||||
"desktop"
|
||||
"dev"
|
||||
"direnv"
|
||||
"docker"
|
||||
"gaming"
|
||||
"git"
|
||||
"gnupg"
|
||||
"harmonia"
|
||||
"initrd-ssh"
|
||||
"localisation"
|
||||
"neovim"
|
||||
"networkmanager"
|
||||
"nix-ld"
|
||||
"nix-settings"
|
||||
"onepassword"
|
||||
"openssh"
|
||||
"printing"
|
||||
"shell"
|
||||
"sway"
|
||||
"tailscale"
|
||||
"udev"
|
||||
"zsh"
|
||||
];
|
||||
};
|
||||
|
||||
# nixos-rebuild build-image --image-variant install-iso --flake .#iso
|
||||
iso = mkHost "iso" {
|
||||
system = "x86_64-linux";
|
||||
user = "matej";
|
||||
features = [
|
||||
"nix-settings"
|
||||
"openssh"
|
||||
"zsh"
|
||||
];
|
||||
};
|
||||
|
||||
cube = mkHost "cube" {
|
||||
system = "x86_64-linux";
|
||||
user = "matej";
|
||||
features = [
|
||||
"bootloader"
|
||||
"localisation"
|
||||
"nix-settings"
|
||||
"openssh"
|
||||
"remote-base"
|
||||
"shell"
|
||||
"tailscale"
|
||||
"zsh"
|
||||
];
|
||||
};
|
||||
|
||||
# nix run github:nix-community/nixos-anywhere -- --flake .#floo root@<ip>
|
||||
floo = mkHost "floo" {
|
||||
system = "x86_64-linux";
|
||||
user = "matej";
|
||||
features = [
|
||||
"filedrop"
|
||||
"localisation"
|
||||
"nix-settings"
|
||||
"openssh"
|
||||
"remote-base"
|
||||
"shell"
|
||||
"tailscale"
|
||||
"zsh"
|
||||
];
|
||||
};
|
||||
|
||||
fortress = mkHost "fortress" {
|
||||
system = "x86_64-linux";
|
||||
user = "matej";
|
||||
features = [
|
||||
"bootloader"
|
||||
"desktop"
|
||||
"gnupg"
|
||||
"localisation"
|
||||
"networkmanager"
|
||||
"nix-settings"
|
||||
"sway"
|
||||
"udev"
|
||||
"zsh"
|
||||
];
|
||||
};
|
||||
|
||||
ephvm = mkHost "ephvm" {
|
||||
system = "x86_64-linux";
|
||||
user = "matej";
|
||||
features = [
|
||||
"claude"
|
||||
"dev"
|
||||
"docker"
|
||||
"git"
|
||||
"gnupg"
|
||||
"localisation"
|
||||
"neovim"
|
||||
"nix-settings"
|
||||
"openssh"
|
||||
"shell"
|
||||
"vm-guest"
|
||||
"zsh"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
5
flake/overlays.nix
Normal file
5
flake/overlays.nix
Normal file
@@ -0,0 +1,5 @@
|
||||
_:
|
||||
|
||||
{
|
||||
flake.overlays.default = _: _: { };
|
||||
}
|
||||
21
flake/packages.nix
Normal file
21
flake/packages.nix
Normal file
@@ -0,0 +1,21 @@
|
||||
{ inputs, ... }:
|
||||
|
||||
let
|
||||
my-lib = import ../lib { inherit (inputs.nixpkgs) lib; };
|
||||
in
|
||||
{
|
||||
perSystem =
|
||||
{ pkgs, system, ... }:
|
||||
{
|
||||
packages =
|
||||
import ../packages
|
||||
{
|
||||
inherit my-lib;
|
||||
inherit (inputs.nixpkgs) lib;
|
||||
}
|
||||
{
|
||||
inherit pkgs;
|
||||
pkgs-master = inputs.nixpkgs-master.legacyPackages.${system};
|
||||
};
|
||||
};
|
||||
}
|
||||
33
hosts/cube/configuration.nix
Normal file
33
hosts/cube/configuration.nix
Normal file
@@ -0,0 +1,33 @@
|
||||
{ inputs, ... }:
|
||||
{
|
||||
imports = [ inputs.disko.nixosModules.disko ];
|
||||
|
||||
disko.devices.disk.main = {
|
||||
type = "disk";
|
||||
device = "/dev/nvme0n1";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
esp = {
|
||||
size = "512M";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
};
|
||||
};
|
||||
root = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "ext4";
|
||||
mountpoint = "/";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
31
hosts/cube/hardware-configuration.nix
Normal file
31
hosts/cube/hardware-configuration.nix
Normal file
@@ -0,0 +1,31 @@
|
||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [
|
||||
"xhci_pci"
|
||||
"ahci"
|
||||
"nvme"
|
||||
"usb_storage"
|
||||
"sd_mod"
|
||||
"sdhci_pci"
|
||||
];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-intel" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
||||
119
hosts/ephvm/configuration.nix
Normal file
119
hosts/ephvm/configuration.nix
Normal file
@@ -0,0 +1,119 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
features.nix-settings.towerCache.enable = false;
|
||||
# no hardware firmware needed in a VM
|
||||
hardware.enableRedistributableFirmware = lib.mkForce false;
|
||||
hardware.wirelessRegulatoryDatabase = lib.mkForce false;
|
||||
|
||||
documentation.enable = false;
|
||||
environment.defaultPackages = [ ];
|
||||
|
||||
# qcow2, no channel copy; post-processed with parallel zstd on qcow2 v3
|
||||
# (~half the size of zlib v2, faster decompress)
|
||||
image.modules.qemu =
|
||||
{ config, modulesPath, ... }:
|
||||
{
|
||||
system.build.image = lib.mkForce (
|
||||
let
|
||||
rawImage = import (modulesPath + "/../lib/make-disk-image.nix") {
|
||||
inherit lib config pkgs;
|
||||
inherit (config.virtualisation) diskSize;
|
||||
inherit (config.image) baseName;
|
||||
format = "qcow2";
|
||||
copyChannel = false;
|
||||
partitionTableType = "legacy";
|
||||
};
|
||||
inherit (config.image) baseName;
|
||||
in
|
||||
pkgs.runCommand baseName { nativeBuildInputs = [ pkgs.qemu-utils ]; } ''
|
||||
mkdir -p $out
|
||||
# qemu-img caps -m at 16
|
||||
cores="''${NIX_BUILD_CORES:-4}"
|
||||
[ "$cores" -gt 0 ] || cores=4
|
||||
[ "$cores" -gt 16 ] && cores=16
|
||||
qemu-img convert \
|
||||
-f qcow2 \
|
||||
-O qcow2 \
|
||||
-c \
|
||||
-o compression_type=zstd \
|
||||
-m "$cores" \
|
||||
${rawImage}/${baseName}.qcow2 \
|
||||
$out/${baseName}.qcow2
|
||||
''
|
||||
);
|
||||
};
|
||||
|
||||
# auto-login on serial console
|
||||
services.getty.autologinUser = "matej";
|
||||
|
||||
# enable zsh in home-manager so starship init gets wired up
|
||||
home-manager.users.matej.programs.zsh = {
|
||||
enable = true;
|
||||
dotDir = "/home/matej/.config/zsh";
|
||||
shellAliases.dsp = "claude --dangerously-skip-permissions";
|
||||
};
|
||||
|
||||
home-manager.users.matej.programs.starship = {
|
||||
enable = true;
|
||||
settings = {
|
||||
add_newline = false;
|
||||
format = "$username$hostname$directory$character";
|
||||
hostname = {
|
||||
ssh_only = false;
|
||||
style = "bold blue";
|
||||
format = "[@$hostname]($style)";
|
||||
};
|
||||
username = {
|
||||
show_always = true;
|
||||
style_user = "bold blue";
|
||||
format = "[$user]($style)";
|
||||
};
|
||||
directory.format = " [$path]($style) ";
|
||||
character = {
|
||||
success_symbol = "[>](bold green)";
|
||||
error_symbol = "[>](bold red)";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
features.vm-guest.headless = true;
|
||||
features.vm-guest.automount = {
|
||||
enable = true;
|
||||
user = "matej";
|
||||
};
|
||||
features.neovim.dotfiles = inputs.nvim;
|
||||
|
||||
# ensure .config exists with correct ownership before automount
|
||||
systemd.tmpfiles.rules = [ "d /home/matej/.config 0700 matej users -" ];
|
||||
|
||||
# TODO:(@janezicmatej) replace ssh with virtio-console (hvc0) when qemu 11.0 lands
|
||||
# https://www.mail-archive.com/qemu-devel@nongnu.org/msg1162844.html
|
||||
# accept any ssh key (ephemeral localhost-only vm)
|
||||
services.openssh.settings.AuthorizedKeysCommand =
|
||||
let
|
||||
acceptKey = pkgs.writeShellScript "ephvm-accept-key" ''echo "$1 $2"'';
|
||||
in
|
||||
"${acceptKey} %t %k";
|
||||
services.openssh.settings.AuthorizedKeysCommandUser = "nobody";
|
||||
|
||||
# writable claude config via 9p
|
||||
fileSystems."/home/matej/.config/claude" = {
|
||||
device = "claude";
|
||||
fsType = "9p";
|
||||
options = [
|
||||
"trans=virtio"
|
||||
"version=9p2000.L"
|
||||
"nofail"
|
||||
"x-systemd.automount"
|
||||
];
|
||||
};
|
||||
|
||||
environment.sessionVariables.CLAUDE_CONFIG_DIR = "/home/matej/.config/claude";
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
22
hosts/ephvm/hardware-configuration.nix
Normal file
22
hosts/ephvm/hardware-configuration.nix
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
virtualisation.diskSize = 30720; # 30G
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-label/nixos";
|
||||
autoResize = true;
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
# image.modules (disk-image.nix) overrides boot loader per variant
|
||||
boot.loader.grub.device = lib.mkDefault "/dev/vda";
|
||||
}
|
||||
32
hosts/floo/configuration.nix
Normal file
32
hosts/floo/configuration.nix
Normal file
@@ -0,0 +1,32 @@
|
||||
{ inputs, ... }:
|
||||
{
|
||||
imports = [ inputs.disko.nixosModules.disko ];
|
||||
|
||||
features.filedrop.sopsFile = ../../secrets/floo.yaml;
|
||||
|
||||
boot.loader.grub.enable = true;
|
||||
|
||||
disko.devices.disk.main = {
|
||||
type = "disk";
|
||||
device = "/dev/sda";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
boot = {
|
||||
size = "1M";
|
||||
type = "EF02";
|
||||
};
|
||||
root = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "ext4";
|
||||
mountpoint = "/";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
37
hosts/floo/hardware-configuration.nix
Normal file
37
hosts/floo/hardware-configuration.nix
Normal file
@@ -0,0 +1,37 @@
|
||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [
|
||||
"ahci"
|
||||
"xhci_pci"
|
||||
"virtio_pci"
|
||||
"virtio_scsi"
|
||||
"sd_mod"
|
||||
"sr_mod"
|
||||
];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||
# still possible to use this option, but it's recommended to use it in conjunction
|
||||
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
|
||||
networking.useDHCP = lib.mkDefault true;
|
||||
# networking.interfaces.enp1s0.useDHCP = lib.mkDefault true;
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
}
|
||||
79
hosts/fortress/configuration.nix
Normal file
79
hosts/fortress/configuration.nix
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports = [
|
||||
inputs.disko.nixosModules.disko
|
||||
inputs.nixos-hardware.nixosModules.framework-16-amd-ai-300-series
|
||||
];
|
||||
|
||||
features.desktop = {
|
||||
apps.enable = false;
|
||||
internalCA.enable = false;
|
||||
};
|
||||
features.gnupg.yubikey.enable = true;
|
||||
|
||||
disko.devices.disk.main = {
|
||||
type = "disk";
|
||||
device = "/dev/sda";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
esp = {
|
||||
size = "512M";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
};
|
||||
};
|
||||
luks = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "luks";
|
||||
name = "cryptlvm";
|
||||
settings.allowDiscards = true;
|
||||
content = {
|
||||
type = "lvm_pv";
|
||||
vg = "vg";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
disko.devices.lvm_vg.vg = {
|
||||
type = "lvm_vg";
|
||||
lvs = {
|
||||
root = {
|
||||
size = "100%FREE";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "ext4";
|
||||
mountpoint = "/";
|
||||
};
|
||||
};
|
||||
swap = {
|
||||
size = "32G";
|
||||
content = {
|
||||
type = "swap";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.enable = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
google-chrome
|
||||
firefox
|
||||
vim
|
||||
];
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
30
hosts/fortress/hardware-configuration.nix
Normal file
30
hosts/fortress/hardware-configuration.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
hardware.firmware = [ pkgs.linux-firmware ];
|
||||
|
||||
boot.initrd.availableKernelModules = [
|
||||
"nvme"
|
||||
"xhci_pci"
|
||||
"thunderbolt"
|
||||
"usbhid"
|
||||
"uas"
|
||||
"sd_mod"
|
||||
];
|
||||
boot.initrd.kernelModules = [ "dm-snapshot" ];
|
||||
boot.kernelModules = [ "kvm-amd" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
||||
@@ -1,81 +1,42 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
options,
|
||||
userKeys,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
packages = inputs.self.outputs.packages.${pkgs.stdenv.hostPlatform.system};
|
||||
in
|
||||
|
||||
{
|
||||
imports = [
|
||||
inputs.nixos-hardware.nixosModules.framework-16-amd-ai-300-series
|
||||
inputs.stylix.nixosModules.stylix
|
||||
];
|
||||
|
||||
profiles.desktop.enable = true;
|
||||
|
||||
localisation = {
|
||||
timeZone = "Europe/Ljubljana";
|
||||
defaultLocale = "en_US.UTF-8";
|
||||
features.bootloader.plymouth.enable = true;
|
||||
features.desktop.bluetooth.enable = true;
|
||||
features.gnupg.yubikey.enable = true;
|
||||
features.udev = {
|
||||
ledger.enable = true;
|
||||
keyboard-zsa.enable = true;
|
||||
};
|
||||
features.power.resumeDevice = "/dev/disk/by-uuid/ff4750e7-3a9f-42c2-bb68-c458a6560540";
|
||||
|
||||
stylix = {
|
||||
enable = true;
|
||||
polarity = "dark";
|
||||
image = "${inputs.assets}/wallpaper.png";
|
||||
base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-material-dark-medium.yaml";
|
||||
};
|
||||
boot.kernelParams = [ "pcie_aspm.policy=powersupersave" ];
|
||||
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
|
||||
# WARN:(@janezicmatej) nix-ld for running pip-installed binaries outside nix, probably want to drop this
|
||||
programs.nix-ld.enable = true;
|
||||
programs.nix-ld.libraries = options.programs.nix-ld.libraries.default;
|
||||
|
||||
security.pki.certificateFiles = [ packages.ca-matheo-si ];
|
||||
services.gnome.gnome-keyring.enable = true;
|
||||
|
||||
services.teamviewer.enable = true;
|
||||
|
||||
programs.thunderbird.enable = true;
|
||||
programs._1password.enable = true;
|
||||
programs._1password-gui.enable = true;
|
||||
programs.firefox.enable = true;
|
||||
programs.steam = {
|
||||
enable = true;
|
||||
remotePlay.openFirewall = true;
|
||||
dedicatedServer.openFirewall = true;
|
||||
localNetworkGameTransfers.openFirewall = true;
|
||||
};
|
||||
|
||||
services.hardware.bolt.enable = true;
|
||||
hardware.keyboard.zsa.enable = true;
|
||||
hardware.ledger.enable = true;
|
||||
hardware.bluetooth.powerOnBoot = true;
|
||||
hardware.inputmodule.enable = true;
|
||||
|
||||
programs.nm-applet.enable = true;
|
||||
# NOTE:(@janezicmatej) disable wakeup for framework input modules to prevent spurious wakes
|
||||
services.udev.extraRules = lib.mkAfter ''
|
||||
SUBSYSTEM=="usb", DRIVERS=="usb", ATTRS{idVendor}=="32ac", ATTRS{idProduct}=="0012", ATTR{power/wakeup}="disabled"
|
||||
SUBSYSTEM=="usb", DRIVERS=="usb", ATTRS{idVendor}=="32ac", ATTRS{idProduct}=="0014", ATTR{power/wakeup}="disabled"
|
||||
'';
|
||||
|
||||
networking = {
|
||||
hostName = "fw16";
|
||||
networkmanager.enable = true;
|
||||
firewall.enable = false;
|
||||
nameservers = [
|
||||
"1.1.1.1"
|
||||
"8.8.8.8"
|
||||
];
|
||||
};
|
||||
|
||||
xdg.mime.defaultApplications = {
|
||||
"application/pdf" = "org.pwmt.zathura.desktop";
|
||||
};
|
||||
networking.firewall.enable = false;
|
||||
|
||||
system.stateVersion = "24.11";
|
||||
}
|
||||
|
||||
@@ -1,43 +1,15 @@
|
||||
{ lib, userKeys, ... }:
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
userKeys,
|
||||
...
|
||||
}:
|
||||
{
|
||||
openssh.enable = true;
|
||||
|
||||
features.nix-settings.towerCache.enable = false;
|
||||
image.modules.iso-installer = {
|
||||
isoImage.squashfsCompression = "zstd -Xcompression-level 6";
|
||||
};
|
||||
|
||||
fileSystems."/" = lib.mkDefault {
|
||||
device = "/dev/disk/by-label/nixos";
|
||||
fsType = "ext4";
|
||||
};
|
||||
boot.loader.grub.device = lib.mkDefault "/dev/sda";
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 22 ];
|
||||
|
||||
users = {
|
||||
groups.matej = {
|
||||
gid = 1000;
|
||||
};
|
||||
users.matej = {
|
||||
group = "matej";
|
||||
uid = 1000;
|
||||
isNormalUser = true;
|
||||
home = "/home/matej";
|
||||
createHome = true;
|
||||
password = "burek123";
|
||||
extraGroups = [
|
||||
"wheel"
|
||||
"users"
|
||||
];
|
||||
openssh.authorizedKeys.keys = userKeys.sshAuthorizedKeys or [ ];
|
||||
};
|
||||
};
|
||||
# live iso: passwordless login and sudo
|
||||
users.users.matej.initialHashedPassword = "";
|
||||
users.users.root.openssh.authorizedKeys.keys = userKeys.sshAuthorizedKeys;
|
||||
services.openssh.settings.PermitRootLogin = lib.mkForce "prohibit-password";
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
|
||||
system.stateVersion = "25.05";
|
||||
}
|
||||
|
||||
@@ -1,53 +1,36 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
options,
|
||||
userKeys,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports = [
|
||||
inputs.stylix.nixosModules.stylix
|
||||
inputs.lanzaboote.nixosModules.lanzaboote
|
||||
];
|
||||
|
||||
profiles.desktop.enable = true;
|
||||
|
||||
initrd-ssh = {
|
||||
enable = true;
|
||||
features.nix-settings.towerCache.enable = false;
|
||||
features.bootloader = {
|
||||
mode = "lanzaboote";
|
||||
plymouth.enable = true;
|
||||
};
|
||||
features.desktop.bluetooth.enable = true;
|
||||
features.gnupg.yubikey.enable = true;
|
||||
features.udev = {
|
||||
ledger.enable = true;
|
||||
keyboard-zsa.enable = true;
|
||||
};
|
||||
features.initrd-ssh = {
|
||||
networkModule = "r8169";
|
||||
authorizedKeys = userKeys.sshAuthorizedKeys;
|
||||
};
|
||||
|
||||
localisation = {
|
||||
timeZone = "Europe/Ljubljana";
|
||||
defaultLocale = "en_US.UTF-8";
|
||||
};
|
||||
# nix store signing
|
||||
sops.secrets.nix-signing-key.sopsFile = ../../secrets/tower.yaml;
|
||||
nix.settings.secret-key-files = [ config.sops.secrets.nix-signing-key.path ];
|
||||
|
||||
stylix = {
|
||||
enable = true;
|
||||
polarity = "dark";
|
||||
image = "${inputs.assets}/wallpaper.png";
|
||||
base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-material-dark-medium.yaml";
|
||||
};
|
||||
|
||||
# lanzaboote secure boot
|
||||
boot.kernelParams = [ "btusb.reset=1" ];
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
boot.loader.systemd-boot.enable = lib.mkForce false;
|
||||
boot.lanzaboote = {
|
||||
enable = true;
|
||||
pkiBundle = "/var/lib/sbctl";
|
||||
};
|
||||
# early kms so plymouth lands on amdgpu, not simpledrm
|
||||
hardware.amdgpu.initrd.enable = true;
|
||||
|
||||
services.udisks2.enable = true;
|
||||
|
||||
programs._1password.enable = true;
|
||||
programs._1password-gui.enable = true;
|
||||
|
||||
# higher sample rate for audio equipment
|
||||
services.pipewire.extraConfig.pipewire.adjust-sample-rate = {
|
||||
"context.properties" = {
|
||||
@@ -56,15 +39,5 @@
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
easyeffects
|
||||
];
|
||||
|
||||
networking.hostName = "tower";
|
||||
|
||||
xdg.mime.defaultApplications = {
|
||||
"application/pdf" = "org.pwmt.zathura.desktop";
|
||||
};
|
||||
|
||||
system.stateVersion = "25.05";
|
||||
}
|
||||
|
||||
29
justfile
29
justfile
@@ -33,6 +33,35 @@ build:
|
||||
iso:
|
||||
nixos-rebuild build-image --image-variant iso-installer --flake .#iso
|
||||
|
||||
# run ephemeral VM
|
||||
ephvm *ARGS:
|
||||
bash scripts/ephvm-run.sh {{ARGS}}
|
||||
|
||||
# ssh into running ephemeral VM
|
||||
ephvm-ssh port="2222":
|
||||
ssh -p {{port}} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null matej@localhost
|
||||
|
||||
# provision a host with nixos-anywhere
|
||||
provision host ip:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
tmpdir=$(mktemp -d)
|
||||
trap 'rm -rf "$tmpdir"' EXIT
|
||||
install -d -m 755 "$tmpdir/etc/ssh"
|
||||
ssh-keygen -t ed25519 -f "$tmpdir/etc/ssh/ssh_host_ed25519_key" -N ""
|
||||
age_key=$(ssh-to-age < "$tmpdir/etc/ssh/ssh_host_ed25519_key.pub")
|
||||
echo "age key: $age_key"
|
||||
echo "add this key to .sops.yaml, re-encrypt secrets, then press enter to continue"
|
||||
read -r
|
||||
nix run github:nix-community/nixos-anywhere -- --no-reboot --flake .#{{host}} --extra-files "$tmpdir" --generate-hardware-config nixos-generate-config ./hosts/{{host}}/hardware-configuration.nix root@{{ip}}
|
||||
echo "remove USB and press enter to reboot"
|
||||
read -r
|
||||
ssh root@{{ip}} reboot
|
||||
|
||||
# deploy config to a remote host
|
||||
deploy host remote=host:
|
||||
nixos-rebuild switch --flake .#{{host}} --target-host {{remote}} --sudo --ask-sudo-password
|
||||
|
||||
# garbage collect old generations
|
||||
clean:
|
||||
sudo nix-collect-garbage $(nix eval --raw -f ./nix.nix nix.gc.options)
|
||||
|
||||
@@ -8,52 +8,101 @@ name:
|
||||
{
|
||||
system,
|
||||
user ? null,
|
||||
features ? [ ],
|
||||
}:
|
||||
|
||||
let
|
||||
hostConfig = ../hosts/${name}/configuration.nix;
|
||||
hostHWConfig = ../hosts/${name}/hardware-configuration.nix;
|
||||
hasHWConfig = builtins.pathExists hostHWConfig;
|
||||
inherit (nixpkgs) lib;
|
||||
hasUser = user != null;
|
||||
|
||||
userKeys = if hasUser then import ../users/${user}/keys.nix else { };
|
||||
# path helpers
|
||||
featurePath =
|
||||
f:
|
||||
let
|
||||
file = ../features/${f}.nix;
|
||||
dir = ../features/${f};
|
||||
in
|
||||
if builtins.pathExists file then file else dir;
|
||||
userFeaturePath = u: ../features/user-${u}.nix;
|
||||
hostConfig = ../hosts/${name}/configuration.nix;
|
||||
hostHWConfig = ../hosts/${name}/hardware-configuration.nix;
|
||||
|
||||
# auto-import all nixos modules and profiles
|
||||
nixosModuleList = builtins.attrValues inputs.self.nixosModules;
|
||||
nixosProfileList = builtins.attrValues inputs.self.nixosProfiles;
|
||||
# auto-discover all features, excluding user-* and default.nix
|
||||
featureDir = builtins.readDir ../features;
|
||||
allFeatureNames = lib.pipe featureDir [
|
||||
(lib.filterAttrs (
|
||||
n: t:
|
||||
(t == "regular" && lib.hasSuffix ".nix" n && n != "default.nix" && !lib.hasPrefix "user-" n)
|
||||
|| (t == "directory" && builtins.pathExists ../features/${n}/default.nix)
|
||||
))
|
||||
builtins.attrNames
|
||||
(map (n: lib.removeSuffix ".nix" n))
|
||||
];
|
||||
|
||||
# auto-import all home-manager modules
|
||||
hmModuleList = builtins.attrValues inputs.self.homeManagerModules;
|
||||
# load all features unconditionally
|
||||
loadFeature =
|
||||
f:
|
||||
assert
|
||||
builtins.pathExists (featurePath f)
|
||||
|| throw "feature '${f}' not found at ${toString (featurePath f)}";
|
||||
import (featurePath f);
|
||||
|
||||
loadedFeatures = map loadFeature allFeatureNames;
|
||||
|
||||
# load user feature with path check
|
||||
userFeature =
|
||||
if hasUser then
|
||||
assert
|
||||
builtins.pathExists (userFeaturePath user)
|
||||
|| throw "user feature 'user-${user}' not found at ${toString (userFeaturePath user)}";
|
||||
import (userFeaturePath user)
|
||||
else
|
||||
null;
|
||||
|
||||
allFeatures = loadedFeatures ++ lib.optional (userFeature != null) userFeature;
|
||||
|
||||
# extract keys from user feature for specialArgs
|
||||
userKeys = if userFeature != null then (userFeature.keys or { }) else { };
|
||||
|
||||
# collect nixos and home modules from all features
|
||||
nixosMods = map (f: f.nixos) (builtins.filter (f: f ? nixos) allFeatures);
|
||||
homeMods = map (f: f.home) (builtins.filter (f: f ? home) allFeatures);
|
||||
|
||||
# translate features list to enable flags
|
||||
featureEnableModule =
|
||||
{ lib, ... }:
|
||||
{
|
||||
config.features = lib.genAttrs features (_: {
|
||||
enable = true;
|
||||
});
|
||||
};
|
||||
in
|
||||
nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [
|
||||
../nix.nix
|
||||
inputs.sops-nix.nixosModules.sops
|
||||
inputs.stylix.nixosModules.stylix
|
||||
|
||||
{ nixpkgs.overlays = overlays; }
|
||||
{ nixpkgs.config.allowUnfree = true; }
|
||||
{ networking.hostName = name; }
|
||||
|
||||
featureEnableModule
|
||||
hostConfig
|
||||
]
|
||||
++ nixpkgs.lib.optional hasHWConfig hostHWConfig
|
||||
++ nixosModuleList
|
||||
++ nixosProfileList
|
||||
++ nixpkgs.lib.optional (
|
||||
hasUser && builtins.pathExists ../users/${user}/nixos.nix
|
||||
) ../users/${user}/nixos.nix
|
||||
++ [
|
||||
++ lib.optional (builtins.pathExists hostHWConfig) hostHWConfig
|
||||
++ nixosMods
|
||||
++ lib.optionals hasUser [
|
||||
inputs.home-manager.nixosModules.home-manager
|
||||
{
|
||||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
home-manager.backupFileExtension = "backup";
|
||||
home-manager.users = nixpkgs.lib.mkIf hasUser {
|
||||
${user} = import ../users/${user}/home-manager.nix;
|
||||
};
|
||||
home-manager.sharedModules = hmModuleList;
|
||||
home-manager.users.${user}.imports = homeMods;
|
||||
home-manager.extraSpecialArgs = { inherit inputs; };
|
||||
}
|
||||
];
|
||||
specialArgs = { inherit inputs userKeys; };
|
||||
specialArgs = {
|
||||
inherit inputs userKeys user;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
packages = inputs.self.outputs.packages.${pkgs.stdenv.hostPlatform.system};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
claude = {
|
||||
enable = lib.mkEnableOption "claude code";
|
||||
package = lib.mkPackageOption pkgs "claude-code" { };
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.claude.enable {
|
||||
home.packages = [
|
||||
config.claude.package
|
||||
packages.todo-mcp
|
||||
pkgs.mcp-nixos
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
{ lib, my-lib }: args: (my-lib.autoDir ./.)
|
||||
@@ -1,36 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
desktop.enable = lib.mkEnableOption "desktop gui applications";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.desktop.enable {
|
||||
home.packages = with pkgs; [
|
||||
ghostty
|
||||
google-chrome
|
||||
zathura
|
||||
pavucontrol
|
||||
bolt-launcher
|
||||
libnotify
|
||||
bibata-cursors
|
||||
vesktop
|
||||
rocketchat-desktop
|
||||
telegram-desktop
|
||||
slack
|
||||
jellyfin-media-player
|
||||
cider-2
|
||||
protonmail-bridge
|
||||
ledger-live-desktop
|
||||
];
|
||||
|
||||
services.dunst.enable = true;
|
||||
|
||||
home.file.".assets".source = inputs.assets;
|
||||
};
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
packages = inputs.self.outputs.packages.${pkgs.stdenv.hostPlatform.system};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
dev.enable = lib.mkEnableOption "development tools";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.dev.enable {
|
||||
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
|
||||
];
|
||||
|
||||
programs.direnv = {
|
||||
enable = true;
|
||||
nix-direnv.enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
neovim = {
|
||||
enable = lib.mkEnableOption "neovim nightly with lsp support";
|
||||
package = lib.mkPackageOption pkgs "neovim" { };
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.neovim.enable {
|
||||
stylix.targets.neovim.enable = false;
|
||||
programs.neovim = {
|
||||
enable = true;
|
||||
vimAlias = true;
|
||||
defaultEditor = true;
|
||||
inherit (config.neovim) package;
|
||||
|
||||
extraPackages = with pkgs; [
|
||||
# runtime deps
|
||||
gcc
|
||||
luajit
|
||||
nodejs_22
|
||||
tree-sitter
|
||||
gnumake
|
||||
osc
|
||||
|
||||
# search and diff
|
||||
fd
|
||||
ripgrep
|
||||
bat
|
||||
delta
|
||||
|
||||
# language servers
|
||||
pyright
|
||||
typescript-language-server
|
||||
lua-language-server
|
||||
gopls
|
||||
nil
|
||||
nixd
|
||||
|
||||
# formatters
|
||||
nixpkgs-fmt
|
||||
stylua
|
||||
];
|
||||
|
||||
extraWrapperArgs = [
|
||||
"--suffix"
|
||||
"LD_LIBRARY_PATH"
|
||||
":"
|
||||
"${lib.makeLibraryPath [ pkgs.stdenv.cc.cc.lib ]}"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
shell.enable = lib.mkEnableOption "shell utilities";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.shell.enable {
|
||||
home.packages = with pkgs; [
|
||||
starship
|
||||
fzf
|
||||
htop
|
||||
jc
|
||||
jq
|
||||
openssl
|
||||
pv
|
||||
ripgrep
|
||||
fd
|
||||
tmux
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
{ lib, my-lib }: args: (my-lib.autoDir ./.)
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
desktop = {
|
||||
enable = lib.mkEnableOption "base desktop environment";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.desktop.enable {
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
|
||||
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
|
||||
maple-mono.NF
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
gnupg = {
|
||||
enable = lib.mkEnableOption "GnuPG agent with SSH support";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.gnupg.enable {
|
||||
programs.gnupg.agent = {
|
||||
enable = true;
|
||||
enableSSHSupport = true;
|
||||
enableExtraSocket = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
# generate host keys for new machines: ./scripts/initrd-ssh-keygen.sh
|
||||
keyDir = "/etc/secrets/initrd";
|
||||
|
||||
mkIpString =
|
||||
{
|
||||
address,
|
||||
gateway,
|
||||
netmask,
|
||||
interface,
|
||||
...
|
||||
}:
|
||||
"${address}::${gateway}:${netmask}::${interface}:none";
|
||||
in
|
||||
{
|
||||
options = {
|
||||
initrd-ssh = {
|
||||
enable = lib.mkEnableOption "SSH in initrd for remote LUKS unlock";
|
||||
|
||||
ip = {
|
||||
enable = lib.mkEnableOption "static IP for initrd (otherwise DHCP)";
|
||||
|
||||
address = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "10.222.0.247";
|
||||
};
|
||||
|
||||
gateway = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "10.222.0.1";
|
||||
};
|
||||
|
||||
netmask = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "255.255.255.0";
|
||||
};
|
||||
|
||||
interface = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "enp5s0";
|
||||
};
|
||||
};
|
||||
|
||||
authorizedKeys = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
networkModule = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "r8169";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.initrd-ssh.enable {
|
||||
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
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
localisation = {
|
||||
enable = lib.mkEnableOption "localisation defaults";
|
||||
|
||||
timeZone = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
defaultLocale = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.localisation.enable {
|
||||
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;
|
||||
};
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
nvidia.enable = lib.mkEnableOption "NVIDIA GPU support";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.nvidia.enable {
|
||||
hardware.graphics.enable = true;
|
||||
|
||||
services.xserver.videoDrivers = [ "nvidia" ];
|
||||
|
||||
hardware.nvidia = {
|
||||
modesetting.enable = true;
|
||||
open = true;
|
||||
nvidiaSettings = true;
|
||||
package = config.boot.kernelPackages.nvidiaPackages.stable;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
openssh = {
|
||||
enable = lib.mkEnableOption "hardened SSH server";
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 22;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.openssh.enable {
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
ports = [ config.openssh.port ];
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
AllowUsers = null;
|
||||
PermitRootLogin = "no";
|
||||
StreamLocalBindUnlink = "yes";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
printing = {
|
||||
enable = lib.mkEnableOption "CUPS printing with Avahi discovery";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.printing.enable {
|
||||
services.printing.enable = true;
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
nssmdns4 = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
|
||||
options = {
|
||||
sway = {
|
||||
enable = lib.mkEnableOption "enable sway module";
|
||||
cmdFlags = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.sway.enable {
|
||||
programs.sway = {
|
||||
enable = true;
|
||||
package = pkgs.swayfx;
|
||||
wrapperFeatures.gtk = true;
|
||||
extraOptions = config.sway.cmdFlags;
|
||||
extraSessionCommands = ''
|
||||
# fix for java awt apps not rendering
|
||||
export _JAVA_AWT_WM_NONREPARENTING=1
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
brightnessctl
|
||||
foot
|
||||
grim
|
||||
pulseaudio
|
||||
swayidle
|
||||
# use swaylock-effects instead of swaylock
|
||||
swaylock-effects
|
||||
wmenu
|
||||
slurp
|
||||
wofi
|
||||
wl-clipboard
|
||||
wob
|
||||
pamixer
|
||||
wlsunset
|
||||
flameshot
|
||||
waybar
|
||||
wayland-pipewire-idle-inhibit
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
tuigreet = {
|
||||
enable = lib.mkEnableOption "greetd with tuigreet";
|
||||
|
||||
command = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.tuigreet.enable {
|
||||
services.greetd = {
|
||||
enable = true;
|
||||
useTextGreeter = true;
|
||||
settings = {
|
||||
default_session = {
|
||||
command = pkgs.writeShellScript "tuigreet-session" ''
|
||||
${pkgs.util-linux}/bin/setterm --blank 1 --powersave powerdown --powerdown 1
|
||||
exec ${pkgs.tuigreet}/bin/tuigreet --time --remember --cmd ${config.tuigreet.command}
|
||||
'';
|
||||
user = "greeter";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
workstation = {
|
||||
enable = lib.mkEnableOption "workstation utilities";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.workstation.enable {
|
||||
virtualisation.docker = {
|
||||
enable = true;
|
||||
logDriver = "json-file";
|
||||
};
|
||||
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
useRoutingFeatures = "both";
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
smartmontools
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
|
||||
options = {
|
||||
yubikey = {
|
||||
enable = lib.mkEnableOption "enable yubikey module";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.yubikey.enable {
|
||||
environment.systemPackages = with pkgs; [
|
||||
yubikey-personalization
|
||||
yubikey-manager
|
||||
];
|
||||
|
||||
services.pcscd.enable = true;
|
||||
};
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
zsh = {
|
||||
enable = lib.mkEnableOption "zsh with ZDOTDIR in ~/.config/zsh";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.zsh.enable {
|
||||
programs.zsh.enable = true;
|
||||
environment.etc."zshenv".text = ''
|
||||
export ZDOTDIR=$HOME/.config/zsh
|
||||
'';
|
||||
};
|
||||
}
|
||||
10
nix.nix
10
nix.nix
@@ -7,6 +7,16 @@
|
||||
];
|
||||
download-buffer-size = 2 * 1024 * 1024 * 1024;
|
||||
warn-dirty = false;
|
||||
substituters = [
|
||||
"https://cache.nixos.org"
|
||||
"https://nix-community.cachix.org?priority=45"
|
||||
"http://tower:5000?priority=50"
|
||||
];
|
||||
trusted-public-keys = [
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
"matej.nix-1:TdbemLVYblvAxqJcwb3mVKmmr3cfzXbMcZHE5ILnZDE="
|
||||
];
|
||||
};
|
||||
|
||||
gc = {
|
||||
|
||||
@@ -19,6 +19,20 @@ pkgs.rustPlatform.buildRustPackage {
|
||||
|
||||
buildType = "debug";
|
||||
|
||||
nativeBuildInputs = [ pkgs.installShellFiles ];
|
||||
|
||||
preBuild = ''
|
||||
mkdir -p completions
|
||||
'';
|
||||
|
||||
SHELL_COMPLETIONS_DIR = "completions";
|
||||
|
||||
postInstall = ''
|
||||
installShellCompletion --bash completions/ahab.bash
|
||||
installShellCompletion --zsh completions/_ahab
|
||||
installShellCompletion --fish completions/ahab.fish
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "ahab";
|
||||
homepage = "https://git.janezic.dev/janezicmatej/ahab";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p curl jq nix-prefetch
|
||||
# shellcheck shell=bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
@@ -12,24 +13,28 @@ extract_hash() {
|
||||
sed 's/\x1b\[[0-9;]*m//g' | grep 'got:' | tail -1 | grep -oP 'sha256-[A-Za-z0-9+/]+='
|
||||
}
|
||||
|
||||
main() {
|
||||
echo "fetching latest version..."
|
||||
LATEST=$(curl -sf "https://git.janezic.dev/api/v1/repos/janezicmatej/ahab/tags?limit=1" | jq -r '.[0].name')
|
||||
CURRENT=$(grep 'version = ' "$PKG_FILE" | head -1 | sed 's/.*"\(.*\)".*/\1/')
|
||||
local latest current
|
||||
latest=$(curl -sf "https://git.janezic.dev/api/v1/repos/janezicmatej/ahab/tags?limit=1" | jq -r '.[0].name')
|
||||
current=$(grep 'version = ' "$PKG_FILE" | head -1 | sed 's/.*"\(.*\)".*/\1/')
|
||||
|
||||
if [[ "$CURRENT" == "$LATEST" ]]; then
|
||||
echo "ahab already at $LATEST"
|
||||
exit 0
|
||||
if [[ "$current" == "$latest" ]]; then
|
||||
echo "ahab already at $latest"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "updating ahab: $CURRENT -> $LATEST"
|
||||
echo "updating ahab: $current -> $latest"
|
||||
|
||||
echo " prefetching source..."
|
||||
BASE32=$(nix-prefetch-url --unpack "https://git.janezic.dev/janezicmatej/ahab/archive/${LATEST}.tar.gz" 2>/dev/null)
|
||||
SRC_HASH=$(nix hash convert --to sri "sha256:$BASE32")
|
||||
echo " source: $SRC_HASH"
|
||||
local base32 src_hash
|
||||
base32=$(nix-prefetch-url --unpack "https://git.janezic.dev/janezicmatej/ahab/archive/${latest}.tar.gz" 2>/dev/null)
|
||||
src_hash=$(nix hash convert --to sri "sha256:$base32")
|
||||
echo " source: $src_hash"
|
||||
|
||||
echo " computing cargo hash..."
|
||||
BUILD_OUTPUT=$(nix build --no-link --impure --expr "
|
||||
local build_output cargo_hash
|
||||
build_output=$(nix build --no-link --impure --expr "
|
||||
let
|
||||
pkgs = (builtins.getFlake \"path:$ROOT_DIR\").inputs.nixpkgs.legacyPackages.\${builtins.currentSystem};
|
||||
in pkgs.rustPlatform.fetchCargoVendor {
|
||||
@@ -37,26 +42,30 @@ BUILD_OUTPUT=$(nix build --no-link --impure --expr "
|
||||
domain = \"git.janezic.dev\";
|
||||
owner = \"janezicmatej\";
|
||||
repo = \"ahab\";
|
||||
rev = \"$LATEST\";
|
||||
hash = \"$SRC_HASH\";
|
||||
rev = \"$latest\";
|
||||
hash = \"$src_hash\";
|
||||
};
|
||||
hash = \"\";
|
||||
}
|
||||
" 2>&1) || true
|
||||
CARGO_HASH=$(echo "$BUILD_OUTPUT" | extract_hash) || true
|
||||
cargo_hash=$(echo "$build_output" | extract_hash) || true
|
||||
|
||||
if [[ -z "$CARGO_HASH" ]]; then
|
||||
echo " error: failed to compute cargo hash"
|
||||
echo "$BUILD_OUTPUT"
|
||||
if [[ -z "$cargo_hash" ]]; then
|
||||
echo "error: failed to compute cargo hash" >&2
|
||||
echo "$build_output" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo " cargo: $CARGO_HASH"
|
||||
echo " cargo: $cargo_hash"
|
||||
|
||||
OLD_SRC=$(grep 'sha256 = ' "$PKG_FILE" | grep -oP 'sha256-[A-Za-z0-9+/]+=')
|
||||
OLD_CARGO=$(grep 'cargoHash = ' "$PKG_FILE" | grep -oP 'sha256-[A-Za-z0-9+/]+=')
|
||||
local old_src old_cargo
|
||||
old_src=$(grep 'sha256 = ' "$PKG_FILE" | grep -oP 'sha256-[A-Za-z0-9+/]+=')
|
||||
old_cargo=$(grep 'cargoHash = ' "$PKG_FILE" | grep -oP 'sha256-[A-Za-z0-9+/]+=')
|
||||
|
||||
sed -i "s|version = \"$CURRENT\"|version = \"$LATEST\"|" "$PKG_FILE"
|
||||
sed -i "s|$OLD_SRC|$SRC_HASH|" "$PKG_FILE"
|
||||
sed -i "s|$OLD_CARGO|$CARGO_HASH|" "$PKG_FILE"
|
||||
sed -i "s|version = \"$current\"|version = \"$latest\"|" "$PKG_FILE"
|
||||
sed -i "s|$old_src|$src_hash|" "$PKG_FILE"
|
||||
sed -i "s|$old_cargo|$cargo_hash|" "$PKG_FILE"
|
||||
|
||||
echo "ahab updated to $LATEST"
|
||||
echo "ahab updated to $latest"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
91
packages/claude-code/package.nix
Normal file
91
packages/claude-code/package.nix
Normal file
@@ -0,0 +1,91 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (pkgs) stdenv lib;
|
||||
version = "2.1.116";
|
||||
|
||||
# upstream ships platform-native binaries as separate npm packages under
|
||||
# @anthropic-ai/claude-code-<platform>; the wrapper package is just a
|
||||
# postinstall shim that copies the matching one into place
|
||||
sources = {
|
||||
"x86_64-linux" = {
|
||||
slug = "linux-x64";
|
||||
hash = "sha256-QEjJ4CRk35TubDNW02Dzcu+EMRLLndJUXJeP3BFT3b8=";
|
||||
};
|
||||
"aarch64-linux" = {
|
||||
slug = "linux-arm64";
|
||||
hash = "sha256-/Hqp8GQx8Hub8K4w0Fnx/AksksY61vRC44XxrJVwF5w=";
|
||||
};
|
||||
"x86_64-darwin" = {
|
||||
slug = "darwin-x64";
|
||||
hash = "sha256-O3J/ew2fWbUQePs6tHEhK0Q9E3Mx/BDSL7b7NL3FRc8=";
|
||||
};
|
||||
"aarch64-darwin" = {
|
||||
slug = "darwin-arm64";
|
||||
hash = "sha256-O41sf7b05SJfXVjszMeTp838mja+PgZ+aEKykLsHeNo=";
|
||||
};
|
||||
};
|
||||
|
||||
source =
|
||||
sources.${stdenv.hostPlatform.system}
|
||||
or (throw "claude-code: unsupported system ${stdenv.hostPlatform.system}");
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
pname = "claude-code";
|
||||
inherit version;
|
||||
|
||||
src = pkgs.fetchzip {
|
||||
url = "https://registry.npmjs.org/@anthropic-ai/claude-code-${source.slug}/-/claude-code-${source.slug}-${version}.tgz";
|
||||
inherit (source) hash;
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.makeWrapper
|
||||
]
|
||||
++ lib.optionals stdenv.hostPlatform.isLinux [ pkgs.patchelf ];
|
||||
|
||||
dontBuild = true;
|
||||
dontConfigure = true;
|
||||
dontStrip = true;
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
install -Dm755 claude $out/bin/claude
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
# NOTE:(@janezicmatej) upstream is a bun single-file-executable; the
|
||||
# embedded script payload sits at the tail of the ELF, so autoPatchelfHook's
|
||||
# section-layout changes corrupt it — only the interpreter can be rewritten
|
||||
postFixup =
|
||||
lib.optionalString stdenv.hostPlatform.isLinux ''
|
||||
patchelf --set-interpreter ${stdenv.cc.bintools.dynamicLinker} $out/bin/claude
|
||||
''
|
||||
+ ''
|
||||
wrapProgram $out/bin/claude \
|
||||
--set DISABLE_AUTOUPDATER 1 \
|
||||
--set-default FORCE_AUTOUPDATE_PLUGINS 1 \
|
||||
--set DISABLE_INSTALLATION_CHECKS 1 \
|
||||
--unset DEV \
|
||||
--prefix PATH : ${
|
||||
lib.makeBinPath (
|
||||
[
|
||||
pkgs.procps
|
||||
]
|
||||
++ lib.optionals stdenv.hostPlatform.isLinux [
|
||||
pkgs.bubblewrap
|
||||
pkgs.socat
|
||||
]
|
||||
)
|
||||
}
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster";
|
||||
homepage = "https://github.com/anthropics/claude-code";
|
||||
downloadPage = "https://www.npmjs.com/package/@anthropic-ai/claude-code";
|
||||
license = lib.licenses.unfree;
|
||||
mainProgram = "claude";
|
||||
platforms = lib.attrNames sources;
|
||||
};
|
||||
}
|
||||
53
packages/claude-code/update.sh
Executable file
53
packages/claude-code/update.sh
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p curl jq nix
|
||||
# shellcheck shell=bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PKG_FILE="$SCRIPT_DIR/package.nix"
|
||||
|
||||
# keep in sync with the `sources` attrset in package.nix
|
||||
PLATFORMS=(linux-x64 linux-arm64 darwin-x64 darwin-arm64)
|
||||
|
||||
prefetch() {
|
||||
local url="$1"
|
||||
nix --extra-experimental-features 'nix-command flakes' \
|
||||
store prefetch-file --unpack --json "$url" 2>/dev/null | jq -r '.hash'
|
||||
}
|
||||
|
||||
main() {
|
||||
echo "fetching latest version from npm..."
|
||||
local latest current
|
||||
latest=$(curl -sf "https://registry.npmjs.org/@anthropic-ai/claude-code/latest" | jq -r '.version')
|
||||
current=$(grep 'version = ' "$PKG_FILE" | head -1 | sed 's/.*"\(.*\)".*/\1/')
|
||||
|
||||
if [[ "$current" == "$latest" ]]; then
|
||||
echo "claude-code already at $latest"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "updating claude-code: $current -> $latest"
|
||||
|
||||
sed -i "s|version = \"$current\"|version = \"$latest\"|" "$PKG_FILE"
|
||||
|
||||
local slug url new_hash old_hash
|
||||
for slug in "${PLATFORMS[@]}"; do
|
||||
url="https://registry.npmjs.org/@anthropic-ai/claude-code-${slug}/-/claude-code-${slug}-${latest}.tgz"
|
||||
echo " prefetching $slug..."
|
||||
new_hash=$(prefetch "$url")
|
||||
old_hash=$(awk -v slug="$slug" '
|
||||
$0 ~ "slug = \"" slug "\";" { found=1; next }
|
||||
found && /hash = "sha256-/ {
|
||||
match($0, /sha256-[A-Za-z0-9+\/]+=*/)
|
||||
print substr($0, RSTART, RLENGTH)
|
||||
exit
|
||||
}
|
||||
' "$PKG_FILE")
|
||||
sed -i "s|$old_hash|$new_hash|" "$PKG_FILE"
|
||||
echo " $new_hash"
|
||||
done
|
||||
|
||||
echo "claude-code updated to $latest"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -26,6 +26,15 @@ pkgs.buildGoModule.override
|
||||
"-X go.tkw01536.de/ggman.buildVersion=${version}"
|
||||
];
|
||||
|
||||
nativeBuildInputs = [ pkgs.installShellFiles ];
|
||||
|
||||
postInstall = ''
|
||||
installShellCompletion --cmd ggman \
|
||||
--bash <($out/bin/ggman completion bash) \
|
||||
--zsh <($out/bin/ggman completion zsh) \
|
||||
--fish <($out/bin/ggman completion fish)
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Manager for all your local git repositories";
|
||||
homepage = "https://github.com/tkw1536/ggman";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p curl jq nix-prefetch
|
||||
# shellcheck shell=bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
@@ -12,52 +13,60 @@ extract_hash() {
|
||||
sed 's/\x1b\[[0-9;]*m//g' | grep 'got:' | tail -1 | grep -oP 'sha256-[A-Za-z0-9+/]+='
|
||||
}
|
||||
|
||||
main() {
|
||||
echo "fetching latest tag..."
|
||||
LATEST=$(curl -sf "https://api.github.com/repos/tkw1536/ggman/tags?per_page=1" | jq -r '.[0].name')
|
||||
CURRENT=$(grep 'version = ' "$PKG_FILE" | head -1 | sed 's/.*"\(.*\)".*/\1/')
|
||||
local latest current
|
||||
latest=$(curl -sf "https://api.github.com/repos/tkw1536/ggman/tags?per_page=1" | jq -r '.[0].name')
|
||||
current=$(grep 'version = ' "$PKG_FILE" | head -1 | sed 's/.*"\(.*\)".*/\1/')
|
||||
|
||||
if [[ "$CURRENT" == "$LATEST" ]]; then
|
||||
echo "ggman already at $LATEST"
|
||||
exit 0
|
||||
if [[ "$current" == "$latest" ]]; then
|
||||
echo "ggman already at $latest"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "updating ggman: $CURRENT -> $LATEST"
|
||||
echo "updating ggman: $current -> $latest"
|
||||
|
||||
echo " prefetching source..."
|
||||
BASE32=$(nix-prefetch-url --unpack "https://github.com/tkw1536/ggman/archive/${LATEST}.tar.gz" 2>/dev/null)
|
||||
SRC_HASH=$(nix hash convert --to sri "sha256:$BASE32")
|
||||
echo " source: $SRC_HASH"
|
||||
local base32 src_hash
|
||||
base32=$(nix-prefetch-url --unpack "https://github.com/tkw1536/ggman/archive/${latest}.tar.gz" 2>/dev/null)
|
||||
src_hash=$(nix hash convert --to sri "sha256:$base32")
|
||||
echo " source: $src_hash"
|
||||
|
||||
echo " computing vendor hash..."
|
||||
BUILD_OUTPUT=$(nix build --no-link --impure --expr "
|
||||
local build_output vendor_hash
|
||||
build_output=$(nix build --no-link --impure --expr "
|
||||
let
|
||||
pkgs = (builtins.getFlake \"path:$ROOT_DIR\").inputs.nixpkgs-master.legacyPackages.\${builtins.currentSystem};
|
||||
in (pkgs.buildGoModule.override { go = pkgs.go_1_26; } {
|
||||
pname = \"ggman\";
|
||||
version = \"$LATEST\";
|
||||
version = \"$latest\";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = \"tkw1536\";
|
||||
repo = \"ggman\";
|
||||
rev = \"$LATEST\";
|
||||
hash = \"$SRC_HASH\";
|
||||
rev = \"$latest\";
|
||||
hash = \"$src_hash\";
|
||||
};
|
||||
vendorHash = \"\";
|
||||
}).goModules
|
||||
" 2>&1) || true
|
||||
VENDOR_HASH=$(echo "$BUILD_OUTPUT" | extract_hash) || true
|
||||
vendor_hash=$(echo "$build_output" | extract_hash) || true
|
||||
|
||||
if [[ -z "$VENDOR_HASH" ]]; then
|
||||
echo " error: failed to compute vendor hash"
|
||||
echo "$BUILD_OUTPUT"
|
||||
if [[ -z "$vendor_hash" ]]; then
|
||||
echo "error: failed to compute vendor hash" >&2
|
||||
echo "$build_output" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo " vendor: $VENDOR_HASH"
|
||||
echo " vendor: $vendor_hash"
|
||||
|
||||
OLD_SRC=$(grep 'sha256 = ' "$PKG_FILE" | grep -oP 'sha256-[A-Za-z0-9+/]+=')
|
||||
OLD_VENDOR=$(grep 'vendorHash = ' "$PKG_FILE" | grep -oP 'sha256-[A-Za-z0-9+/]+=')
|
||||
local old_src old_vendor
|
||||
old_src=$(grep 'sha256 = ' "$PKG_FILE" | grep -oP 'sha256-[A-Za-z0-9+/]+=')
|
||||
old_vendor=$(grep 'vendorHash = ' "$PKG_FILE" | grep -oP 'sha256-[A-Za-z0-9+/]+=')
|
||||
|
||||
sed -i "s|version = \"$CURRENT\"|version = \"$LATEST\"|" "$PKG_FILE"
|
||||
sed -i "s|$OLD_SRC|$SRC_HASH|" "$PKG_FILE"
|
||||
sed -i "s|$OLD_VENDOR|$VENDOR_HASH|" "$PKG_FILE"
|
||||
sed -i "s|version = \"$current\"|version = \"$latest\"|" "$PKG_FILE"
|
||||
sed -i "s|$old_src|$src_hash|" "$PKG_FILE"
|
||||
sed -i "s|$old_vendor|$vendor_hash|" "$PKG_FILE"
|
||||
|
||||
echo "ggman updated to $LATEST"
|
||||
echo "ggman updated to $latest"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
version = "v0.3.1";
|
||||
in
|
||||
pkgs.rustPlatform.buildRustPackage {
|
||||
pname = "todo-mcp";
|
||||
inherit version;
|
||||
|
||||
src = pkgs.fetchFromGitea {
|
||||
domain = "git.janezic.dev";
|
||||
owner = "janezicmatej";
|
||||
repo = "todo-mcp";
|
||||
rev = version;
|
||||
sha256 = "sha256-FLsPatHeWcDMLaGZS91aaXtZEful5frN2pqZkQN9vNs=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-gdR4p5LIEMGBV3ikuuRZ5R8CYIjE1K2OnMJm7yo18Nw=";
|
||||
|
||||
nativeBuildInputs = [ pkgs.installShellFiles ];
|
||||
|
||||
preBuild = ''
|
||||
mkdir -p completions
|
||||
'';
|
||||
|
||||
SHELL_COMPLETIONS_DIR = "completions";
|
||||
|
||||
postInstall = ''
|
||||
installShellCompletion --bash completions/todo-mcp.bash
|
||||
installShellCompletion --zsh completions/_todo-mcp
|
||||
installShellCompletion --fish completions/todo-mcp.fish
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "simple todo cli with mcp server for ai integration";
|
||||
homepage = "https://git.janezic.dev/janezicmatej/todo-mcp";
|
||||
maintainers = [ ];
|
||||
};
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p curl jq nix-prefetch
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
PKG_FILE="$SCRIPT_DIR/package.nix"
|
||||
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
extract_hash() {
|
||||
sed 's/\x1b\[[0-9;]*m//g' | grep 'got:' | tail -1 | grep -oP 'sha256-[A-Za-z0-9+/]+='
|
||||
}
|
||||
|
||||
echo "fetching latest version..."
|
||||
LATEST=$(curl -sf "https://git.janezic.dev/api/v1/repos/janezicmatej/todo-mcp/tags?limit=1" | jq -r '.[0].name')
|
||||
CURRENT=$(grep 'version = ' "$PKG_FILE" | head -1 | sed 's/.*"\(.*\)".*/\1/')
|
||||
|
||||
if [[ "$CURRENT" == "$LATEST" ]]; then
|
||||
echo "todo-mcp already at $LATEST"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "updating todo-mcp: $CURRENT -> $LATEST"
|
||||
|
||||
echo " prefetching source..."
|
||||
BASE32=$(nix-prefetch-url --unpack "https://git.janezic.dev/janezicmatej/todo-mcp/archive/${LATEST}.tar.gz" 2>/dev/null)
|
||||
SRC_HASH=$(nix hash convert --to sri "sha256:$BASE32")
|
||||
echo " source: $SRC_HASH"
|
||||
|
||||
echo " computing cargo hash..."
|
||||
BUILD_OUTPUT=$(nix build --no-link --impure --expr "
|
||||
let
|
||||
pkgs = (builtins.getFlake \"path:$ROOT_DIR\").inputs.nixpkgs.legacyPackages.\${builtins.currentSystem};
|
||||
in pkgs.rustPlatform.fetchCargoVendor {
|
||||
src = pkgs.fetchFromGitea {
|
||||
domain = \"git.janezic.dev\";
|
||||
owner = \"janezicmatej\";
|
||||
repo = \"todo-mcp\";
|
||||
rev = \"$LATEST\";
|
||||
hash = \"$SRC_HASH\";
|
||||
};
|
||||
hash = \"\";
|
||||
}
|
||||
" 2>&1) || true
|
||||
CARGO_HASH=$(echo "$BUILD_OUTPUT" | extract_hash) || true
|
||||
|
||||
if [[ -z "$CARGO_HASH" ]]; then
|
||||
echo " error: failed to compute cargo hash"
|
||||
echo "$BUILD_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
echo " cargo: $CARGO_HASH"
|
||||
|
||||
OLD_SRC=$(grep 'sha256 = ' "$PKG_FILE" | grep -oP 'sha256-[A-Za-z0-9+/]+=')
|
||||
OLD_CARGO=$(grep 'cargoHash = ' "$PKG_FILE" | grep -oP 'sha256-[A-Za-z0-9+/]+=')
|
||||
|
||||
sed -i "s|version = \"$CURRENT\"|version = \"$LATEST\"|" "$PKG_FILE"
|
||||
sed -i "s|$OLD_SRC|$SRC_HASH|" "$PKG_FILE"
|
||||
sed -i "s|$OLD_CARGO|$CARGO_HASH|" "$PKG_FILE"
|
||||
|
||||
echo "todo-mcp updated to $LATEST"
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
profiles.base.enable = lib.mkEnableOption "base profile for all machines";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.profiles.base.enable {
|
||||
openssh.enable = lib.mkDefault true;
|
||||
zsh.enable = lib.mkDefault true;
|
||||
localisation.enable = lib.mkDefault true;
|
||||
gnupg.enable = lib.mkDefault true;
|
||||
};
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
{ lib, my-lib }: args: (my-lib.autoDir ./.)
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
profiles.desktop.enable = lib.mkEnableOption "desktop profile (sway, audio, printing)";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.profiles.desktop.enable {
|
||||
profiles.base.enable = lib.mkDefault true;
|
||||
desktop.enable = lib.mkDefault true;
|
||||
sway.enable = lib.mkDefault true;
|
||||
tuigreet = {
|
||||
enable = lib.mkDefault true;
|
||||
command = lib.mkDefault "sway";
|
||||
};
|
||||
printing.enable = lib.mkDefault true;
|
||||
workstation.enable = lib.mkDefault true;
|
||||
yubikey.enable = lib.mkDefault true;
|
||||
};
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options = {
|
||||
profiles.server.enable = lib.mkEnableOption "headless server profile";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.profiles.server.enable {
|
||||
profiles.base.enable = lib.mkDefault true;
|
||||
workstation.enable = lib.mkDefault true;
|
||||
};
|
||||
}
|
||||
238
scripts/ephvm-run.sh
Executable file
238
scripts/ephvm-run.sh
Executable file
@@ -0,0 +1,238 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
setup_colors() {
|
||||
if [ -t 2 ]; then
|
||||
red=$'\033[31m'
|
||||
yellow=$'\033[33m'
|
||||
cyan=$'\033[36m'
|
||||
reset=$'\033[0m'
|
||||
else
|
||||
red="" yellow="" cyan="" reset=""
|
||||
fi
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "${red}error:${reset} $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo "${yellow}warning:${reset} $*" >&2
|
||||
}
|
||||
|
||||
info() {
|
||||
echo "${cyan}$*${reset}" >&2
|
||||
}
|
||||
|
||||
# globals for cleanup trap
|
||||
CLEANUP_OVERLAY=""
|
||||
CLEANUP_TMPDIR=""
|
||||
QEMU_PID=""
|
||||
VM_READY=false
|
||||
cleanup() {
|
||||
[ -n "$QEMU_PID" ] && kill "$QEMU_PID" 2>/dev/null && wait "$QEMU_PID" 2>/dev/null
|
||||
[ -n "$CLEANUP_OVERLAY" ] && rm -rf "$CLEANUP_OVERLAY"
|
||||
# preserve tmpdir on abnormal exit so the qemu log survives for inspection
|
||||
if [ -n "$CLEANUP_TMPDIR" ]; then
|
||||
if [ "$VM_READY" = true ]; then
|
||||
rm -rf "$CLEANUP_TMPDIR"
|
||||
else
|
||||
echo "qemu log preserved: $CLEANUP_TMPDIR/qemu.log" >&2
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# returns 0 once the guest's sshd is speaking (first bytes are "SSH-")
|
||||
awaiting_ssh_banner() {
|
||||
local port="$1"
|
||||
local banner
|
||||
banner=$(timeout 2 bash -c "exec 3<>/dev/tcp/localhost/$port; head -c 4 <&3" 2>/dev/null) || return 1
|
||||
[ "$banner" = "SSH-" ]
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: ephvm-run.sh [options]
|
||||
|
||||
Options:
|
||||
--mount <path> Mount host directory into VM (repeatable)
|
||||
--no-claude Skip mounting claude config dir
|
||||
--disk-size <size> Resize guest disk (e.g. 50G)
|
||||
--memory <size> VM memory (default: 4G)
|
||||
--cpus <n> VM CPUs (default: 2)
|
||||
--ssh-port <port> Use specific SSH port (default: auto)
|
||||
--serial Attach to serial console instead of SSH
|
||||
-h, --help Show usage
|
||||
EOF
|
||||
exit "${1:-0}"
|
||||
}
|
||||
|
||||
main() {
|
||||
setup_colors
|
||||
|
||||
[ "$EUID" -eq 0 ] && die "ephvm-run.sh must not run as root"
|
||||
|
||||
local ssh_port="" memory=4G cpus=2 claude=true disk_size="" serial=false
|
||||
local -a mounts=()
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--mount)
|
||||
mounts+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
--no-claude)
|
||||
claude=false
|
||||
shift
|
||||
;;
|
||||
--disk-size)
|
||||
disk_size="$2"
|
||||
shift 2
|
||||
;;
|
||||
--memory)
|
||||
memory="$2"
|
||||
shift 2
|
||||
;;
|
||||
--cpus)
|
||||
cpus="$2"
|
||||
shift 2
|
||||
;;
|
||||
--ssh-port)
|
||||
ssh_port="$2"
|
||||
shift 2
|
||||
;;
|
||||
--serial)
|
||||
serial=true
|
||||
shift
|
||||
;;
|
||||
-h | --help) usage ;;
|
||||
*)
|
||||
echo "${red}error:${reset} unknown option: $1" >&2
|
||||
usage 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
info "building ephvm image..."
|
||||
local image_dir image
|
||||
[ -n "${EPHVM_FLAKE:-}" ] || die "EPHVM_FLAKE must be set to the flake directory"
|
||||
local flake="$EPHVM_FLAKE"
|
||||
image_dir=$(nix build --no-link --print-out-paths "${flake}#nixosConfigurations.ephvm.config.system.build.images.qemu")
|
||||
image=$(find "$image_dir" -name '*.qcow2' -print -quit)
|
||||
[ -n "$image" ] || die "no qcow2 image found in $image_dir"
|
||||
|
||||
# create resized overlay when --disk-size is given
|
||||
local drive_arg
|
||||
if [ -n "$disk_size" ]; then
|
||||
CLEANUP_OVERLAY=$(mktemp -d)
|
||||
local overlay="$CLEANUP_OVERLAY/overlay.qcow2"
|
||||
qemu-img create -f qcow2 -b "$(realpath "$image")" -F qcow2 "$overlay" "$disk_size"
|
||||
drive_arg="if=none,id=hd0,file=$overlay,format=qcow2,cache=writeback,aio=threads,discard=unmap,detect-zeroes=unmap"
|
||||
else
|
||||
drive_arg="if=none,id=hd0,file=$image,format=qcow2,snapshot=on,cache=writeback,aio=threads,discard=unmap,detect-zeroes=unmap"
|
||||
fi
|
||||
|
||||
command -v qemu-system-x86_64 &>/dev/null || die "qemu-system-x86_64 not found"
|
||||
[ -r /dev/kvm ] || die "/dev/kvm not readable; kvm is required"
|
||||
|
||||
# auto-allocate ssh port unless serial mode
|
||||
if [ "$serial" = false ] && [ -z "$ssh_port" ]; then
|
||||
ssh_port=10022
|
||||
while ss -tln | grep -q ":${ssh_port}\b"; do
|
||||
ssh_port=$((ssh_port + 1))
|
||||
done
|
||||
fi
|
||||
|
||||
local nic_arg="user,model=virtio-net-pci"
|
||||
if [ -n "$ssh_port" ]; then
|
||||
nic_arg="user,model=virtio-net-pci,hostfwd=tcp:127.0.0.1:${ssh_port}-:22"
|
||||
fi
|
||||
|
||||
local -a qemu_args=(
|
||||
qemu-system-x86_64
|
||||
-accel kvm
|
||||
-cpu host
|
||||
-m "$memory"
|
||||
-smp "$cpus"
|
||||
-drive "$drive_arg"
|
||||
-device "virtio-blk-pci,drive=hd0"
|
||||
-device virtio-rng-pci
|
||||
-nic "$nic_arg"
|
||||
-nographic
|
||||
-sandbox "on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny"
|
||||
)
|
||||
|
||||
local fs_id=0 mount_path name tag
|
||||
for mount_path in "${mounts[@]}"; do
|
||||
[ -e "$mount_path" ] || die "--mount path does not exist: $mount_path"
|
||||
mount_path=$(realpath "$mount_path")
|
||||
# qemu parses -virtfs as csv, a comma in the path would inject options
|
||||
case "$mount_path" in
|
||||
*,*) die "--mount path may not contain commas: $mount_path" ;;
|
||||
esac
|
||||
name=$(basename "$mount_path")
|
||||
tag="m_${name:0:29}"
|
||||
qemu_args+=(
|
||||
-virtfs "local,path=$mount_path,mount_tag=$tag,security_model=none,id=fs${fs_id}"
|
||||
)
|
||||
fs_id=$((fs_id + 1))
|
||||
done
|
||||
|
||||
if [ "$claude" = true ]; then
|
||||
[ -n "${CLAUDE_CONFIG_DIR:-}" ] || die "CLAUDE_CONFIG_DIR must be set (use --no-claude to skip)"
|
||||
mkdir -p "$CLAUDE_CONFIG_DIR"
|
||||
local claude_dir
|
||||
claude_dir=$(realpath "$CLAUDE_CONFIG_DIR")
|
||||
case "$claude_dir" in
|
||||
*,*) die "claude config dir may not contain commas: $claude_dir" ;;
|
||||
esac
|
||||
|
||||
qemu_args+=(
|
||||
-virtfs "local,path=$claude_dir,mount_tag=claude,security_model=none,id=fs${fs_id}"
|
||||
)
|
||||
fs_id=$((fs_id + 1))
|
||||
fi
|
||||
|
||||
info "---"
|
||||
[ -n "$ssh_port" ] && info "SSH: ssh -p $ssh_port matej@localhost"
|
||||
info "---"
|
||||
|
||||
if [ "$serial" = true ]; then
|
||||
exec "${qemu_args[@]}"
|
||||
fi
|
||||
|
||||
CLEANUP_TMPDIR=$(mktemp -d)
|
||||
local qemu_log="$CLEANUP_TMPDIR/qemu.log"
|
||||
|
||||
# start qemu in background and auto-ssh
|
||||
"${qemu_args[@]}" &>"$qemu_log" &
|
||||
QEMU_PID=$!
|
||||
|
||||
# throwaway ssh key (vm accepts any key via AuthorizedKeysCommand)
|
||||
local ssh_key="$CLEANUP_TMPDIR/id_ed25519"
|
||||
ssh-keygen -t ed25519 -f "$ssh_key" -N "" -q
|
||||
|
||||
info "waiting for vm (port $ssh_port)..."
|
||||
local attempts=0
|
||||
# poll for the real SSH banner, not TCP accept: qemu's user-mode nic
|
||||
# accepts host-side the moment qemu starts, well before guest sshd is up
|
||||
while ! awaiting_ssh_banner "$ssh_port"; do
|
||||
attempts=$((attempts + 1))
|
||||
[ $attempts -gt 120 ] && die "vm did not become ready in 60s"
|
||||
kill -0 "$QEMU_PID" 2>/dev/null || die "qemu exited unexpectedly"
|
||||
sleep 0.5
|
||||
done
|
||||
VM_READY=true
|
||||
|
||||
ssh -p "$ssh_port" -t \
|
||||
-i "$ssh_key" \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
-o LogLevel=ERROR \
|
||||
matej@localhost
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -3,22 +3,22 @@ set -euo pipefail
|
||||
|
||||
KEY_DIR="/etc/secrets/initrd"
|
||||
|
||||
echo "Generating initrd SSH host keys in $KEY_DIR"
|
||||
|
||||
main() {
|
||||
echo "generating initrd SSH host keys in $KEY_DIR"
|
||||
sudo mkdir -p "$KEY_DIR"
|
||||
|
||||
if [[ ! -f "$KEY_DIR/ssh_host_rsa_key" ]]; then
|
||||
sudo ssh-keygen -t rsa -N "" -f "$KEY_DIR/ssh_host_rsa_key"
|
||||
echo "Generated: $KEY_DIR/ssh_host_rsa_key"
|
||||
local key_type
|
||||
for key_type in rsa ed25519; do
|
||||
local key_file="$KEY_DIR/ssh_host_${key_type}_key"
|
||||
if [[ ! -f "$key_file" ]]; then
|
||||
sudo ssh-keygen -t "$key_type" -N "" -f "$key_file"
|
||||
echo "generated: $key_file"
|
||||
else
|
||||
echo "Exists: $KEY_DIR/ssh_host_rsa_key"
|
||||
echo "exists: $key_file"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ! -f "$KEY_DIR/ssh_host_ed25519_key" ]]; then
|
||||
sudo ssh-keygen -t ed25519 -N "" -f "$KEY_DIR/ssh_host_ed25519_key"
|
||||
echo "Generated: $KEY_DIR/ssh_host_ed25519_key"
|
||||
else
|
||||
echo "Exists: $KEY_DIR/ssh_host_ed25519_key"
|
||||
fi
|
||||
echo "done. now run nixos-rebuild."
|
||||
}
|
||||
|
||||
echo "Done. Now run nixos-rebuild."
|
||||
main "$@"
|
||||
|
||||
0
secrets/.gitkeep
Normal file
0
secrets/.gitkeep
Normal file
55
secrets/common.yaml
Normal file
55
secrets/common.yaml
Normal file
@@ -0,0 +1,55 @@
|
||||
user-password: ENC[AES256_GCM,data:c7y3RZSikVS32w7RTY5nBSWxDWbwNI5FhLIEoXcru5lpCUu3YqKjHNm8eMI7oeAg1VQIW/1axv0LPHM+bb7wn7SSHy49EvGyda4AU8hdVnsO9gNBul9WQy9Q6RM1PR5vW+IbX1HBFPTTOQ==,iv:oNsDzDugNq2E1CJ89BCXZ/ieCGV+evOwsOuKlKsotBg=,tag:jU8g9fIgexw2bm3E+ow3wA==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age1frwe9fpt9vh969aqnggvq8pfypp6hl98guwfmgttucp7gr55r42sqy2t65
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQOU9BTksxbXdjTkExRDJV
|
||||
aFhVbUFGd1ZSeHFBL0lJRjdSRDRjcjl6ZEQ0Cjg2TFlNZENUWTh5aWNGck52TWFx
|
||||
SC9LS0FrelFCWUI3RUZjdCs3cXF6aDQKLS0tIEwwTWkzOXgxUC9iTFgrQ0szRW8v
|
||||
cGFMa2Rqd1VvWjU3Z2pUdExsdnJUT1EK9iQiW5qZszu65b0wEeq+9JnzzhiAS7fo
|
||||
BmR9OWbDA4GZJBEPBJFD8KxIcO/BYFOjfW2A9PZaTsTpa50Z6+zWxw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age19qj2aaryx869cvcqp77gs9x5hcv4dqjxunkmyre78upsxda6ss7s5vquz4
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPczdWeTRxalA1M3R0S0Qr
|
||||
eGdtZnJxaHllZ2lKMXJUZTN3VWhhTnU1TFRnCjM5OHoxMnEzKzdQelZEQ3ZZRFpt
|
||||
aWRzaTg4dUc5OXpQUngrVmtSRkk1Q3MKLS0tIEZOd0FyMFRlRElWbjlHOVVkZlZP
|
||||
eEhwRVRrcVgvQUx6bi85YWxDYjJZa28K7Hrk4fAqbjeYJfPJODvsth1p8JYbsfMf
|
||||
a6gTckyeQWTNlE+1Tw6g18lvMP1dzIAYRPHtyzmxeCaETVMmSn7XxQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1hksdq2lc89thnpth49sw44f0pmkp950plrhhnttj4petvnfy04tsydz6fl
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPbUh0U1ZDc0ZOKzhxZ3Yv
|
||||
ZHRwbzBIdVNsbEJmU0h4ZnpuTlNHSFdwRlQ0Ck1BREhlVFQ3bnVKajVlTGUzRjhN
|
||||
cWpna25Ya1hoZG1ybFZ0REpCNTFTZmcKLS0tIG5ZQzNIWmd4a3J6YWxDQjYyY2px
|
||||
Y085TkhubS9MSjJtMmZDakdZd2RhR3cKlGH906WAhXNDKwaWqHRoYO9bgiZau0ay
|
||||
8ph3OLOVmrENPW3Othf17NDRet/nATFYZghBU/CI5CvZjr9n9SDYMg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age15cktenavt5v7zm84se36jtly740syca5nw8em8edx404n5x2ddws8jn29g
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwRG5zRkxOT0RyeXVpTDJu
|
||||
TSt2SFFtSlFrSTk1YUZBMnAxTEM3dnFnQkFrClA0cnVpMkdsQWxCakNEZm16OEVG
|
||||
dHFIUDA3TDJLdytySEJJMSsrMGZHcTgKLS0tIHhvdWNXaUthbDJqMWVYeWxuOGpL
|
||||
L0lEZ3FVbmlOcndGUXUybXA4RDA2alUKQo5ctVmARPNY0POf2Ft6AxjwIN1N06C7
|
||||
ft4YX+B4D61tUZ+uvFqHzmKsNpvDdoV81zxvGnnCnv0nSXwNghPFxw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2026-03-29T23:11:10Z"
|
||||
mac: ENC[AES256_GCM,data:XY5wElDn+YD4UHSIGd9Ru8ob39gJVE8VE5gqJJkmzF/xERXp7re/d/6RXxoYDgYS0qUnn8c2VFzJxCvakmV/lPLA8YulFk/ZDysEVn+U3CbfTIkjXcJzewJNz0N+hQKeVaCzPfWeB5oaGtB8bjxOg+GYz2TmSvEAT+kO1U/4Klg=,iv:QOlZ4O+eqvOS9/guc+RmWgVDgPzskb4WIlzyT/14MVM=,tag:ziJE9Yytlr680EpSnBGmdQ==,type:str]
|
||||
pgp:
|
||||
- created_at: "2026-03-29T23:25:01Z"
|
||||
enc: |-
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hF4DPaEEpDtHdk8SAQdAPlvxgVq9o2boPPXWWwV6X3TjHZEl3lm9OcOj7lbsQxsw
|
||||
5PTrX1rIV73XbRQUdFlnoYpUAwxh3UPULyA4+19fvCooC3L0FxA8e4wTiAdw6SKE
|
||||
0l4BImy4sTiM8hNHXqB6u4rj3LbykCjesQve5C3fut62RV8x4cqUJHAB/aumQINT
|
||||
QRXErylKmqo3h7ReRrCm2oOELauv4JFKNPi/cTE0MNh1+w9JxjoASoBufozDOxe4
|
||||
=vIK+
|
||||
-----END PGP MESSAGE-----
|
||||
fp: AF349EECC849D87B790E88FF6318FFB7DB374B7D
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.12.1
|
||||
28
secrets/floo.yaml
Normal file
28
secrets/floo.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
filedrop-authorized-keys: ENC[AES256_GCM,data:3zg0ZZR/EfmffhT+5hiiCawhHW0Y8VOcsMRwPq50AgSvM8DJO/fOK5RhPMlHmOOXSbYYal9QoPILP5rSHDMszk6QSRqmvAbpkpJhgfW4jx8XbLTFxO4lUKe/hd968ryqP2pXtZzUBnOp4vSI29LcYms6e8fSwS8ANtSIjCLkEsY=,iv:EOjsWB7uxjqI5NXot586Q0997SOmkAMwVkxm6VLplDc=,tag:Q4rB6KFibV+F79/rs5m0dA==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age1hksdq2lc89thnpth49sw44f0pmkp950plrhhnttj4petvnfy04tsydz6fl
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTRk1qOGNGNFp4VS9GOUs0
|
||||
dTQ0K3A2Y3VXY3NSV0RyU0VxV3VCa0dDOG5zClAvOElXcHhYaWNCamxFZHMvV2Iy
|
||||
WFRwNFRjaHpKSDdkak5UK05hd0hYMFUKLS0tIGRQeVJGdk8vYVdQdS9BYVd3TEhn
|
||||
UWxzeHlaY2pvdS9tbW9vaVE5NTNwRFEKKieIA5Sn6oN5qjDwh5/usaKwLdYPClmS
|
||||
d+hBdcn4/mtQnrm9dnbRVHd/B1MOuQxoXEB1kc4nzFKvCEqRdRIlYQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2026-04-09T08:57:26Z"
|
||||
mac: ENC[AES256_GCM,data:XHC5cBvQuDi9byVgDymx9qSbplDlHwFTSLaGfWTRQJZeioBelDgBwUstbgWDeNPj1RzGGaSa3+kDOa054DuXi/mw2nDnLGuQDFAmJ66kepJE1mw4F6i4+YnbSE+y7GTbTkUkvbmiNV7uGO4Fq9jy/gNb1wq3IHzDVaKNjNbkKAk=,iv:qK/tgbAkxGpfgJAjBrqDwO/lVkD79pY9S3hzXGGycvM=,tag:oHURU988sW4iN7fXwurOtQ==,type:str]
|
||||
pgp:
|
||||
- created_at: "2026-04-09T08:55:59Z"
|
||||
enc: |-
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hF4DPaEEpDtHdk8SAQdATk1lN0/WDX6S1oPje9jZloSll1qSNau3zgt67CrselMw
|
||||
YlbenxVeY8G4qTvfimX9/qH1/SNHkL/B0jqMCEkw8EpeyA3oEIWuzEEEOA+W/Iri
|
||||
0lwB26CTd8PKwvjuMwmvzTaZfQ9fk+ZsvIjtQaj//WA2utfU4b9T2E+M2Jb5vyki
|
||||
INcWT4PJkNSDxm5NabcTqyetcorDGaU1oN/T1p7pvRBvGCSHItYthVvq/RC0bw==
|
||||
=pKJc
|
||||
-----END PGP MESSAGE-----
|
||||
fp: AF349EECC849D87B790E88FF6318FFB7DB374B7D
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.12.2
|
||||
28
secrets/tower.yaml
Normal file
28
secrets/tower.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
nix-signing-key: ENC[AES256_GCM,data:V/mFaYQazqn3KkbDSt5Fnrl/IFvS9kEe10uhkPHeBluZGjFphKD+2dFCQrPPcXreX0UWklQA9Dokd2cGQBGZIUihJE9o9lH+Q6nrmqk3xsi1fzPS5l8zbn4RITmL3rNkmycXBw==,iv:g/jbUS88IBXnb9e6jGiWYHGfCZtdgI1X167hNmzUQEY=,tag:vO5kiN01FzU7s5jOCGW3Fg==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age1frwe9fpt9vh969aqnggvq8pfypp6hl98guwfmgttucp7gr55r42sqy2t65
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjbkdXUW5YSTA4c3MyZzdi
|
||||
ZlF0L2FQZmttbFBaVmlaWWppaXUxUVdYZEZZCmJHT25IZVBESHVqUWE2bnBYWXQ5
|
||||
UTFLeXg3eUpyWngxc1FXUzhXRCs3R2MKLS0tIGxkbzFMaEUycCtpOC9mTitpVEZh
|
||||
c0pROVJpMjJ6bHd1aEQ2QVE5MUUwdnMK/3tXEStP8JF/2c5nAJ19uA+P1cMG1X+v
|
||||
H5b49uBJ+0UUGMzUpCLgMKz8bq+L8Se0b92iMW5bGW1Fdg/zwJWXOw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2026-03-29T21:47:29Z"
|
||||
mac: ENC[AES256_GCM,data:573t4NH/764zZKzhhpVbzNzpN4QrBjwesIBMyHe7aB47ptGceLhnm+cHOhty3J89VBgn8jgHv5WCBzXFER0LDuQUMFPg6snJ0DK+IgRwuAwNbZdKdSR6VnjqOSBnaijU/Wx93kd/gcMqerYo6rEOLNjVadKgs+NYPLKC/dY4sVs=,iv:kOTr9CIvp6haV8BxTpQfdndYTjZRcmyg+7yjPjHRNLU=,tag:1odj8DYHSnOatRnqyZAcgg==,type:str]
|
||||
pgp:
|
||||
- created_at: "2026-03-29T21:46:47Z"
|
||||
enc: |-
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hF4DPaEEpDtHdk8SAQdA4NO+XFIyWa8YNV24yrosJKMQ60rmiEWYLjFdIkPrKz8w
|
||||
cj1x62iDXeO6DYvyCZnw2h0WstIrXziX6PySveTVnCri90QdLl3jsolIW+V13b8V
|
||||
0lEB5LFvx7OdZJPzrs32qiPv+ofleSMKAokPEhSTKccFI2GbyUiIw7ge2vHSjNpT
|
||||
T9E3tA7HOglyopKTjFw/ujEhKDSRGXwdD2VEYH426Dt8JjU=
|
||||
=E3fO
|
||||
-----END PGP MESSAGE-----
|
||||
fp: AF349EECC849D87B790E88FF6318FFB7DB374B7D
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.12.1
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
osConfig,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
home.stateVersion = "24.11";
|
||||
|
||||
# always-on
|
||||
shell.enable = true;
|
||||
dev.enable = true;
|
||||
neovim = {
|
||||
enable = true;
|
||||
package = inputs.neovim-nightly-overlay.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||
};
|
||||
claude = {
|
||||
enable = true;
|
||||
package = inputs.claude-code-overlay.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||
};
|
||||
|
||||
# desktop-conditional
|
||||
desktop.enable = osConfig.desktop.enable;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
sshAuthorizedKeys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICQGLdINKzs+sEy62Pefng0bcedgU396+OryFgeH99/c janezicmatej"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDk00+Km03epQXQs+xEwwH3zcurACzkEH+kDOPBw6RQe openpgp:0xB095D449"
|
||||
];
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
keys = import ./keys.nix;
|
||||
in
|
||||
{
|
||||
users.users.matej = {
|
||||
uid = 1000;
|
||||
isNormalUser = true;
|
||||
home = "/home/matej";
|
||||
shell = pkgs.zsh;
|
||||
extraGroups = [
|
||||
"wheel"
|
||||
"docker"
|
||||
];
|
||||
openssh.authorizedKeys.keys = keys.sshAuthorizedKeys;
|
||||
};
|
||||
|
||||
users.groups.matej = {
|
||||
gid = 1000;
|
||||
members = [ "matej" ];
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user