Compare commits

..

16 Commits

Author SHA1 Message Date
Alexander d8f2392f80 Point fujin DNS at OPNsense
Old 192.168.1.x Pi-hole/router nameservers returned NXDOMAIN for the
homelab.lan zone; use the OPNsense Unbound resolver (192.168.100.1)
with 1.1.1.1 fallback. Bare http://karate.homelab.lan now resolves and
serves on port 80.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-09-05 12:45:03 +02:00
Alexander be9f5bccf6 Nixos update 31-08-2026 2026-08-31 14:50:42 +02:00
Alexander 27c8db6b29 Update backlog 2026-08-31 14:18:15 +02:00
Alexander a966a47714 Nixos update 24-08-2026 2026-08-24 12:20:16 +02:00
Alexander c2d2c62364 Nixos update 19-08-2026 2026-08-19 13:55:17 +02:00
Alexander 9eed9f81d4 Add android config 2026-08-17 22:02:42 +02:00
Alexander b471966e8a Fix noctalia, add qoder 2026-08-13 19:40:32 +02:00
Alexander 37d6977223 Nixos update 10-08-2026 2026-08-10 17:14:18 +02:00
Alexander 20963732a5 Implement better remote build script 2026-07-27 20:21:10 +02:00
Alexander e9ac72d162 Nixos update 26-07-2026 2026-07-26 14:26:41 +02:00
Alexander e68498cd42 Nixos update 19-07-2026 2026-07-19 13:54:34 +02:00
Alexander 2b9e446876 Integrate with yubikey 2026-07-16 13:50:15 +02:00
Alexander 7313f718df Add some more themes 2026-07-16 11:45:06 +02:00
Alexander 233e463f87 Lock with hyprland on idle 2026-07-12 16:12:37 +02:00
Alexander 727d6c3da9 Update Nixos 06-07-2026 2026-07-06 13:38:22 +02:00
Alexander 1934cd036e Intorduce noctalia bar 2026-07-03 22:10:45 +02:00
22 changed files with 2480 additions and 268 deletions
+231
View File
@@ -61,6 +61,7 @@ This guide documents methods for installing NixOS on a Proxmox virtual machine a
- [[#rebuildsh---enhanced-nixos-rebuild-wrapper][rebuild.sh - Enhanced NixOS Rebuild Wrapper]]
- [[#backupsh---automated-backup-script][backup.sh - Automated Backup Script]]
- [[#hash-utilsh---file-hash-verification][hash-util.sh - File Hash Verification]]
- [[#pve-buildsh---disposable-lxc-builder-on-proxmox-ve][pve-build.sh - Disposable LXC Builder on Proxmox VE]]
- [[#optional-nixos-modules][Optional NixOS Modules]]
- [[#reverse-proxies][Reverse Proxies]]
- [[#file-servers][File Servers]]
@@ -335,6 +336,155 @@ Verifies file integrity using SHA256 checksums.
./bin/hash-util.sh --path configuration.nix --hash $(sha256sum configuration.nix | cut -d' ' -f1)
#+end_src
** pve-build.sh - Disposable LXC Builder on Proxmox VE
Builds a NixOS configuration on a throwaway LXC container running on the Proxmox VE node, then activates the result on the requester (= the machine invoking the script, by default). Offloads the heavy compilation work from the requester to a disposable builder; the closure is shipped back over =nix copy= and activated locally.
The disposable is cloned from a NixOS LXC ostemplate (=nixos-lxc= flake output, =proxmox-lxc= format). The template is built locally and uploaded to PVE on first use, then reused.
*** Prerequisites
- An SSH alias =pve= in =~/.ssh/config= pointing at the PVE node (the script defers all connection details — HostName, User, Port, IdentityFile — to SSH config). Override with =PVE_HOST= or =--pve-host= if your alias differs.
- The operator's pubkey must be in the =adminKeys= list in =machines/builder/default.nix=. The disposable's =builder= user trusts whatever keys are listed there.
- The caller must resolve disposable hostnames (=nixos-builder-<VMID>=) — typically via dnsmasq or split-DNS that reads from PVE. The script never uses IPs for SSH.
- =jq= on the caller (to parse =pvesh= JSON output).
*** Flow
1. Ensure a NixOS LXC ostemplate exists on PVE; build =.#nixos-lxc= locally and =scp= it if missing.
2. Clone a fresh container under a free VMID (scanning downward from 9999), start it, wait for SSH on its hostname.
3. Build phase (runs as the calling user, no =sudo=):
#+begin_example
nixos-rebuild build --flake .#<requester> --build-host root@<ct-ip>
#+end_example
builds the closure on the disposable and copies it back to the local Nix store.
4. Activate phase (only for =test= / =switch= / =boot=; runs locally with =sudo=, no =--build-host=):
#+begin_example
sudo nixos-rebuild <cmd> --flake .#<requester>
#+end_example
the closure is already local, so this only activates.
5. Destroy the disposable (=pct destroy --purge --force=).
The build/activate split avoids needing the requester's root user to SSH to the disposable — only the calling user does.
*** Composite vs. step commands
Each stage can be invoked on its own, or chained via the composite commands:
| Composite | Stages chained | Disposable on success |
|-----------+-----------------------------------------------------------------+-----------------------|
| =build= | deploy-image + start-builder + build-on | left running |
| =test= | deploy-image + start-builder + build-on + activate(test) | left running |
| =switch= | deploy-image + start-builder + build-on + activate(switch) + destroy-builder | destroyed |
| =boot= | deploy-image + start-builder + build-on + activate(boot) + destroy-builder | destroyed |
| Step command | Stage | Effect |
|---------------------------+-------+-----------------------------------------------------------------------|
| =check-image= | 1 | Read-only: exit 0 if a NixOS LXC ostemplate is on PVE, 1 if not. |
| =deploy-image= | 1 | Idempotent: build =.#nixos-lxc= locally + scp to PVE if missing. |
| =update-image= | 1 | Force: rebuild =.#nixos-lxc= and replace the ostemplate on PVE. |
| =start-builder= | 2 | deploy-image + clone a fresh CT + start. |
| =build-on [VMID]= | 3 | Build closure on an existing disposable. |
| =activate <test\|switch\|boot>= | 4 | Activate LOCALLY (closure must already be in the local store). |
| =destroy-builder [VMID]= | 5 | =pct destroy --purge --force=. |
| =info [VMID]= | - | List disposables, or show detail for one. |
*** Stateless design
The script writes no state files. Each step discovers prior steps' artifacts dynamically from PVE:
- Disposables are identified by hostname pattern =nixos-builder-<VMID>= (override via =CT_HOSTNAME_PREFIX=). When a step needs a target VMID and none is passed explicitly, it queries =pvesh get /cluster/resources= for LXC containers matching the prefix.
- Exactly one match :: used automatically.
- Zero matches :: the step errors out and points at =create=.
- Multiple matches :: the step errors out, lists the matches, and asks for an explicit VMID.
- VMID allocation starts at =9999= and scans downward (configurable via =--vmid-start= / =--vmid-floor=) so disposables sit clearly above regular VM IDs.
- The built closure lives in the caller's local Nix store; =nixos-rebuild= finds it naturally during =activate=, so no IPC between =build-on= and =activate= is needed.
*** Hostname-based SSH
All SSH to disposables targets their hostname (=nixos-builder-<VMID>=), never their IP. The caller's resolver must be able to look up PVE container hostnames — typically via dnsmasq or split-DNS that reads from PVE. The script never resolves IPs for SSH; =get_ct_ip= is used only for =info= display and diagnostic logging.
This makes the script safe to re-run, interrupt, or split across shell sessions — there is no =latest-vmid= file to drift out of sync with reality.
*** Basic Usage
#+begin_src sh
# Full happy path — build + activate susano permanently, auto-destroy CT.
pve-build switch --machine susano
# Step-by-step (each step discovers the prior step's artifacts from PVE):
pve-build deploy-image # build + upload the LXC ostemplate (no-op if present)
pve-build start-builder # clones a fresh disposable CT
pve-build build-on # discovers the CT on PVE, builds on it
pve-build activate switch # activates locally (no SSH)
pve-build destroy-builder # discovers the CT on PVE, destroys it
# Rebuild the LXC image after editing machines/builder/default.nix.
pve-build update-image
# Read-only check (exit 0 if image is already on PVE, 1 otherwise).
pve-build check-image && echo ready || echo missing
# Operate on a specific CT (skips discovery — needed when multiple exist).
pve-build build-on 305
#+end_src
*** Advanced Examples
#+begin_src sh
# Build + activate temporarily without persisting to the bootloader.
pve-build test --machine fujin
# Use a non-default PVE node and a higher starting VMID.
pve-build switch --pve-host root@10.0.0.5 --vmid-start 9999
# Keep the disposable even after a successful switch (for inspection).
pve-build switch --keep
# List every disposable currently on PVE.
pve-build info
# Inspect a specific disposable in detail.
pve-build info 307
# Destroy a specific disposable by VMID.
pve-build destroy-builder 307
#+end_src
*** Command Reference
**** Composite commands
- =build= - deploy-image + start-builder + build-on.
- =test= - build + activate temporarily (reverts on reboot).
- =switch= - build + activate permanently. Disposable destroyed on success.
- =boot= - build + set as boot default. Disposable destroyed on success.
**** Step commands
- =check-image= - Read-only: exit 0 if ostemplate is on PVE, 1 if missing.
- =deploy-image= - Idempotent: build =.#nixos-lxc= locally + scp to PVE if missing.
- =update-image= - Force rebuild + replace the ostemplate on PVE.
- =start-builder= - deploy-image + clone a fresh CT + start.
- =build-on [VMID]= - Build closure on an existing disposable (default: discovered).
- =activate <test|switch|boot>= - Activate LOCALLY (closure must already be built).
- =destroy-builder [VMID]= - =pct destroy --purge --force= (default: discovered).
- =info [VMID]= - List disposables, or show detail for one.
**** Aliases
The old command names still work as aliases:
- =ensure-template= → =deploy-image=
- =create= → =start-builder=
**** Options
- =--machine NAME= - Requester machine name (default: current hostname).
- =--pve-host HOST= - PVE SSH alias or target (default: =pve=).
- =--pve-storage NAME= - Ostemplate storage (default: =local=).
- =--rootfs-storage NAME= - Rootfs storage (default: =local-lvm=).
- =--bridge NAME= - Network bridge (default: =vmbr0=).
- =--vmid-start N= - Highest VMID to consider (default: =9999=); scanned downward.
- =--vmid-floor N= - Lowest VMID to consider (default: =100=).
- =--rootfs-gib N= - Rootfs size in GiB (default: =20=).
- =--keep= - Keep the disposable even on successful =switch= / =boot=.
- =--show-trace= , =--verbose= - Passed through to =nixos-rebuild=.
**** Environment
= PVE_HOST= , = PVE_STORAGE= , = PVE_ROOTFS_STORAGE= , = PVE_BRIDGE= , = VMID_START= , = VMID_FLOOR= , = BUILD_SSH_USER= , = CT_BOOT_TIMEOUT= , = CT_ROOTFS_GIB= .
*** Notes
- Disposables are matched by hostname prefix (=nixos-builder-= by default). If you want a parallel run with multiple builders, pass explicit VMIDs to =build-on= / =destroy-builder= / =info=.
- =destroy-builder= calls =pct destroy <vmid> --purge --force=, so it stops and removes a running container in one step.
- To rebuild the LXC template after editing =machines/builder/default.nix=, remove the old tarball from =root@<pve>:/var/lib/vz/template/cache/= — the script always picks the alphabetically last =nixos-lxc-*.tar.xz= it finds.
* Optional NixOS Modules
** Reverse Proxies
The following modules can be enabled to provide a reverse proxy.
@@ -405,6 +555,87 @@ dov = {
};
#+end_src
** YubiKey
Provides PAM U2F authentication (touch YubiKey for login/sudo) and a seamless SSH agent backed by the YubiKey PIV applet.
#+begin_src nix
dov = {
yubikey.enable = true;
};
#+end_src
*** PAM U2F (login & sudo)
After enabling the module and rebuilding, enroll your YubiKey:
1. Create the YubiKey config directory:
#+begin_src sh
mkdir -p ~/.config/Yubico
#+end_src
2. Generate the U2F key mapping (touch YubiKey when prompted):
#+begin_src bash
nix-shell -p pam_u2f --run 'pamu2fcfg -u fujin' > ~/.config/Yubico/u2f_keys
#+end_src
*Nushell users:* use ~out>~ instead of ~>~:
#+begin_src
nix-shell -p pam_u2f --run 'pamu2fcfg -u fujin' out> ~/.config/Yubico/u2f_keys
#+end_src
3. Add a backup YubiKey (optional):
#+begin_src bash
nix-shell -p pam_u2f --run 'pamu2fcfg -u fujin -n' >> ~/.config/Yubico/u2f_keys
#+end_src
4. Rebuild and switch:
#+begin_src sh
sudo nixos-rebuild switch --flake .#fujin
#+end_src
5. Test:
#+begin_src sh
sudo true # should prompt to touch YubiKey
#+end_src
The default mode is =sufficient= (touch key *or* type password). If the key is absent or not enrolled, the normal password prompt follows — you cannot lock yourself out.
*** SSH with FIDO2-backed keys
The module enables the standard OpenSSH agent (not GPG agent's SSH emulation, which doesn't reliably support =-sk= keys). The YubiKey uses FIDO2 — the same interface that PAM U2F uses — so no PIV/pcscd setup is needed for SSH.
1. Generate a FIDO2-backed SSH key (one-time, touch YubiKey when prompted):
#+begin_src sh
ssh-keygen -t ed25519-sk -C "yubikey@fujin"
#+end_src
*Resident key* (recoverable on a new machine without the stub file):
#+begin_src sh
ssh-keygen -t ed25519-sk -O resident -C "yubikey@fujin"
#+end_src
2. Load the key into the agent (once per login session, enter passphrase):
#+begin_src sh
ssh-add ~/.ssh/id_ed25519_sk
#+end_src
*After a rebuild*, log out and back in so the shell picks up the new =SSH_AUTH_SOCK=. In an existing session:
#+begin_src sh
export SSH_AUTH_SOCK=/run/user/$(id -u)/ssh-agent
#+end_src
3. Copy the public key to remote hosts:
#+begin_src sh
ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub susano
#+end_src
4. Test:
#+begin_src sh
ssh susano # touch YubiKey, no password
#+end_src
Each SSH authentication requires a physical YubiKey touch. The passphrase is only asked when loading the key into the agent (step 2), not per-connection.
*Note:* The key stub (~/.ssh/id_ed25519_sk) is tied to this specific generation — regenerating produces a different key. Back it up or use =-O resident=.
* Notes and Configuration Details
** Remote Build Configuration
To leverage remote builds (e.g., building fujin configurations on izanagi), you need to set up SSH keys for the root user:
+19
View File
@@ -0,0 +1,19 @@
# Backlog
<!-- SECTION: ENTRIES -->
<!-- SECTION: Nixos -->
- [ ] [P2] Add nushell completion for rebuild script *(priority: P2)*
<!-- SECTION: HISTORY -->
<!-- SECTION: Nixos -->
| Timestamp | Item ID | Action | Details |
|-----------|---------|--------|---------|
| 2026-07-26T11:58:28.175Z | n-dk597m | item_created | Add nushell completion for rebuild script |
<!-- SECTION: INTEGRITY -->
<!-- saved: 2026-07-26T11:58:28Z | checksum: sha256:1805e1b08cf2b01e73cdd1dd28269bd5ccf5ccdeaf584ff43d5a68edd3d17cfc | entries: 1 | history: 1 -->
Generated
+201 -238
View File
@@ -20,11 +20,11 @@
]
},
"locked": {
"lastModified": 1780756231,
"narHash": "sha256-tXQxKdG5716uB9/LIkLQqQwHKf5mRSpHoZhz3lyI2Cg=",
"lastModified": 1788016784,
"narHash": "sha256-RO90Fk+Rn2Yy+I8oL4ePTLLKLgOAr8hrTx7tlpwdLaA=",
"owner": "hyprwm",
"repo": "aquamarine",
"rev": "6ecde03f47172753fe5a2f334f9d3facfb7e6784",
"rev": "783bfd9ae441d1d0519b979ac68b73ddd6e81df0",
"type": "github"
},
"original": {
@@ -40,17 +40,17 @@
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1779123398,
"narHash": "sha256-8KYQSisso0bn8Z/S3+lunu3sFsMGhf2QXKu+yEWOP7k=",
"owner": "LichHunter",
"repo": "backlog",
"rev": "59507ca9f242950d45d2a6e4d3c10385869344ca",
"type": "github"
"lastModified": 1787939266,
"narHash": "sha256-daj/t7zeuD8XObNPyR1MAw5SziY8t031oenYC5lsyBY=",
"ref": "refs/heads/main",
"rev": "41d18d88aaba1146d09cbe1decd60dcadb8e192e",
"revCount": 33,
"type": "git",
"url": "https://gitea.susano-homelab.duckdns.org/fujin/backlog.git"
},
"original": {
"owner": "LichHunter",
"repo": "backlog",
"type": "github"
"type": "git",
"url": "https://gitea.susano-homelab.duckdns.org/fujin/backlog.git"
}
},
"base16": {
@@ -127,11 +127,11 @@
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1781648708,
"narHash": "sha256-i9ggnF31Uq3tpdp6ZMe7YAOxjTfkB7S4WjSBfXV0uMk=",
"lastModified": 1787524125,
"narHash": "sha256-P48TOQdIbB0PKMn4FTk6X0utbf0LemNlJ+bFcSbveGA=",
"owner": "9001",
"repo": "copyparty",
"rev": "d33d11321f823f58a9109298ef886044f63b02ce",
"rev": "9de090265f8d063056320f41d984830839017a2f",
"type": "github"
},
"original": {
@@ -166,11 +166,11 @@
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1782301008,
"narHash": "sha256-GxQhjwF6eNDhP43Yup1LPmjKS1lZaTRvmqgYPOwv3Zs=",
"lastModified": 1788150896,
"narHash": "sha256-suPEqotkAM4UyRxFk6VjWg1E/yBRrpom2E9lr0vnT+8=",
"owner": "nix-community",
"repo": "emacs-overlay",
"rev": "05d06425c4e17fdf1cbc5cdbf744e5d635993245",
"rev": "f6229276417aa356ae16dfd3b21b51525f55083f",
"type": "github"
},
"original": {
@@ -183,11 +183,11 @@
"firefox-gnome-theme": {
"flake": false,
"locked": {
"lastModified": 1779670703,
"narHash": "sha256-UdfMivNMwCCqQsYDg5pSz8X2IOaOrIZLIIy+Bg3CO2o=",
"lastModified": 1783570805,
"narHash": "sha256-ptl5aRlCv9/uRSv2u8Hq8UFVFeZ6Q/bT049bpqNgc3w=",
"owner": "rafaelmardojai",
"repo": "firefox-gnome-theme",
"rev": "942159e73e40bf785816f7f1f5feed9ef3d7c8f9",
"rev": "5602ed62d638142c1ab31dccd01dfbfb28841225",
"type": "github"
},
"original": {
@@ -233,11 +233,11 @@
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1777988971,
"narHash": "sha256-qIoWPDs+0/8JecyYgE3gpKQxW/4bLW/gp45vow9ioCQ=",
"lastModified": 1787559586,
"narHash": "sha256-onL0VLf9vPllmT0H/OlURIU5r5t5WIEl7t4tVNKT0Nw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "0678d8986be1661af6bb555f3489f2fdfc31f6ff",
"rev": "9d0d87172c374f89da73c1cfe6d81ae62feac1f1",
"type": "github"
},
"original": {
@@ -254,11 +254,29 @@
]
},
"locked": {
"lastModified": 1778716662,
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=",
"lastModified": 1782949081,
"narHash": "sha256-vp6Y/Grm98ESt6ceOkWiHWyZRDV3J1RID4w+6NWK9yA=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb",
"rev": "17c9d6cdfc60c64f4ee8d306f9bc0b4ccb51481e",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_3": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib_2"
},
"locked": {
"lastModified": 1772408722,
"narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3",
"type": "github"
},
"original": {
@@ -300,24 +318,6 @@
"type": "github"
}
},
"flake-utils_3": {
"inputs": {
"systems": "systems_4"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"fromYaml": {
"flake": false,
"locked": {
@@ -337,15 +337,14 @@
"git-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1776796298,
"narHash": "sha256-PcRvlWayisPSjd0UcRQbhG8Oqw78AcPE6x872cPRHN8=",
"lastModified": 1787424939,
"narHash": "sha256-O2tBn84NNuHrnqNVxx/XqsXwfYvS1YwBh+7CBnbCYsk=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "3cfd774b0a530725a077e17354fbdb87ea1c4aad",
"rev": "809414f0cdadf82cf11b06c2b29ba9b3168b3297",
"type": "github"
},
"original": {
@@ -354,65 +353,23 @@
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"backlog",
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"gitignore_2": {
"inputs": {
"nixpkgs": [
"hyprland",
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"gnome-shell": {
"flake": false,
"locked": {
"lastModified": 1767737596,
"narHash": "sha256-eFujfIUQDgWnSJBablOuG+32hCai192yRdrNHTv0a+s=",
"host": "gitlab.gnome.org",
"lastModified": 1776175984,
"narHash": "sha256-RJFlFW8GiMei6oqUGrMkGEvVqOH8U7Q8abc1yK4VKD8=",
"owner": "GNOME",
"repo": "gnome-shell",
"rev": "ef02db02bf0ff342734d525b5767814770d85b49",
"type": "github"
"rev": "e0fdc4c13250e9a9b8ea9594c83925274f4a5dca",
"type": "gitlab"
},
"original": {
"host": "gitlab.gnome.org",
"owner": "GNOME",
"ref": "50.1",
"repo": "gnome-shell",
"rev": "ef02db02bf0ff342734d525b5767814770d85b49",
"type": "github"
"type": "gitlab"
}
},
"home-manager": {
@@ -444,11 +401,11 @@
]
},
"locked": {
"lastModified": 1781497404,
"narHash": "sha256-9GAF8sSsnkyCVCWkomXR0T+zdSxyUlfPt6neQidimdg=",
"lastModified": 1786719456,
"narHash": "sha256-B74DLQs/VjlqyhnnX3tguWwghqJHWSJX30TKZuAljIg=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "1285cd3d6882a9847f2d56ed5541b3350c8a6162",
"rev": "83b7606dcf44abe3a94b86e8bb2b3355d22e8797",
"type": "github"
},
"original": {
@@ -473,11 +430,11 @@
]
},
"locked": {
"lastModified": 1776511930,
"narHash": "sha256-fCpwFiTW0rT7oKJqr3cqHMnkwypSwQKpbtUEtxdkgrM=",
"lastModified": 1786464181,
"narHash": "sha256-2alOMkLjXANh7unkZnYnCF2K2rApZaOLMoQ3o+VX2CY=",
"owner": "hyprwm",
"repo": "hyprcursor",
"rev": "39435900785d0c560c6ae8777d29f28617d031ef",
"rev": "e4ed7c08123df5af460a0a70961380cbfb872f76",
"type": "github"
},
"original": {
@@ -502,11 +459,11 @@
]
},
"locked": {
"lastModified": 1776426399,
"narHash": "sha256-RUESLKNikIeEq9ymGJ6nmcDXiSFQpUW1IhJ245nL3xM=",
"lastModified": 1786464367,
"narHash": "sha256-k58p4wbzIXWyRWrW84pP8tD+iaZSSYiiM+fr0Auk4oU=",
"owner": "hyprwm",
"repo": "hyprgraphics",
"rev": "68d064434787cf1ed4a2fe257c03c5f52f33cf84",
"rev": "7c895c44e3ca6d28ed68ddd80ec02b02b925e7fc",
"type": "github"
},
"original": {
@@ -532,11 +489,11 @@
"xdph": "xdph"
},
"locked": {
"lastModified": 1782315209,
"narHash": "sha256-xKpodJ++lnLqRpmcH5OSimuo874wmgm3rD85J3GDmUw=",
"lastModified": 1788100302,
"narHash": "sha256-21MFGYEl3m5SjN9kZGKb+gELVLlMCF1DkbwHqHzSK1w=",
"ref": "refs/heads/main",
"rev": "87cd2a5f6697a5923c4f427e9b399d79a354a7b8",
"revCount": 7499,
"rev": "86c24e2e079aa62214421c76f01b603fc8178125",
"revCount": 7779,
"type": "git",
"url": "https://github.com/hyprwm/Hyprland"
},
@@ -578,11 +535,11 @@
]
},
"locked": {
"lastModified": 1776426575,
"narHash": "sha256-KI6nIfVihn/DPaeB5Et46Xg3dkNHrrEtUd5LBBVomB0=",
"lastModified": 1786464504,
"narHash": "sha256-7sHwM86KILQyHDHDuE2SDBlQ2jvZ0EW3hY7sW009/cg=",
"owner": "hyprwm",
"repo": "hyprland-guiutils",
"rev": "a968d211048e3ed538e47b84cb3649299578f19d",
"rev": "4c30cf3097ea963c0e250749ee0c59f8b08816d6",
"type": "github"
},
"original": {
@@ -608,11 +565,11 @@
]
},
"locked": {
"lastModified": 1781442805,
"narHash": "sha256-Kt56e6Bq2sfqN8yq1RHsS6z+8QKCZelmhaeQQRtZyqU=",
"lastModified": 1788037253,
"narHash": "sha256-QSGOM0IFpp45DwmtIwcih8+kKuSgAoQal9QkVVSRNew=",
"owner": "hyprwm",
"repo": "hyprland-plugins",
"rev": "1f90c674d51a1ef83c725cd6d02280b4c969fdf7",
"rev": "67c3a4c019f223c27b5bdc6bb656ce891a60861a",
"type": "github"
},
"original": {
@@ -662,11 +619,11 @@
]
},
"locked": {
"lastModified": 1777320127,
"narHash": "sha256-Qu+Wf2Bp5qUjyn2YpZNq8a7JyzTGowhT1knrwE38a9U=",
"lastModified": 1786464129,
"narHash": "sha256-339AkTlpMYSIvFuG0rnR+8Yg4/AZKeJalshJavlnKfg=",
"owner": "hyprwm",
"repo": "hyprlang",
"rev": "090117506ddc3d7f26e650ff344d378c2ec329cc",
"rev": "9508458be316a0d70d37ebed1ab725ccd10411ff",
"type": "github"
},
"original": {
@@ -714,11 +671,11 @@
]
},
"locked": {
"lastModified": 1772462885,
"narHash": "sha256-5pHXrQK9zasMnIo6yME6EOXmWGFMSnCITcfKshhKJ9I=",
"lastModified": 1785930473,
"narHash": "sha256-DitTu625BhEYpZjtjxtGpjrEJwPwW+X/+jJvhSZNSJM=",
"owner": "hyprwm",
"repo": "hyprtoolkit",
"rev": "9af245a69fa6b286b88ddfc340afd288e00a6998",
"rev": "af515b69dfbe366dc7873aa1475cb2f4db3ebad7",
"type": "github"
},
"original": {
@@ -739,11 +696,11 @@
]
},
"locked": {
"lastModified": 1780251518,
"narHash": "sha256-fG9xbb1SOAAJ+2kJRakp3ch+BmA/3dEg/K3PoAZTKkw=",
"lastModified": 1786903207,
"narHash": "sha256-QTwMqLLONRhv9iz6CVeuX6BqQNQCIqI8hL/cPYlR/24=",
"owner": "hyprwm",
"repo": "hyprutils",
"rev": "40ede2e7bdec80ba5d4c443160d905e9f841ae5f",
"rev": "6cf50415e06dc6bd9f1252f1b745eac6b4a1cc39",
"type": "github"
},
"original": {
@@ -764,11 +721,11 @@
]
},
"locked": {
"lastModified": 1777159683,
"narHash": "sha256-Jxixw6wZphUp+nHYxOKUYSckL17QMBx2d5Zp0rJHr1g=",
"lastModified": 1786464033,
"narHash": "sha256-QM8Qe4/L8lpdVN4bgwahmi+jyyc4fisseDMe4afcDxA=",
"owner": "hyprwm",
"repo": "hyprwayland-scanner",
"rev": "b8632713a6beaf28b56f2a7b0ab2fb7088dbb404",
"rev": "62e62c1ca23da17612c6890d4ad2064f575643db",
"type": "github"
},
"original": {
@@ -793,11 +750,11 @@
]
},
"locked": {
"lastModified": 1778410714,
"narHash": "sha256-o6RzFj4nJXaPRY7EM01siuCQeT41RfwwmcmFQqwFJJg=",
"lastModified": 1786464294,
"narHash": "sha256-ZQsZ2WvBdkboCIyh8LStDPdAIARmxzn0XMNxxoOhjPE=",
"owner": "hyprwm",
"repo": "hyprwire",
"rev": "85148a8e612808cf5ddb25d0b3c5840f3498a7dc",
"rev": "4ce7cd6b6128c1ac41caf23c58a30a26b327f9dd",
"type": "github"
},
"original": {
@@ -811,11 +768,11 @@
"nixpkgs": "nixpkgs_6"
},
"locked": {
"lastModified": 1775570192,
"narHash": "sha256-wTLOBy3l/FaIGJWRGFTVYsITkou0lmDU3uAMxvOCCN8=",
"lastModified": 1787822983,
"narHash": "sha256-wusELfq9vxbkbZy8cPprcOldqoqSbKltxt++EW9gQ9g=",
"owner": "Lxtharia",
"repo": "minegrub-theme",
"rev": "8ba52f8402ed642abf0f6eee32c407412a3ceae6",
"rev": "89f9e24f44cbe06b11d69068e39f534666e4d3d3",
"type": "github"
},
"original": {
@@ -846,11 +803,11 @@
]
},
"locked": {
"lastModified": 1781513248,
"narHash": "sha256-YLeEcfvlQiNXP9bVoIwyB+NMjMxJmkwv/y+AP/7RWYo=",
"lastModified": 1788166029,
"narHash": "sha256-+hgpdq6rXpbBHhB5Pbu80kq7UTZhVpbZZtJXePs9ufE=",
"owner": "Mic92",
"repo": "nix-ld",
"rev": "b320f5cb8b7f141c224c3631539cd0c45fcf7ee3",
"rev": "2cced31ac171b55dd6ab8cc04502cb1ad012d7cf",
"type": "github"
},
"original": {
@@ -900,11 +857,11 @@
"nixpkgs": "nixpkgs_7"
},
"locked": {
"lastModified": 1782166108,
"narHash": "sha256-/EtnQBcKbsaCAGQ5VRcplrHRkR4ryqyLMpBfkVuG9Xw=",
"lastModified": 1788044418,
"narHash": "sha256-cmOd3iGoE140M2GidgQMQbyxHZ4dT7C0QZq2+CrXQyA=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "875776f0252fcb8618bb948640a0d1f7a5b362be",
"rev": "dc3f0cfde2050172abf6c3cdb684f735c15a57c5",
"type": "github"
},
"original": {
@@ -916,11 +873,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1770073757,
"narHash": "sha256-Vy+G+F+3E/Tl+GMNgiHl9Pah2DgShmIUBJXmbiQPHbI=",
"lastModified": 1782918843,
"narHash": "sha256-ETYnV9U7Sr+A45dohzZdfCZKOss4qrTkO+wgNZNvEc0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "47472570b1e607482890801aeaf29bfb749884f6",
"rev": "e8273b29fe1390ec8d4603f2477357555291432e",
"type": "github"
},
"original": {
@@ -932,11 +889,26 @@
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1777168982,
"narHash": "sha256-GOkGPcboWE9BmGCRMLX3worL4EMnsnG8MyKmXNeYuhQ=",
"lastModified": 1785031560,
"narHash": "sha256-OmshNvn2vupOFpYinLUu+1Dnpu4n7Q5N3ggGVNHpkUI=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "f5901329dade4a6ea039af1433fb087bd9c1fe14",
"rev": "0e79af5e3d4dcfcd676ab5ba3f95d2e3352e078c",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"nixpkgs-lib_2": {
"locked": {
"lastModified": 1772328832,
"narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742",
"type": "github"
},
"original": {
@@ -947,11 +919,11 @@
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1782116945,
"narHash": "sha256-G3tw/IXmaH6IQ2upZvhuN9sG8CkuX+BLuJDpE8hz0Ds=",
"lastModified": 1787962033,
"narHash": "sha256-u6z9VTZA4Kf3RkHQo9sQI7NI4Ei/uiU9vrMqOiwWP1Y=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "34268251cf5547d39063f2c5ea9a196246f7f3a6",
"rev": "c5c4a43b0e8056328ec4529f735cabdb8f1942bb",
"type": "github"
},
"original": {
@@ -963,25 +935,11 @@
},
"nixpkgs_10": {
"locked": {
"lastModified": 1682134069,
"narHash": "sha256-TnI/ZXSmRxQDt2sjRYK/8j8iha4B4zP2cnQCZZ3vp7k=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "fd901ef4bf93499374c5af385b2943f5801c0833",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_11": {
"locked": {
"lastModified": 1781074563,
"narHash": "sha256-md8WlXOlfnIeHeOScMTTHFyf2d6iaTwPl2apR5EQ3P4=",
"lastModified": 1786599213,
"narHash": "sha256-yNJd40f11EzXBjSByCB7IPpeFFAdeoSKKM67dGkfFoU=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "9ae611a455b90cf061d8f332b977e387bda8e1ca",
"rev": "0e251e24a4f24e036a084b6b4b2d2491af4167f4",
"type": "github"
},
"original": {
@@ -993,11 +951,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1778093112,
"narHash": "sha256-18rT4EfMrtYVMQX7AMAEsnv5KhCryLxGolmJ+v+vZdM=",
"lastModified": 1787921194,
"narHash": "sha256-BgYCc3Gn0MuVOj8XpkisNIiTJ5XXFoQ3Ngs0SkVSiOg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "cf9db9282552bb3f2743fc9ed3852d239692089a",
"rev": "0525b37d4207b34aafae53206e7aac1fdf80dbac",
"type": "github"
},
"original": {
@@ -1023,11 +981,11 @@
},
"nixpkgs_4": {
"locked": {
"lastModified": 1781577229,
"narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=",
"lastModified": 1788039129,
"narHash": "sha256-pa4Q0qErvCvzCaaUph7Sm37RhR4xvPrYI8Lgz6k85+A=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "567a49d1913ce81ac6e9582e3553dd90a955875f",
"rev": "d2f67949798825fe853f7c5d0492b8bf016d3f88",
"type": "github"
},
"original": {
@@ -1039,11 +997,11 @@
},
"nixpkgs_5": {
"locked": {
"lastModified": 1780749050,
"narHash": "sha256-3av0pIjlOWQ6rDbNOmpUSvbNnJkGORQKKjb4LtCZsIY=",
"lastModified": 1787736819,
"narHash": "sha256-cV5xEJJK3BvhU8rEd4mC9UsmDi5qscv/kzGPhBRC5WA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a799d3e3886da994fa307f817a6bc705ae538eeb",
"rev": "9fbb54b33e91ee4ca368e35a78e0613c720600b3",
"type": "github"
},
"original": {
@@ -1114,6 +1072,26 @@
"type": "github"
}
},
"noctalia": {
"inputs": {
"nixpkgs": [
"unstable"
]
},
"locked": {
"lastModified": 1788154427,
"narHash": "sha256-nCzmnj3rk60iznPMoDBg09b3wsDzEoGAjQj81QlsUTo=",
"owner": "noctalia-dev",
"repo": "noctalia",
"rev": "bee126157205f9e686e4f3f98d2cc3be1c1bf252",
"type": "github"
},
"original": {
"owner": "noctalia-dev",
"repo": "noctalia",
"type": "github"
}
},
"nur": {
"inputs": {
"flake-parts": [
@@ -1126,11 +1104,11 @@
]
},
"locked": {
"lastModified": 1780281641,
"narHash": "sha256-M/+hUKoKbHXpV0xGVfELbN1Ds1aoe3pL5p5/t46YhVo=",
"lastModified": 1785549842,
"narHash": "sha256-DCwBZmGsySF7oKGTRgEv2HvpxVXkHT+38VhTM76k0B4=",
"owner": "nix-community",
"repo": "NUR",
"rev": "30f9ae2f04174de63ba8bcf3580ca90843b28a01",
"rev": "a9f987b57594e845e3e5cdd423b9a70846d70308",
"type": "github"
},
"original": {
@@ -1142,18 +1120,17 @@
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat_2",
"gitignore": "gitignore_2",
"nixpkgs": [
"hyprland",
"nixpkgs"
]
},
"locked": {
"lastModified": 1778507602,
"narHash": "sha256-kTwur1wV+01SdqskVMSo6JMEpg71ps3HpbFY2GsflKs=",
"lastModified": 1787424939,
"narHash": "sha256-O2tBn84NNuHrnqNVxx/XqsXwfYvS1YwBh+7CBnbCYsk=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "61ab0e80d9c7ab14c256b5b453d8b3fb0189ba0a",
"rev": "809414f0cdadf82cf11b06c2b29ba9b3168b3297",
"type": "github"
},
"original": {
@@ -1226,6 +1203,7 @@
"nixos-generators": "nixos-generators",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_8",
"noctalia": "noctalia",
"sops-nix": "sops-nix",
"split-monitor-workspaces": "split-monitor-workspaces",
"stylix": "stylix",
@@ -1243,11 +1221,11 @@
]
},
"locked": {
"lastModified": 1782165805,
"narHash": "sha256-478kKQBvK6SYTOdN2h9jhKJv94nbXRbFMfuL1WshErg=",
"lastModified": 1786629091,
"narHash": "sha256-gkig4nPi1CWc4Z50GBsjE4ygSE7hMpl/TwID2an2Cck=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "56b24064fdcaedca53553b1a6d607fd23b613a24",
"rev": "a8627b21b9107c5711c96b84f32a9a4b3d45295f",
"type": "github"
},
"original": {
@@ -1264,11 +1242,11 @@
"nix-filter": "nix-filter"
},
"locked": {
"lastModified": 1782237065,
"narHash": "sha256-Oxtr8k+qu4Kd/7BJ5eo8Pfoje8PDIO1YK2+mhCkHRhQ=",
"lastModified": 1787489216,
"narHash": "sha256-VE1o0B6GPHrwmYANfGIEm/hDz2u4IhG0Gdj+ZkEV2uY=",
"owner": "zjeffer",
"repo": "split-monitor-workspaces",
"rev": "968a6a603cabf8ab8f5ce5a402e8ed3bfcae69ce",
"rev": "47b22971e3a21d228882ca1e2509fdac26f2d5b2",
"type": "github"
},
"original": {
@@ -1297,11 +1275,11 @@
"tinted-zed": "tinted-zed"
},
"locked": {
"lastModified": 1782310521,
"narHash": "sha256-vsxcG0i8e4EPfdnhMTKMVzD1825H2vG1BBslzom9wxg=",
"lastModified": 1787771653,
"narHash": "sha256-DkkJSBOXWV/mja5Vy8az5g1KpZlsbUwlmH0BsQhowaQ=",
"owner": "nix-community",
"repo": "stylix",
"rev": "e084d011e7ee9302aceaaf6c1fc28a9ace09e16a",
"rev": "5e3809851f486e7fc7e84b40f174c74b60ecc784",
"type": "github"
},
"original": {
@@ -1327,15 +1305,16 @@
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"lastModified": 1774449309,
"narHash": "sha256-brhZ8DmuGtzkCYHJg4HEd602amKm89Y9ytsFZ5uWD1w=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"rev": "c29398b59d2048c4ab79345812849c9bd15e9150",
"type": "github"
},
"original": {
"owner": "nix-systems",
"ref": "future-26.11",
"repo": "default",
"type": "github"
}
@@ -1355,21 +1334,6 @@
"type": "github"
}
},
"systems_4": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"thefuck": {
"inputs": {
"flake-utils": "flake-utils_2",
@@ -1411,11 +1375,11 @@
"tinted-schemes": {
"flake": false,
"locked": {
"lastModified": 1777806186,
"narHash": "sha256-PDF0/wObw4nIsSBeXVYLsloXOiphXCgIdsrNcVXguKs=",
"lastModified": 1785153830,
"narHash": "sha256-fNdfCTeCXU3tZG3TMincd+u68qBHQgCr2Ljr/M1mWP0=",
"owner": "tinted-theming",
"repo": "schemes",
"rev": "0c94645546f4f3ddac77a1a5fce54eb95bf50795",
"rev": "9bd28ed313560db3c5b605c63bc4e309e78e3fc8",
"type": "github"
},
"original": {
@@ -1427,11 +1391,11 @@
"tinted-tmux": {
"flake": false,
"locked": {
"lastModified": 1778379944,
"narHash": "sha256-wPDFzMGSlARlw0Sfsn48Q2+jPSfk6N0Ng6BC/d+7Q24=",
"lastModified": 1785031658,
"narHash": "sha256-mZp9O2LjzdMzlqQF3l3fjqsuPBzXy+1qTfBEUGjTlpk=",
"owner": "tinted-theming",
"repo": "tinted-tmux",
"rev": "fe0203a198690e71a5ff11e08812a4673de3678d",
"rev": "5d2c67f61ea7af36f16865ab6d541cdba41dc257",
"type": "github"
},
"original": {
@@ -1443,11 +1407,11 @@
"tinted-zed": {
"flake": false,
"locked": {
"lastModified": 1778378178,
"narHash": "sha256-OXPXRIQgGwV77HjYRryOHguh4ALX96jkg+tseLkGgHA=",
"lastModified": 1785030526,
"narHash": "sha256-klZf8UviewRkxuu74Bhbq6tqy7oxebQC7UVRWbbtQxU=",
"owner": "tinted-theming",
"repo": "base16-zed",
"rev": "9cd816033ff969415b190722cddf134e78a5665f",
"rev": "16f5a8adf4a6b1310d0a61ab172de963e8f76a02",
"type": "github"
},
"original": {
@@ -1458,11 +1422,11 @@
},
"unstable": {
"locked": {
"lastModified": 1781577229,
"narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=",
"lastModified": 1788039129,
"narHash": "sha256-pa4Q0qErvCvzCaaUph7Sm37RhR4xvPrYI8Lgz6k85+A=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "567a49d1913ce81ac6e9582e3553dd90a955875f",
"rev": "d2f67949798825fe853f7c5d0492b8bf016d3f88",
"type": "github"
},
"original": {
@@ -1479,11 +1443,11 @@
]
},
"locked": {
"lastModified": 1782358560,
"narHash": "sha256-vCcLh9pw3XO/+Lxk8r6xv6QnoCrTfGqiACcI7O637Wg=",
"lastModified": 1788146656,
"narHash": "sha256-XmJmvk9rytTb7dCotO/aqR+YysB8HOqnprlOdv+LAF4=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "3a70e333f2950c302e875c44cfcfaff3f80f36bc",
"rev": "82c265faf4e3161d6015db07c9b0f1ee36a9029b",
"type": "github"
},
"original": {
@@ -1520,15 +1484,14 @@
},
"vscode-server": {
"inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs_10"
"flake-parts": "flake-parts_3"
},
"locked": {
"lastModified": 1770124655,
"narHash": "sha256-yHmd2B13EtBUPLJ+x0EaBwNkQr9LTne1arLVxT6hSnY=",
"lastModified": 1784312229,
"narHash": "sha256-2uHCSUw341o3my1R0U0YCfbnMEazylxb58evWsjGL50=",
"owner": "nix-community",
"repo": "nixos-vscode-server",
"rev": "92ce71c3ba5a94f854e02d57b14af4997ab54ef0",
"rev": "2f984dfbe7e5271b5c413d3e734374cc1306c921",
"type": "github"
},
"original": {
@@ -1565,11 +1528,11 @@
]
},
"locked": {
"lastModified": 1780133819,
"narHash": "sha256-0YPKIY3dlnR7SPq7Z8ekFVvzFsfeiAtEj+QUI3KHrlI=",
"lastModified": 1786988229,
"narHash": "sha256-frEFLVRj8xXvBBDs44IRiqHo6R2PxsRpluygL7abjjI=",
"owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland",
"rev": "4a170c0ba96fd37374f93d8f91c9ed91814828ac",
"rev": "59d429bf45aed4e2209043c0c36565ad8e2859a5",
"type": "github"
},
"original": {
@@ -1581,14 +1544,14 @@
"zen-browser": {
"inputs": {
"home-manager": "home-manager_2",
"nixpkgs": "nixpkgs_11"
"nixpkgs": "nixpkgs_10"
},
"locked": {
"lastModified": 1782144240,
"narHash": "sha256-RgCWSv7AJZCwPhCzz+J0lvwp1WBz9ouvCnnlmvu0xfw=",
"lastModified": 1788149125,
"narHash": "sha256-GueAv4789rOV70hixnL9+uN4tiDKJm7s92DnTejdpuE=",
"owner": "0xc000022070",
"repo": "zen-browser-flake",
"rev": "d1693556428967f8b4eef128feb090421ddcaf15",
"rev": "5fe00f38d41ced9a5c0ba1cbf2127d7e8b3e3d56",
"type": "github"
},
"original": {
+20 -2
View File
@@ -1,5 +1,5 @@
{
description = "Susano NixOS Homelab";
description = "Alex's NixOS";
inputs = {
# Nixpkgs
@@ -70,7 +70,12 @@
thefuck.url = "github:LichHunter/thefuck";
backlog.url = "github:LichHunter/backlog";
backlog.url = "git+https://gitea.susano-homelab.duckdns.org/fujin/backlog.git";
noctalia = {
url = "github:noctalia-dev/noctalia";
inputs.nixpkgs.follows = "unstable";
};
};
outputs = {
@@ -209,6 +214,19 @@
};
packages.x86_64-linux = {
nixos-lxc = (nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./machines/builder
({ modulesPath, ... }: {
imports = [ (modulesPath + "/virtualisation/proxmox-lxc.nix") ];
})
];
specialArgs = {
inherit inputs;
};
}).config.system.build.image;
izanami-proxmox = nixos-generators.nixosGenerate {
system = "x86_64-linux";
modules = [
+1
View File
@@ -3,5 +3,6 @@
{
imports = [
./waybar
./noctalia
];
}
+143
View File
@@ -0,0 +1,143 @@
{
config,
lib,
pkgs,
inputs,
...
}:
with lib;
let
cfg = config.dov.bar.noctalia;
c = config.lib.stylix.colors.withHashtag;
# Build a noctalia palette from the active stylix base16 scheme.
# Both dark/light keys carry the same values so the palette works
# regardless of which theme.mode noctalia picks.
mkPalette = variant: {
mPrimary = c.base0D;
mOnPrimary = c.base00;
mSecondary = c.base0E;
mOnSecondary = c.base00;
mTertiary = c.base0C;
mOnTertiary = c.base00;
mError = c.base08;
mOnError = c.base00;
mSurface = if variant == "dark" then c.base00 else c.base07;
mOnSurface = if variant == "dark" then c.base05 else c.base01;
mSurfaceVariant = if variant == "dark" then c.base01 else c.base06;
mOnSurfaceVariant = if variant == "dark" then c.base04 else c.base02;
mHover = if variant == "dark" then mkForce c.base02 else mkForce c.base06;
mOnHover = if variant == "dark" then mkForce c.base06 else mkForce c.base01;
mOutline = c.base03;
mShadow = c.base00;
terminal = {
background = if variant == "dark" then c.base00 else c.base07;
foreground = if variant == "dark" then c.base05 else c.base01;
cursor = if variant == "dark" then c.base05 else c.base01;
cursorText = if variant == "dark" then c.base00 else c.base07;
selectionBg = c.base02;
selectionFg = if variant == "dark" then c.base05 else c.base01;
normal = {
black = c.base00;
red = c.base08;
green = c.base0B;
yellow = c.base0A;
blue = c.base0D;
magenta = c.base0E;
cyan = c.base0C;
white = c.base05;
};
bright = {
black = c.base03;
red = c.base08;
green = c.base0B;
yellow = c.base0A;
blue = c.base0D;
magenta = c.base0E;
cyan = c.base0C;
white = c.base07;
};
};
};
themeMode = if config.stylix.polarity == "dark" then "dark" else "light";
in
{
options.dov.bar.noctalia.enable = mkEnableOption "noctalia bar";
config = mkIf cfg.enable {
programs.noctalia = {
enable = true;
package = inputs.noctalia.packages.${pkgs.system}.default;
systemd.enable = true;
customPalettes.stylix = {
dark = mkPalette "dark";
light = mkPalette "light";
};
settings = {
theme = {
mode = themeMode;
source = "custom";
custom_palette = "stylix";
};
location.address = "Marseille, France";
bar.main = {
position = "top";
thickness = 34;
radius = 12;
margin_h = 0;
margin_v = 6;
padding = 14;
widget_spacing = 6;
capsule = true;
capsule_fill = "surface_variant";
capsule_radius = 20.0;
reserve_space = true;
start = [ "workspaces" "media" "active_window" ];
center = [ "clock" ];
end = [ "tray" "caffeine" "keyboard_layout" "cpu" "ram" "brightness" "volume" "mic" "network" "battery" "session" ];
};
widget = {
clock = {
format = "{:%a %d %b, %H:%M}";
tooltip_format = "{:%A, %B %d, %Y}";
};
workspaces.display = "id";
# Named sysmon instances — type field overrides the widget id
cpu = {
type = "sysmon";
stat = "cpu_usage";
};
ram = {
type = "sysmon";
stat = "ram_pct";
};
# Microphone — named volume widget with input device
mic = {
type = "volume";
device = "input";
};
battery.warning_threshold = 30;
keyboard_layout = {
display = "short";
hide_when_single_layout = true;
};
};
};
};
};
}
+83 -19
View File
@@ -6,7 +6,8 @@ let
cfg = config.dov.dynamic-theme;
schemes = "${pkgs.base16-schemes}/share/themes";
# Single source of truth for builtin themes
# Curated defaults — covers the popular schemes without blowing up
# build memory. Users can add more via `dov.dynamic-theme.themes`.
builtinThemes = {
gruvbox = {
dark = "${schemes}/gruvbox-dark-hard.yaml";
@@ -16,9 +17,42 @@ let
dark = "${schemes}/catppuccin-mocha.yaml";
light = "${schemes}/catppuccin-latte.yaml";
};
nord = {
dark = "${schemes}/nord.yaml";
light = "${schemes}/nord-light.yaml";
};
solarized = {
dark = "${schemes}/solarized-dark.yaml";
light = "${schemes}/solarized-light.yaml";
};
tokyo-night = {
dark = "${schemes}/tokyo-night-dark.yaml";
light = "${schemes}/tokyo-night-light.yaml";
};
rose-pine = {
dark = "${schemes}/rose-pine.yaml";
light = "${schemes}/rose-pine-dawn.yaml";
};
one = {
dark = "${schemes}/onedark.yaml";
light = "${schemes}/one-light.yaml";
};
material = {
dark = "${schemes}/material-darker.yaml";
light = "${schemes}/material-lighter.yaml";
};
google = {
dark = "${schemes}/google-dark.yaml";
light = "${schemes}/google-light.yaml";
};
github = {
dark = "${schemes}/github-dark.yaml";
light = "${schemes}/github.yaml";
};
};
# Generate all theme-variant combinations
# Generate all theme-variant combinations from the configured themes.
# Each theme produces a "-dark" and "-light" variant.
themeVariants = concatMapAttrs (name: theme: {
"${name}-dark" = { scheme = theme.dark; polarity = "dark"; };
"${name}-light" = { scheme = theme.light; polarity = "light"; };
@@ -112,28 +146,42 @@ in {
};
});
default = builtinThemes;
description = "Available themes with dark and light variants";
description = ''
Available themes with dark and light variants. Each entry
generates two specialisations (`<name>-dark` and
`<name>-light`). Add more here to extend the defaults.
'';
};
doomThemes = mkOption {
type = types.attrsOf types.str;
default = {
gruvbox-dark = "doom-gruvbox";
gruvbox-light = "doom-one-light";
catppuccin-dark = "doom-one";
catppuccin-light = "doom-one-light";
};
# Auto-generate sane defaults from the configured themes, then
# overlay specific overrides for schemes that ship a dedicated
# doom-theme.
default =
let
generated = concatMapAttrs (name: _: {
"${name}-dark" = "doom-one";
"${name}-light" = "doom-one-light";
}) cfg.themes;
in generated // {
"gruvbox-dark" = "doom-gruvbox";
"solarized-dark" = "doom-solarized-dark";
"solarized-light" = "doom-solarized-light";
"tokyo-night-dark" = "doom-tokyo-night";
"nord-dark" = "doom-nordic";
"material-dark" = "doom-material";
"rose-pine-dark" = "doom-rose-pine";
"catppuccin-dark" = "doom-catppuccin-mocha";
"catppuccin-light" = "doom-catppuccin-latte";
};
description = ''
Mapping from theme variant name (e.g. "gruvbox-dark") to the Doom
Emacs theme symbol (e.g. "doom-gruvbox") that theme-switch will
live-load via emacsclient when switching to that variant. Variants
absent from this map are left unchanged in Emacs.
Only themes actually installed in Doom will load; the defaults use
themes bundled with doom-themes (so they work out of the box, though
catppuccin variants fall back to generic dark/light). For accurate
catppuccin colours, install the `catppuccin-theme` Emacs package and
map the variants to `catppuccin-mocha` / `catppuccin-latte`.
Mapping from variant name (e.g. "gruvbox-dark") to the Doom
Emacs theme symbol. Defaults are auto-generated from the
configured themes (dark → doom-one, light → doom-one-light)
with overrides for schemes that have a dedicated doom-theme.
Only themes installed in Doom will load; others are silently
skipped.
'';
};
@@ -213,5 +261,21 @@ in {
Install.WantedBy = [ "graphical-session.target" ];
};
}
# Nushell tab-completion: declares `theme-switch`'s argument signature
# so nushell completes variant names natively (takes priority over
# carapace's generic fallback). `extraConfig` is `types.lines`, so it
# merges cleanly with the carapace completer from hm-modules/shell/nu.
(mkIf config.programs.nushell.enable {
programs.nushell.extraConfig = ''
def "nu-complete theme-variants" [] {
"${availableVariants}" | split row " "
}
extern theme-switch [
variant: string@"nu-complete theme-variants"
]
'';
})
]);
}
+152
View File
@@ -0,0 +1,152 @@
# Minimal NixOS configuration for a disposable LXC builder on Proxmox VE.
#
# Built via the `nixos-lxc` flake output using nixos-generators with
# format = "proxmox-lxc". The resulting tarball is uploaded to PVE's
# /var/lib/vz/template/cache/ and cloned by pve-build each time a
# disposable builder is needed.
#
# Responsibilities of this image:
# * Run nix with flakes as the `builder` user so nixos-rebuild
# --build-host builder@<hostname> works against it.
# * Be a competent builder: all cores, hardlink dedup, keep-derivations
# and keep-outputs, keep-going on failure, idle CPU scheduling.
# * Accept SSH from the operator (`builder` user + admin keys shared
# across the rest of the homelab). Root SSH is disabled.
# * Stay tiny — no bootloader, no kernel, no home-manager. The proxmox-lxc
# format module from nixpkgs already sets boot.isContainer = true and
# handles the LXC-specific bits.
{
config,
pkgs,
inputs,
lib,
...
}:
let
flakeInputs = lib.filterAttrs (_: lib.isType "flake") inputs;
# Operator keys — same ones baked into every other machine in this flake.
# Whoever runs pve-build must hold a matching private key. Add more
# keys here as needed; the authorized_keys list mirrors this exactly.
adminKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBcGhVpjmWEw1GEw0y/ysJPa2v3+u/Rt/iES/Se2huH2 alexander0derevianko@gmail.com"
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIGXvmStLAC4f+D9/b3/eKl6lb8xLQOfDqwu3Piocrr7ZAAAABHNzaDo= yubikey@fujin"
];
in {
nixpkgs = {
hostPlatform = "x86_64-linux";
config.allowUnfree = true;
};
nix = {
settings = {
experimental-features = "nix-command flakes";
flake-registry = "";
nix-path = config.nix.nixPath;
# Parallelism — use every core the container can see.
cores = 0; # 0 = use all visible cores per build job
max-jobs = "auto"; # auto = one local build job per core
# Store hygiene — hardlink identical files so the store stays compact
# across many sequential builds.
auto-optimise-store = true;
# Cache reuse — keep derivation files and their outputs around even
# when no current generation references them. Massively speeds up
# repeated builds of the same flakes and lets you inspect what a
# prior build actually pulled in.
gc-keep-derivations = true;
gc-keep-outputs = true;
# Don't abort the whole build on the first failing derivation — let
# nix continue so the caller sees every failure in one pass.
keep-going = true;
# `builder` drives builds via nixos-rebuild --build-host. Trust it so
# `nix copy --to ssh://builder@<ct>` from the caller works without
# extra configuration.
trusted-users = [ "builder" ];
allowed-users = [ "builder" ];
# Keep the default cache so flake inputs and build outputs resolve
# without having to build them from source.
substituters = lib.mkForce [ "https://cache.nixos.org/" ];
trusted-public-keys = lib.mkForce [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
];
};
channel.enable = false;
# Be polite to other tenants on the PVE node when no builds are running.
daemonCPUSchedPolicy = "idle";
registry = lib.mapAttrs (_: flake: { inherit flake; }) flakeInputs;
nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs;
};
# Networking: PVE creates the veth pair and attaches it to the bridge, but
# because NixOS is not a recognised PVE ostype (no setup plugin exists),
# PVE cannot write the guest-side network config. We configure eth0 DHCP
# ourselves via systemd-networkd. The proxmox-lxc module already enables
# networking.useNetworkd; this block provides the matching .network file.
systemd.network = {
enable = true;
networks."10-eth0" = {
matchConfig.Name = "eth0";
networkConfig.DHCP = "yes";
};
};
time.timeZone = "Europe/Warsaw";
i18n.defaultLocale = "en_US.UTF-8";
# `builder` is the only SSH-reachable account on this disposable. It is a
# normal user (no root login via SSH — see services.openssh.settings below)
# but has passwordless sudo for the rare case a build needs it. Build
# traffic itself goes through nix-daemon, which trusts `builder`.
users.users.builder = {
isNormalUser = true;
description = "Disposable LXC builder";
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = adminKeys;
};
security.sudo = {
enable = true;
extraRules = [{
users = [ "builder" ];
commands = [{
command = "ALL";
options = [ "NOPASSWD" ];
}];
}];
};
environment.systemPackages = with pkgs; [
vim
wget
curl
ripgrep
jq
git
tmux
htop
ncdu
file
iproute2
nix-output-monitor # `nom build` for friendlier nix build output
];
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no"; # only `builder` may log in
PasswordAuthentication = false;
};
};
# This is a disposable image; do NOT change.
system.stateVersion = "25.05";
}
+15 -3
View File
@@ -66,9 +66,11 @@
};
networking = {
# OPNsense (192.168.100.1) runs Unbound with the homelab.lan overrides;
# the old 192.168.1.x Pi-hole/router are gone and returned NXDOMAIN for
# the local zone. 1.1.1.1 stays as a fallback if the firewall is down.
nameservers = [
"192.168.1.2" # PyHole
"192.168.1.1" # Router
"192.168.100.1" # OPNsense Unbound
"1.1.1.1"
];
dhcpcd.extraConfig = ''
@@ -112,6 +114,12 @@
dov = {
development.emacs.enable = true;
development.qoder = {
enable = false;
version = "1.19.2";
hash = "sha256-/P3UStsRHKKWC1xET9SL23E0CUPxQ5DkmWFco+dH37A="; # nix store prefetch-file --json https://download.qoder.com/release/latest/qoder_amd64.deb | jq -r .hash
};
development.android.enable = true;
virtualisation.docker.enable = true;
virtualisation.incus.enable = true;
@@ -121,6 +129,8 @@
display-manager.ly.enable = true;
gaming.enable = true;
yubikey.enable = true;
};
###
@@ -134,7 +144,9 @@
# Stylix is handled entirely at the Home Manager level (see
# hm-modules/theme). Load the stylix HM module here so the `stylix`
# option exists for fujin's home configuration.
sharedModules = [ inputs.stylix.homeModules.stylix ];
sharedModules = [
inputs.stylix.homeModules.stylix
];
users."${username}" = { imports = [ ./home.nix ] ++ extraHomeModules; };
};
@@ -42,6 +42,12 @@
;; change `org-directory'. It must be set before org loads!
(setq org-directory "~/org/")
;; Use bash, not nu, for non-interactive subprocesses (compile, shell-command,
;; lsp-mode installers). Nu doesn't unescape Emacs's POSIX-style backslash
;; escaping, which corrupts args like -Djdt.download.url=...?...=... .
;; vterm keeps using nu (see vterm-shell below).
(setq shell-file-name "/run/current-system/sw/bin/bash")
;; Whenever you reconfigure a package, make sure to wrap your config in an
;; `after!' block, otherwise Doom's defaults may override your settings. E.g.
+5 -3
View File
@@ -47,9 +47,10 @@
browser.zen.enable = true;
#window-manager.hypr.enable = true;
bar.waybar.enable = true;
bar = {
waybar.enable = false;
noctalia.enable = true;
};
launcher.wofi.enable = true;
@@ -151,6 +152,7 @@
wl-clipboard
#cloudflared
kdePackages.okular #pdf tool
kdePackages.gwenview # image viewer
#nextcloud-client
#music
+3 -1
View File
@@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }:
{ ... }:
{
imports = [
@@ -15,5 +15,7 @@
./gitlab
./jenkins
./gaming
./yubikey
./scripts
];
}
+43
View File
@@ -0,0 +1,43 @@
{
config,
lib,
pkgs,
username,
...
}:
let
cfg = config.dov.development.android;
mtk-udev-rules = pkgs.writeTextFile {
name = "mtk-udev-rules";
destination = "/etc/udev/rules.d/60-mtk.rules";
text = ''
# MediaTek BROM (0003), Preloader VCOM (2000/2001), META (6000)
SUBSYSTEM=="usb", ATTR{idVendor}=="0e8d", MODE="0666", TAG+="uaccess"
# Oppo/Realme fastboot + adb
SUBSYSTEM=="usb", ATTR{idVendor}=="22d9", MODE="0666", TAG+="uaccess"
# keep ModemManager's hands off the preloader port
SUBSYSTEM=="usb", ATTR{idVendor}=="0e8d", ENV{ID_MM_DEVICE_IGNORE}="1"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0e8d", ENV{ID_MM_DEVICE_IGNORE}="1"
'';
};
in
{
options.dov.development.android = {
enable = lib.mkEnableOption "Android and MediaTek flashing tools";
};
config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [
android-tools
mtkclient
usbutils
];
users.users.${username}.extraGroups = [ "dialout" ];
services.udev.packages = [ mtk-udev-rules ];
};
}
+2
View File
@@ -4,5 +4,7 @@
imports = [
./nix-vscode-server
./emacs
./qoder
./android
];
}
+1 -1
View File
@@ -18,7 +18,7 @@ in {
## Emacs itself
binutils # native-comp needs 'as', provided by this
# 28.2 + native-comp
((emacsPackagesFor emacs30).emacsWithPackages (epkgs: [
((emacsPackagesFor emacs).emacsWithPackages (epkgs: [
epkgs.vterm
epkgs.treesit-grammars.with-all-grammars
epkgs.mu4e
+92
View File
@@ -0,0 +1,92 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.dov.development.qoder;
qoder = pkgs.callPackage ./package.nix {
inherit (cfg)
version
url
hash
extraFlags
;
};
in
{
options.dov.development.qoder = {
enable = mkEnableOption "Qoder IDE (unfree, repackaged from the upstream .deb)";
version = mkOption {
type = types.str;
default = "1.19.2";
description = ''
Label only — upstream publishes a rolling "latest" URL, so this is
just what the store path is called. Bump it together with `hash`.
'';
};
url = mkOption {
type = types.str;
default = "https://download.qoder.com/release/latest/qoder_amd64.deb";
description = "Upstream .deb to repackage.";
};
hash = mkOption {
type = types.str;
default = "";
example = "sha256-0000000000000000000000000000000000000000000=";
description = ''
SRI hash of the .deb. Refresh whenever upstream ships a new build:
nix store prefetch-file --json <url> | jq -r .hash
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--disable-gpu-sandbox" ];
description = "Extra Electron/Chromium flags appended to the wrapper.";
};
keyring = mkOption {
type = types.bool;
default = true;
description = ''
Enable gnome-keyring. Qoder is wrapped with
--password-store=gnome-libsecret; without a running secret service
the sign-in token is lost on every restart.
'';
};
};
config = mkIf cfg.enable (mkMerge [
{
assertions = [
{
assertion = cfg.hash != "";
message = ''
dov.development.qoder.hash is empty. Prefetch the .deb first:
nix store prefetch-file --json ${cfg.url} | jq -r .hash
'';
}
];
environment.systemPackages = [ qoder ];
}
(mkIf cfg.keyring {
services.gnome.gnome-keyring.enable = true;
# gnome-keyring enables gcr-ssh-agent by default, which asserts against
# programs.ssh.startAgent from dov.yubikey. We only want the secret
# service here — SSH keys stay with the OpenSSH agent.
services.gnome.gcr-ssh-agent.enable = false;
})
]);
}
+204
View File
@@ -0,0 +1,204 @@
{
lib,
stdenv,
fetchurl,
autoPatchelfHook,
makeWrapper,
wrapGAppsHook3,
zstd,
alsa-lib,
at-spi2-atk,
at-spi2-core,
atk,
cairo,
cups,
dbus,
expat,
fontconfig,
freetype,
gdk-pixbuf,
glib,
gtk3,
krb5,
libdrm,
libgbm,
libglvnd,
libnotify,
libsecret,
libuuid,
libxkbcommon,
nspr,
nss,
pango,
systemd,
zlib,
libx11,
libxcb,
libxcomposite,
libxcursor,
libxdamage,
libxext,
libxfixes,
libxi,
libxkbfile,
libxrandr,
libxrender,
libxscrnsaver,
libxshmfence,
libxtst,
version,
url,
hash,
passwordStore ? "gnome-libsecret",
extraFlags ? [ ],
}:
let
runtimeLibs = [
alsa-lib
at-spi2-atk
at-spi2-core
atk
cairo
cups
dbus
expat
fontconfig
freetype
gdk-pixbuf
glib
gtk3
krb5
libdrm
libgbm
libglvnd
libnotify
libsecret
libuuid
libxkbcommon
nspr
nss
pango
zlib
(lib.getLib systemd)
libx11
libxcb
libxcomposite
libxcursor
libxdamage
libxext
libxfixes
libxi
libxkbfile
libxrandr
libxrender
libxscrnsaver
libxshmfence
libxtst
];
in
stdenv.mkDerivation (finalAttrs: {
pname = "qoder";
inherit version;
src = fetchurl {
inherit url hash;
name = "qoder-${version}_amd64.deb";
};
nativeBuildInputs = [
autoPatchelfHook
makeWrapper
wrapGAppsHook3
zstd
];
buildInputs = runtimeLibs;
# dlopen'ed at runtime, so autoPatchelf can't see them in the ELF headers
runtimeDependencies = [
(lib.getLib systemd)
libglvnd
libgbm
];
dontConfigure = true;
dontBuild = true;
dontWrapGApps = true; # wrapped by hand in preFixup
# `ar` comes from stdenv. --no-same-permissions keeps the setuid bit on
# chrome-sandbox from blowing up the build inside the nix sandbox.
unpackPhase = ''
runHook preUnpack
ar x $src
tar -xf data.tar.* --no-same-permissions --no-same-owner
runHook postUnpack
'';
installPhase = ''
runHook preInstall
mkdir -p $out/share/qoder $out/bin
if [ -d usr/share/qoder ]; then
cp -r usr/share/qoder/. $out/share/qoder/
elif [ -d opt/Qoder ]; then
cp -r opt/Qoder/. $out/share/qoder/
elif [ -d opt/qoder ]; then
cp -r opt/qoder/. $out/share/qoder/
else
echo "unexpected .deb layout:" >&2
find . -maxdepth 3 -type d >&2
exit 1
fi
for d in applications icons pixmaps; do
if [ -d "usr/share/$d" ]; then
mkdir -p "$out/share/$d"
cp -r "usr/share/$d/." "$out/share/$d/"
fi
done
# Store paths can never be setuid — drop the helper, use --no-sandbox.
rm -f $out/share/qoder/chrome-sandbox
if [ ! -x $out/share/qoder/qoder ]; then
echo "main binary not where expected:" >&2
ls $out/share/qoder >&2
exit 1
fi
for f in $out/share/applications/*.desktop; do
[ -e "$f" ] || continue
substituteInPlace "$f" \
--replace-quiet "/usr/share/qoder/qoder" "$out/bin/qoder" \
--replace-quiet "/opt/Qoder/qoder" "$out/bin/qoder" \
--replace-quiet "/opt/qoder/qoder" "$out/bin/qoder"
done
runHook postInstall
'';
# preFixup, not installPhase: gappsWrapperArgs is only populated by then.
preFixup = ''
makeWrapper $out/share/qoder/qoder $out/bin/qoder \
"''${gappsWrapperArgs[@]}" \
--prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath runtimeLibs}" \
--set-default NIXOS_OZONE_WL 1 \
--add-flags "--no-sandbox" \
--add-flags "--password-store=${passwordStore}" \
${lib.optionalString (extraFlags != [ ]) ''--add-flags "${lib.escapeShellArgs extraFlags}"''}
'';
meta = {
description = "Qoder — agentic coding IDE, repackaged from the upstream .deb";
homepage = "https://qoder.com";
license = lib.licenses.unfree;
sourceProvenance = [ lib.sourceTypes.binaryNativeCode ];
platforms = [ "x86_64-linux" ];
mainProgram = "qoder";
};
})
+52
View File
@@ -0,0 +1,52 @@
{
config,
lib,
pkgs,
username,
...
}:
{
environment.systemPackages = [
(pkgs.writeShellScriptBin "pve-build" ''
export PATH="${
lib.makeBinPath [
pkgs.jq
pkgs.openssh
]
}:$PATH"
${builtins.readFile ./pve-build.sh}
'')
];
home-manager.users.${username} = {
programs.nushell.extraConfig =
lib.mkIf config.home-manager.users.${username}.programs.nushell.enable
''
def "nu-complete pve-build-cmds" [] {
[build test switch boot check-image deploy-image update-image start-builder build-on activate destroy-builder info]
}
def "nu-complete pve-build-activate" [] {
[test switch boot]
}
extern pve-build [
command?: string@"nu-complete pve-build-cmds"
--machine: string
--pve-host: string
--pve-storage: string
--rootfs-storage: string
--bridge: string
--vmid-start: int
--vmid-floor: int
--rootfs-gib: int
--keep
--local-build
--show-trace
--verbose
--debug
--help(-h)
]
'';
};
}
+1103
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -243,6 +243,9 @@ in {
hl.exec_cmd("waybar")
hl.exec_cmd("mako")
''
+ lib.optionalString hm-cfg.bar.noctalia.enable ''
hl.exec_cmd("noctalia")
''
+ ''
end)
'';
+1 -1
View File
@@ -18,7 +18,7 @@ listener {
listener {
timeout = 300 # 5min
on-timeout = loginctl lock-session # lock screen when timeout has passed
on-timeout = hyprlock # lock screen when timeout has passed
}
# listener {
+100
View File
@@ -0,0 +1,100 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.dov.yubikey;
in {
options.dov.yubikey = {
enable = mkEnableOption "YubiKey integration (PAM U2F + SSH agent)";
pamControl = mkOption {
type = types.enum [ "sufficient" "required" ];
default = "sufficient";
description = ''
PAM control flag for U2F authentication.
- "sufficient": touch YubiKey OR type password (default).
Can't lock yourself out — if the key is missing or not
enrolled, the normal password prompt follows.
- "required": touch YubiKey AND type password (true 2FA).
'';
};
pamServices = mkOption {
type = types.listOf types.str;
default = [ "login" "sudo" ];
description = ''
PAM services to enable U2F for. Scoped per-service rather
than globally so that e.g. sshd is not affected.
'';
};
authFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Central U2F authfile path. When null, uses the default
per-user location (~/.config/Yubico/u2f_keys). Set to a
nix-store path for a central, non-user-writable mapping.
Generate mappings with:
pamu2fcfg -u &lt;username&gt;
'';
};
};
config = mkIf cfg.enable (mkMerge [
{
# --- Shared infrastructure: smart card daemon + device access ---
# hardware.gpgSmartcards installs the CCID udev rules that give
# pcscd permission to open the YubiKey's smart-card USB interface.
hardware.gpgSmartcards.enable = true;
services.pcscd.enable = true;
services.udev.packages = with pkgs; [
yubikey-personalization
libfido2
];
environment.systemPackages = with pkgs; [
yubikey-manager # `ykman` CLI
pam_u2f # `pamu2fcfg` for key enrollment
libfido2 # `fido2-token` management
];
}
# --- PAM U2F: touch YubiKey for login / sudo ---
{
security.pam.u2f = {
enable = true;
control = cfg.pamControl;
settings = {
cue = true; # "Please touch the device."
interactive = true; # "Insert your U2F device, then press ENTER."
nouserok = true; # fall through to password if key not enrolled yet
} // optionalAttrs (cfg.authFile != null) {
inherit (cfg) authFile;
};
};
# Enable U2F per-service, not globally (avoids enabling for sshd).
security.pam.services = genAttrs cfg.pamServices (_: {
u2fAuth = true;
});
}
# --- SSH agent for FIDO2 (-sk) keys ---
# yubikey-agent is incompatible with YubiKey firmware 5.7.x (PIV
# management key auth changed). GPG agent's SSH emulation doesn't
# reliably handle -sk keys. Use the standard OpenSSH agent instead,
# which is the same software stack that created the key.
{
programs.gnupg.agent.enableSSHSupport = mkForce false;
programs.ssh.startAgent = true;
}
]);
}