Compare commits

..

17 commits

Author SHA1 Message Date
Leon Schwarzäugl
9acfc5f934 feat[client,server]: add remote builds, confLib
Some checks failed
Flake check / Check flake (push) Has been cancelled
2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
c20f1b0b59 feat[server]: network management 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
8f833485da chore[server]: improve backup management 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
5b5ef2b9b0 fix[server]: get cache working 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
15e2355406 chore: improve formatting 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
29533d6be6 docs: update resources 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
26f324e66d feat[server]: add minecraft 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
cea2980fef chore[work]: add antigravity 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
3f1dfd5fa9 fix[client]: actually use nix-index-database 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
2538d7c279 feat: improve bootstrapping toolchain 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
118f7a2fe8 feat[client]: use dgx as remote build host 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
00340a9c01 feat[server]: add dns server 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
a8f29d26c6 chore: update flake 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
8803e130cc feat[server]: add kexec tarball for low-ram bootstrap 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
732f4fbd00 feat[server]: add mailserver 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
2cb67804d4 feat[server]: use confLib to manage services 2025-12-02 00:59:27 +01:00
Leon Schwarzäugl
e0480cb6f6 chore: cleanup flake inputs 2025-12-02 00:59:27 +01:00
175 changed files with 13276 additions and 19113 deletions

38
.github/README.md vendored
View file

@ -150,24 +150,26 @@
### Hosts
| Name | Hardware | Use |
|--------------------|-----------------------------------------------------|------------------------------------------------------|
|💻 **pyramid** | Framework Laptop 16, AMD 7940HS, RX 7700S, 64GB RAM | Work laptop |
|💻 **bakery** | Lenovo Ideapad 720S-13IKB | Personal laptop |
|💻 **machpizza** | MacBook Pro 2016 | MacOS reference and build sandbox |
|🏠 **treehouse** | NVIDIA DGX Spark | Workstation, AI playground and home-manager reference|
|🖥️ **winters** | ASRock J4105-ITX, 32GB RAM | Secondary homeserver and data storgae |
|🖥️ **summers** | ASUS Z10PA-D8, 2* Intel Xeon E5-2650 v4, 128GB RAM | Main homeserver running microvms, data storage |
|🖥️ **hintbooth** | HUNSN RM02, 8GB RAM | Router |
|☁️ **milkywell** | Oracle Cloud: VM.Standard.E2.1.Micro | Server for lightweight synchronization tasks |
|☁️ **moonside** | Oracle Cloud: VM.Standard.A1.Flex, 4 OCPUs, 24GB RAM| Proxy for local services, some lightweight services |
|☁️ **belchsfactory**| Oracle Cloud: VM.Standard.A1.Flex, 4 OCPUs, 24GB RAM| Hydra builder and nix binary cache |
|☁️ **monkeycave** | Oracle Cloud: VM.Standard.A1.Flex, 4 OCPUs, 24GB RAM| Gaming server |
|☁️ **eagleland** | Hetzner Cloud: CX23 | Mail server |
|📱 **magicant** | Samsung Galaxy Z Flip 6 | Phone |
|💿 **drugstore** | - | ISO installer configuration |
|❔ **chaotheatre** | - | Demo config for checking out my configurtion |
|❔ **toto** | - | Helper configuration for bootstrapping a new system |
| Name | Hardware | Use |
|---------------------|-----------------------------------------------------|-----------------------------------------------------|
|💻 **pyramid** | Framework Laptop 16, AMD 7940HS, RX 7700S, 64GB RAM | Work laptop |
|💻 **bakery** | Lenovo Ideapad 720S-13IKB | Personal laptop |
|💻 **machpizza** | MacBook Pro 2016 | MacOS reference and build sandbox |
|🏠 **treehouse** | NVIDIA DGX Spark | AI Workstation, remote builder, hm-only-reference |
|🖥️ **summers** | ASUS Z10PA-D8, 2* Intel Xeon E5-2650 v4, 128GB RAM | Homeserver (microvms), remote builder, datastorage |
|🖥️ **winters** | ASRock J4105-ITX, 32GB RAM | Homeserver (IoT server in spe) |
|🖥️ **hintbooth** | HUNSN RM02, 8GB RAM | Router |
|☁️ **stoicclub** | Cloud Server: 1 vCPUs, 8GB RAM | Authoritative dns server |
|☁️ **liliputsteps** | Cloud Server: 1 vCPUs, 8GB RAM | SSH bastion |
|☁️ **twothreetunnel**| Cloud Server: 2 vCPUs, 8GB RAM | Service proxy |
|☁️ **eagleland** | Cloud Server: 2 vCPUs, 8GB RAM | Mailserver |
|☁️ **moonside** | Cloud Server: 4 vCPUs, 24GB RAM | Gaming server, syncthing + lightweight services |
|☁️ **belchsfactory** | Cloud Server: 4 vCPUs, 24GB RAM | Hydra builder and nix binarycache |
|📱 **magicant** | Samsung Galaxy Z Flip 6 | Phone |
|💿 **drugstore** | - | NixOS-installer ISO for bootstrapping new hosts |
|💿 **brickroad** | - | Kexec tarball for bootstrapping low-memory machines |
|❔ **chaotheatre** | - | Demo config for checking out this configuration |
|❔ **toto** | - | Helper configuration for testing purposes |
</details>
## General Nix tips & useful links

View file

@ -7,12 +7,16 @@ keys:
- &swarsel 4BE7925262289B476DBBC17B76FD3810215AE097
- &hosts
- &winters age1h72072slm2pthn9m2qwjsyy2dsazc6hz97kpzh4gksvv0r2jqecqul8w63
- &twothreetunnel age1g7atkxdlt4ymeh7v7aa2yzr2hq2qkvzrc4r49ugttm3n582ymv9qrmpk8d
- &liliputsteps age1ly2endyt0y9xyddj6yuj4nw6fa3ltvzlvew4cr4lzs6dv8dkavpqadmyxx
- &stoicclub age15klj4t7gpfp69472mne4ue62pp6m4e04dmjyw7yf30qtqd3vl3uqjmcyxm
- &belchsfactory age1k73gy5em3js9zklnnkzp5hme9k04lny32fgahmzddknjw5c295asdyr4x6
- &eagleland age1cmzh82q8k59yzceuuy2epmqu22g7m84gqvq056mhgehwpmvjadfsc3glc8
- &hintbooth age1hsumymvh5mkqlaynrp9lv2w696yk3wtjzlyfmrpeuvh9u2tlwceqh3563x
- &bakery age1mjgw3nxlnqdj04mgjz3wn7fj2nl2nxla4p2r2fn4nkvayfgp09pqllxzyh
- &toto age16vzhcvz8tyxj8e0f47fy0z4p3dsg0ak4vl52ut3l07a0tz465cxslmhevl
- &surface age1zlnxraee6tddr07xn59mx5rdexw8qxryd53eqlsajasfhfy78fkq705dfg
- &nbl age16lnmuuxfuxxtty3atnhut8wseppwnhp7rdhmxqd5tdvs9qnjffjq42sqyy
- &milkywell age1glge4e97vgqzh332mqs5990vteezu2m8k4wq3z35jk0q8czw3gks2d7a3h
- &moonside age18quey88vge7xytclg2nuq4ncme86dg04lxwczqxczmdchnjg3p0saehsnh
creation_rules:
- path_regex: secrets/general/[^/]+\.(yaml|json|env|ini)$
@ -21,12 +25,16 @@ creation_rules:
- *swarsel
age:
- *winters
- *twothreetunnel
- *liliputsteps
- *stoicclub
- *belchsfactory
- *eagleland
- *hintbooth
- *bakery
- *toto
- *surface
- *nbl
- *milkywell
- *moonside
- path_regex: secrets/repo/[^/]+$
key_groups:
@ -34,12 +42,16 @@ creation_rules:
- *swarsel
age:
- *winters
- *twothreetunnel
- *liliputsteps
- *stoicclub
- *belchsfactory
- *eagleland
- *hintbooth
- *bakery
- *toto
- *surface
- *nbl
- *milkywell
- *moonside
- path_regex: secrets/certs/[^/]+\.(yaml|json|env|ini)$
key_groups:
@ -47,6 +59,11 @@ creation_rules:
- *swarsel
age:
- *nbl
- *twothreetunnel
- *liliputsteps
- *stoicclub
- *belchsfactory
- *eagleland
- *hintbooth
- *bakery
- *toto
@ -86,6 +103,19 @@ creation_rules:
age:
- *moonside
- path_regex: secrets/belchsfactory/secrets.yaml
key_groups:
- pgp:
- *swarsel
age:
- *belchsfactory
- path_regex: hosts/nixos/aarch64-linux/belchsfactory/secrets/pii.nix.enc
key_groups:
- pgp:
- *swarsel
age:
- *belchsfactory
- path_regex: secrets/bakery/secrets.yaml
key_groups:
- pgp:
@ -111,20 +141,61 @@ creation_rules:
- *swarsel
age:
- *winters
- *moonside
- path_regex: secrets/milkywell/[^/]+\.(yaml|json|env|ini)$
- path_regex: secrets/eagleland/[^/]+\.(yaml|json|env|ini)$
key_groups:
- pgp:
- *swarsel
age:
- *milkywell
- path_regex: hosts/nixos/aarch64-linux/milkywell/secrets/pii.nix.enc
- *eagleland
- path_regex: hosts/nixos/x86_64-linux/eagleland/secrets/pii.nix.enc
key_groups:
- pgp:
- *swarsel
age:
- *milkywell
- *eagleland
- path_regex: secrets/stoicclub/[^/]+\.(yaml|json|env|ini)$
key_groups:
- pgp:
- *swarsel
age:
- *stoicclub
- path_regex: hosts/nixos/aarch64-linux/stoicclub/secrets/pii.nix.enc
key_groups:
- pgp:
- *swarsel
age:
- *stoicclub
- path_regex: secrets/liliputsteps/[^/]+\.(yaml|json|env|ini)$
key_groups:
- pgp:
- *swarsel
age:
- *liliputsteps
- path_regex: hosts/nixos/aarch64-linux/liliputsteps/secrets/pii.nix.enc
key_groups:
- pgp:
- *swarsel
age:
- *liliputsteps
- path_regex: secrets/twothreetunnel/[^/]+\.(yaml|json|env|ini)$
key_groups:
- pgp:
- *swarsel
age:
- *twothreetunnel
- path_regex: hosts/nixos/aarch64-linux/twothreetunnel/secrets/pii.nix.enc
key_groups:
- pgp:
- *swarsel
age:
- *twothreetunnel
- path_regex: hosts/nixos/x86_64-linux/summers/secrets/
key_groups:

File diff suppressed because it is too large Load diff

View file

@ -236,6 +236,48 @@ create a new one."
(add-hook 'minibuffer-setup-hook #'swarsel/minibuffer-setup-hook)
(add-hook 'minibuffer-exit-hook #'swarsel/minibuffer-exit-hook)
(defun swarsel/org-colorize-outline (parents raw)
(let* ((palette ["#58B6ED" "#8BD49C" "#33CED8" "#4B9CCC"
"yellow" "orange" "salmon" "red"])
(n (length parents))
(colored-parents
(cl-mapcar
(lambda (p i)
(propertize p 'face `(:foreground ,(aref palette (mod i (length palette))) :weight bold)))
parents
(number-sequence 0 (1- n)))))
(concat
(when parents
(string-join colored-parents "/"))
(when parents "/")
(propertize raw 'face `(:foreground ,(aref palette (mod n (length palette)))
:weight bold)))))
(defun swarsel/org-insert-link-to-heading ()
(interactive)
(let ((candidates '()))
(org-map-entries
(lambda ()
(let* ((raw (org-get-heading t t t t))
(parents (org-get-outline-path t))
(m (copy-marker (point)))
(colored (swarsel/org-colorize-outline parents raw)))
(push (cons colored m) candidates))))
(let* ((choice (completing-read "Heading: " (mapcar #'car candidates)))
(marker (cdr (assoc choice candidates)))
id raw-heading)
(unless marker
(user-error "No marker for heading??"))
(save-excursion
(goto-char marker)
(setq id (prot-org--id-get))
(setq raw-heading (org-get-heading t t t t)))
(insert (org-link-make-string (format "#%s" id)
raw-heading)))))
;; Make ESC quit prompts
(global-set-key (kbd "<escape>") 'keyboard-escape-quit)
@ -334,6 +376,7 @@ create a new one."
"<DUMMY-m>" 'swarsel/last-buffer
"M-\\" 'indent-region
"M-r" 'swarsel/consult-magit-repos
"M-i" 'swarsel/org-insert-link-to-heading
"<Paste>" 'yank
"<Cut>" 'kill-region
"<Copy>" 'kill-ring-save
@ -348,12 +391,12 @@ create a new one."
;; set Nextcloud directory for journals etc.
(setq
swarsel-emacs-directory "~/.emacs.d"
swarsel-dotfiles-directory "~/.dotfiles"
swarsel-dotfiles-directory (getenv "FLAKE")
swarsel-swarsel-org-filepath (expand-file-name "SwarselSystems.org" swarsel-dotfiles-directory)
swarsel-tasks-org-file "Tasks.org"
swarsel-archive-org-file "Archive.org"
swarsel-work-projects-directory "~/Documents/Work"
swarsel-private-projects-directory "~/Documents/Private"
swarsel-work-projects-directory (getenv "DOCUMENT_DIR_WORK")
swarsel-private-projects-directory (getenv "DOCUMENT_DIR_PRIV")
)
;; Change the user-emacs-directory to keep unwanted things out of ~/.emacs.d
@ -384,7 +427,7 @@ create a new one."
;; use UTF-8 everywhere
(set-language-environment "UTF-8")
(profiler-start 'cpu)
;; (profiler-start 'cpu)
;; set default font size
(defvar swarsel/default-font-size 130)
(setq swarsel-standard-font "FiraCode Nerd Font Mono"
@ -1158,9 +1201,13 @@ create a new one."
(setq elfeed-protocol-enabled-protocols '(fever))
(setq elfeed-protocol-fever-update-unread-only t)
(setq elfeed-protocol-fever-fetch-category-as-tag t)
(setq elfeed-protocol-feeds '(("fever+https://Swarsel@signpost.swarsel.win"
:api-url "https://signpost.swarsel.win/api/fever.php"
:password-file "~/.emacs.d/.fever")))
(let ((domain (getenv "SWARSEL_RSS_DOMAIN")))
(setq elfeed-protocol-feeds
`((,(concat "fever+https://Swarsel@" domain)
:api-url ,(concat "https://" domain "/api/fever.php")
:password-file "~/.emacs.d/.fever"))))
(define-key elfeed-show-mode-map (kbd ";") 'visual-fill-column-mode)
(define-key elfeed-show-mode-map (kbd "j") 'elfeed-goodies/split-show-next)
@ -1668,7 +1715,7 @@ create a new one."
:init
;; set org-caldav-sync-initalization
(setq swarsel-caldav-synced 0)
;; (setq org-caldav-url "https://schedule.swarsel.win/swarsel/calendar")
;; (setq org-caldav-url "https://cal.example.org/swarsel/calendar")
;; (setq org-caldav-calendars
;; '((:calendar-id "personal"
;; :inbox "~/Calendars/leon_cal.org")))
@ -1731,59 +1778,66 @@ create a new one."
:config
(dashboard-setup-startup-hook)
;; (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*")))
(setq dashboard-display-icons-p t ;; display icons on both GUI and terminal
dashboard-icon-type 'nerd-icons ;; use `nerd-icons' package
dashboard-set-file-icons t
dashboard-items '((recents . 5)
(projects . 5)
(agenda . 5))
dashboard-set-footer nil
dashboard-banner-logo-title "Welcome to SwarsEmacs!"
dashboard-image-banner-max-height 300
dashboard-startup-banner "~/.dotfiles/files/wallpaper/swarsel.png"
dashboard-projects-backend 'projectile
dashboard-projects-switch-function 'magit-status
dashboard-set-navigator t
dashboard-startupify-list '(dashboard-insert-banner
dashboard-insert-newline
dashboard-insert-banner-title
dashboard-insert-newline
dashboard-insert-navigator
dashboard-insert-newline
dashboard-insert-init-info
dashboard-insert-items
)
dashboard-navigator-buttons
`(;; line1
((,""
"SwarselSocial"
"Browse Swarsele"
(lambda (&rest _) (browse-url "instagram.com/Swarsele")))
(,""
"SwarselSound"
"Browse SwarselSound"
(lambda (&rest _) (browse-url "sound.swarsel.win")) )
(,""
"SwarselSwarsel"
"Browse Swarsel"
(lambda (&rest _) (browse-url "github.com/Swarsel")) )
(,""
"SwarselStash"
"Browse SwarselStash"
(lambda (&rest _) (browse-url "stash.swarsel.win")) )
(,"󰫑"
"SwarselSport"
"Browse SwarselSports"
(lambda (&rest _) (browse-url "social.parkour.wien/@Lenno")))
)
(
(,"󱄅"
"swarsel.win"
"Browse swarsel.win"
(lambda (&rest _) (browse-url "swarsel.win")))
)
)))
(let ((files-domain (getenv "SWARSEL_FILES_DOMAIN"))
(music-domain (getenv "SWARSEL_MUSIC_DOMAIN"))
(insta-domain (getenv "SWARSEL_INSTA_DOMAIN"))
(sport-domain (getenv "SWARSEL_SPORT_DOMAIN"))
(swarsel-domain (getenv "SWARSEL_DOMAIN"))
)
(setq dashboard-display-icons-p t ;; display icons on both GUI and terminal
dashboard-icon-type 'nerd-icons ;; use `nerd-icons' package
dashboard-set-file-icons t
dashboard-items '((recents . 5)
(projects . 5)
(agenda . 5))
dashboard-set-footer nil
dashboard-banner-logo-title "Welcome to SwarsEmacs!"
dashboard-image-banner-max-height 300
dashboard-startup-banner "~/.dotfiles/files/wallpaper/swarsel.png"
dashboard-projects-backend 'projectile
dashboard-projects-switch-function 'magit-status
dashboard-set-navigator t
dashboard-startupify-list '(dashboard-insert-banner
dashboard-insert-newline
dashboard-insert-banner-title
dashboard-insert-newline
dashboard-insert-navigator
dashboard-insert-newline
dashboard-insert-init-info
dashboard-insert-items
)
dashboard-navigator-buttons
`(;; line1
((,""
"SwarselSocial"
"Browse Swarsele"
(lambda (&rest _) (browse-url ,insta-domain)))
(,""
"SwarselSound"
"Browse SwarselSound"
(lambda (&rest _) (browse-url ,(concat "https://" music-domain))) )
(,""
"SwarselSwarsel"
"Browse Swarsel"
(lambda (&rest _) (browse-url "https://github.com/Swarsel")) )
(,""
"SwarselStash"
"Browse SwarselStash"
(lambda (&rest _) (browse-url ,(concat "https://" files-domain))) )
(,"󰫑"
"SwarselSport"
"Browse SwarselSports"
(lambda (&rest _) (browse-url ,sport-domain)))
)
(
(,"󱄅"
,swarsel-domain
,(concat "Browse " main-domain)
(lambda (&rest _) (browse-url ,(concat "https://" swarsel-domain))))
)
))))
(use-package vterm
:ensure t)

View file

@ -60,8 +60,10 @@ See the above repository for updates as well as full license text. */
transform-origin: 0px calc(0px - var(--tab-min-height) - var(--tab-block-margin) * 2);
transform: rotateX(89.9deg);
}
#mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts,#selection-shortcut-action-panel,#chat-shortcuts-options-panel,#tab-preview-panel)) ~ toolbox #urlbar[popover],
/* swarsel: removed :hover from below line */
:root[window-modal-open] #urlbar[popover],
#mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts,#selection-shortcut-action-panel,#chat-shortcuts-options-panel,#tab-preview-panel), > #tab-group-editor > [panelopen]) ~ toolbox #urlbar[popover],
/* swarsel: removed :hover from below line */
#navigator-toolbox:is(:focus-within,[movingtab]) #urlbar[popover],
#urlbar-container > #urlbar[popover]:is([focused],[open]){
pointer-events: auto;
@ -69,9 +71,11 @@ See the above repository for updates as well as full license text. */
transition-delay: 33ms;
transform: rotateX(0deg);
}
#mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts,#selection-shortcut-action-panel,#chat-shortcuts-options-panel,#tab-preview-panel)) ~ toolbox,
:root[window-modal-open] #navigator-toolbox,
#mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts,#selection-shortcut-action-panel,#chat-shortcuts-options-panel,#tab-preview-panel), > #tab-group-editor > [panelopen]) ~ toolbox,
#navigator-toolbox:has(#urlbar:is([open],[focus-within])),
/* swarsel: removed :hover from below line */
/* swarsel: removed :hover from below line */
#navigator-toolbox:is(:focus-within,[movingtab]){
transition-delay: 33ms !important;
transform: rotateX(0);
@ -80,8 +84,7 @@ See the above repository for updates as well as full license text. */
/* This makes things like OS menubar/taskbar show the toolbox when hovered in maximized windows.
* Unfortunately it also means that other OS native surfaces (such as context menu on macos)
* and other always-on-top applications will trigger toolbox to show up. */
@media (-moz-bool-pref: "userchrome.autohide-toolbox.unhide-by-native-ui.enabled"),
-moz-pref("userchrome.autohide-toolbox.unhide-by-native-ui.enabled"){
@media -moz-pref("userchrome.autohide-toolbox.unhide-by-native-ui.enabled"){
:root[sizemode="maximized"]:not(:hover){
#navigator-toolbox:not(:-moz-window-inactive),
#urlbar[popover]:not(:-moz-window-inactive){
@ -111,11 +114,7 @@ See the above repository for updates as well as full license text. */
padding-block: calc(min(4px,(var(--urlbar-container-height) - var(--urlbar-height)) / 2) + var(--urlbar-container-padding)) !important;
}
/* Uncomment this if tabs toolbar is hidden with hide_tabs_toolbar.css */
/*#titlebar{ margin-bottom: -9px }*/
/* Uncomment the following for compatibility with tabs_on_bottom.css - this isn't well tested though */
/*
#navigator-toolbox{ flex-direction: column; display: flex; }
#titlebar{ order: 2 }
*/

View file

@ -8,6 +8,8 @@ target_user="swarsel"
ssh_port="22"
persist_dir=""
disk_encryption=0
disk_encryption_args=""
no_disko_deps="false"
temp=$(mktemp -d)
function help_and_exit() {
@ -27,6 +29,7 @@ function help_and_exit() {
echo " Default='${target_user}'."
echo " --port <ssh_port> specify the ssh port to use for remote access. Default=${ssh_port}."
echo " --debug Enable debug mode."
echo " --no-disko-deps Upload only disk script and not dependencies (for use on low ram)."
echo " -h | --help Print this help."
exit 0
}
@ -80,14 +83,14 @@ function update_sops_file() {
SOPS_FILE=".sops.yaml"
sed -i "{
# Remove any * and & entries for this host
/[*&]$key_name/ d;
# Inject a new age: entry
# n matches the first line following age: and p prints it, then we transform it while reusing the spacing
/age:/{n; p; s/\(.*- \*\).*/\1$key_name/};
# Inject a new hosts or user: entry
/&$key_type/{n; p; s/\(.*- &\).*/\1$key_name $key/}
}" $SOPS_FILE
# Remove any * and & entries for this host
/[*&]$key_name/ d;
# Inject a new age: entry
# n matches the first line following age: and p prints it, then we transform it while reusing the spacing
/age:/{n; p; s/\(.*- \*\).*/\1$key_name/};
# Inject a new hosts or user: entry
/&$key_type/{n; p; s/\(.*- &\).*/\1$key_name $key/}
}" $SOPS_FILE
green "Updating .sops.yaml"
cd -
}
@ -114,6 +117,9 @@ while [[ $# -gt 0 ]]; do
shift
ssh_port=$1
;;
--no-disko-deps)
no_disko_deps="true"
;;
--debug)
set -x
;;
@ -131,6 +137,12 @@ if [[ $target_arch == "" || $target_destination == "" || $target_hostname == ""
help_and_exit
fi
LOCKED="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.node.lockFromBootstrapping)"
if [[ $LOCKED == "true" ]]; then
red "THIS SYSTEM IS LOCKED FROM BOOTSTRAPPING"
exit
fi
green "~SwarselSystems~ remote installer"
green "Reading system information for $target_hostname ..."
@ -141,6 +153,11 @@ CRYPTED="$(nix eval ~/.dotfiles#nixosConfigurations."$target_hostname".config.sw
if [[ $CRYPTED == "true" ]]; then
green "Encryption: ✓"
disk_encryption=1
disk_encryption_args=(
--disk-encryption-keys
/tmp/disko-password
/tmp/disko-password
)
else
red "Encryption: X"
disk_encryption=0
@ -233,7 +250,14 @@ $scp_cmd root@"$target_destination":/mnt/etc/nixos/hardware-configuration.nix "$
# ------------------------
green "Deploying minimal NixOS installation on $target_destination"
nix run github:nix-community/nixos-anywhere/1.10.0 -- --ssh-port "$ssh_port" --extra-files "$temp" --flake ./install#"$target_hostname" root@"$target_destination"
if [[ $no_disko_deps == "true" ]]; then
green "Building without disko dependencies (using custom kexec)"
nix run github:nix-community/nixos-anywhere/1.10.0 -- "${disk_encryption_args[@]}" --no-disko-deps --ssh-port "$ssh_port" --extra-files "$temp" --flake ./install#"$target_hostname" --kexec "$(nix build --print-out-paths .#packages."$target_arch".swarsel-kexec)/swarsel-kexec-$target_arch.tar.gz" root@"$target_destination"
else
green "Building with disko dependencies (using nixos-images kexec)"
nix run github:nix-community/nixos-anywhere/1.10.0 -- "${disk_encryption_args[@]}" --ssh-port "$ssh_port" --extra-files "$temp" --flake ./install#"$target_hostname" root@"$target_destination"
fi
echo "Updating ssh host fingerprint at $target_destination to ~/.ssh/known_hosts"
ssh-keyscan -p "$ssh_port" "$target_destination" >> ~/.ssh/known_hosts || true
@ -305,8 +329,8 @@ $ssh_root_cmd "chown $target_user:users /home/$target_user/.ssh/ssh_host_ed25519
if yes_or_no "Add ssh host fingerprints for git upstream repositories? (This is needed for building the full config)"; then
green "Adding ssh host fingerprints for git{lab,hub}"
$ssh_cmd "mkdir -p /home/$target_user/.ssh/; ssh-keyscan -t ssh-ed25519 gitlab.com github.com swagit.swarsel.win | tee /home/$target_user/.ssh/known_hosts"
$ssh_root_cmd "mkdir -p /root/.ssh/; ssh-keyscan -t ssh-ed25519 gitlab.com github.com swagit.swarsel.win | tee /root/.ssh/known_hosts"
$ssh_cmd "mkdir -p /home/$target_user/.ssh/; ssh-keyscan -t ssh-ed25519 gitlab.com github.com | tee /home/$target_user/.ssh/known_hosts"
$ssh_root_cmd "mkdir -p /root/.ssh/; ssh-keyscan -t ssh-ed25519 gitlab.com github.com | tee /root/.ssh/known_hosts"
fi
# --------------------------

14665
flake.lock generated

File diff suppressed because it is too large Load diff

View file

@ -11,100 +11,57 @@
};
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
smallpkgs.url = "github:nixos/nixpkgs/08fcb0dcb59df0344652b38ea6326a2d8271baff?narHash=sha256-HXIQzULIG/MEUW2Q/Ss47oE3QrjxvpUX7gUl4Xp6lnc%3D&shallow=1";
nixpkgs-dev.url = "github:Swarsel/nixpkgs/main";
nixpkgs-kernel.url = "github:NixOS/nixpkgs/063f43f2dbdef86376cc29ad646c45c46e93234c?narHash=sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o%3D"; #specifically pinned for kernel version
nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.05";
nixpkgs-stable24_05.url = "github:NixOS/nixpkgs/nixos-24.05";
nixpkgs-stable24_11.url = "github:NixOS/nixpkgs/nixos-24.11";
nixpkgs-stable25_05.url = "github:NixOS/nixpkgs/nixos-25.05";
systems.url = "github:nix-systems/default";
swarsel-modules.url = "github:Swarsel/swarsel-modules/main";
swarsel-nix.url = "github:Swarsel/swarsel-nix/main";
home-manager = {
# url = "github:nix-community/home-manager";
url = "github:Swarsel/home-manager/main";
inputs.nixpkgs.follows = "nixpkgs";
};
swarsel.url = "github:Swarsel/.dotfiles";
emacs-overlay = {
# url = "github:nix-community/emacs-overlay";
url = "github:nix-community/emacs-overlay/aba8daa237dc07a3bb28a61c252a718e8eb38057?narHash=sha256-4OXXccXsY1sBXTXjYIthdjXLAotozSh4F8StGRuLyMQ%3D";
nix-index-database = {
url = "github:nix-community/nix-index-database";
inputs.nixpkgs.follows = "nixpkgs";
};
# emacs-overlay.url = "github:nix-community/emacs-overlay";
emacs-overlay.url = "github:nix-community/emacs-overlay/aba8daa237dc07a3bb28a61c252a718e8eb38057?narHash=sha256-4OXXccXsY1sBXTXjYIthdjXLAotozSh4F8StGRuLyMQ%3D";
swarsel-nix.url = "github:Swarsel/swarsel-nix/main";
systems.url = "github:nix-systems/default";
nur.url = "github:nix-community/NUR";
nixgl.url = "github:guibou/nixGL";
stylix.url = "github:danth/stylix";
sops-nix.url = "github:Mic92/sops-nix";
lanzaboote.url = "github:nix-community/lanzaboote";
nix-on-droid = {
url = "github:nix-community/nix-on-droid/release-24.05";
inputs.nixpkgs.follows = "nixpkgs";
};
nixos-generators = {
url = "github:nix-community/nixos-generators";
inputs.nixpkgs.follows = "nixpkgs";
};
nixos-hardware = {
url = "github:NixOS/nixos-hardware/master";
};
nswitch-rcm-nix = {
url = "github:Swarsel/nswitch-rcm-nix";
};
nix-index-database = {
url = "github:nix-community/nix-index-database";
inputs.nixpkgs.follows = "nixpkgs";
};
disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-on-droid.url = "github:nix-community/nix-on-droid/release-24.05";
nixos-generators.url = "github:nix-community/nixos-generators";
nixos-images.url = "github:Swarsel/nixos-images/main";
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
nswitch-rcm-nix.url = "github:Swarsel/nswitch-rcm-nix";
disko.url = "github:nix-community/disko";
impermanence.url = "github:nix-community/impermanence";
zjstatus = {
url = "github:dj95/zjstatus";
};
# has been upstreamed
# fw-fanctrl = {
# # url = "github:TamtamHero/fw-fanctrl/packaging/nix";
# url = "github:Swarsel/fw-fanctrl/packaging/nix";
# inputs.nixpkgs.follows = "nixpkgs";
# };
nix-darwin = {
url = "github:lnl7/nix-darwin";
inputs.nixpkgs.follows = "nixpkgs";
};
pre-commit-hooks = {
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
vbc-nix = {
url = "git+ssh://git@github.com/vbc-it/vbc-nix.git?ref=main";
inputs.nixpkgs.follows = "nixpkgs";
};
zjstatus.url = "github:dj95/zjstatus";
nix-darwin.url = "github:lnl7/nix-darwin";
pre-commit-hooks.url = "github:cachix/git-hooks.nix";
vbc-nix.url = "git+ssh://git@github.com/vbc-it/vbc-nix.git?ref=main";
nix-topology.url = "github:oddlama/nix-topology";
flake-parts.url = "github:hercules-ci/flake-parts";
devshell = {
url = "github:numtide/devshell";
inputs.nixpkgs.follows = "nixpkgs";
};
spicetify-nix = {
url = "github:Gerg-l/spicetify-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
niri-flake = {
url = "github:sodiboo/niri-flake";
inputs.nixpkgs.follows = "nixpkgs";
};
nixos-extra-modules = {
url = "github:oddlama/nixos-extra-modules";
inputs.nixpkgs.follows = "nixpkgs";
};
microvm = {
url = "github:astro/microvm.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
devshell.url = "github:numtide/devshell";
spicetify-nix.url = "github:Gerg-l/spicetify-nix";
niri-flake.url = "github:sodiboo/niri-flake";
nixos-extra-modules.url = "github:oddlama/nixos-extra-modules/main";
microvm.url = "github:astro/microvm.nix";
treefmt-nix.url = "github:numtide/treefmt-nix";
dns.url = "github:kirelagin/dns.nix";
nix-minecraft.url = "github:Infinidoge/nix-minecraft";
simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/master";
};
outputs =
inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } {

View file

@ -1,4 +1,4 @@
{ self, ... }:
{ self, pkgs, ... }:
{
imports = [
@ -16,11 +16,15 @@
};
};
home.packages = with pkgs; [
attic-client
];
# programs.zsh.initContent = "
# export GPG_TTY=\"$(tty)\"
# export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
# gpgconf --launch gpg-agent
# ";
swarselmodules.pii = true;
swarselsystems = {
isLaptop = false;

View file

@ -0,0 +1,58 @@
{ self, lib, minimal, ... }:
{
imports = [
./hardware-configuration.nix
./disk-config.nix
"${self}/modules/nixos/optional/systemd-networkd-server.nix"
];
node.lockFromBootstrapping = lib.mkForce false;
topology.self = {
icon = "devices.cloud-server";
};
swarselmodules.server.nginx = false;
swarselsystems = {
flakePath = "/root/.dotfiles";
info = "VM.Standard.A1.Flex, 4 vCPUs, 24GB RAM";
isImpermanence = true;
isSecureBoot = false;
isCrypted = true;
isSwap = false;
rootDisk = "/dev/sda";
isBtrfs = true;
isNixos = true;
isLinux = true;
isCloud = true;
server = {
garage = {
data_dir = {
capacity = "150G";
path = "/var/lib/garage/data";
};
keys = {
nixos = [
"attic"
];
};
buckets = [
"attic"
];
};
};
};
} // lib.optionalAttrs (!minimal) {
swarselprofiles = {
server = true;
};
swarselmodules.server = {
ssh-builder = lib.mkDefault true;
postgresql = lib.mkDefault true;
attic = lib.mkDefault true;
garage = lib.mkDefault true;
};
}

View file

@ -0,0 +1,121 @@
{ lib, pkgs, config, ... }:
let
type = "btrfs";
extraArgs = [ "-L" "nixos" "-f" ]; # force overwrite
subvolumes = {
"/root" = {
mountpoint = "/";
mountOptions = [
"subvol=root"
"compress=zstd"
"noatime"
];
};
"/home" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/home";
mountOptions = [
"subvol=home"
"compress=zstd"
"noatime"
];
};
"/persist" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/persist";
mountOptions = [
"subvol=persist"
"compress=zstd"
"noatime"
];
};
"/log" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/var/log";
mountOptions = [
"subvol=log"
"compress=zstd"
"noatime"
];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = [
"subvol=nix"
"compress=zstd"
"noatime"
];
};
"/swap" = lib.mkIf config.swarselsystems.isSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = config.swarselsystems.swapSize;
};
};
in
{
disko = {
imageBuilder.extraDependencies = [ pkgs.kmod ];
devices = {
disk = {
disk0 = {
type = "disk";
device = config.swarselsystems.rootDisk;
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "defaults" ];
};
};
root = lib.mkIf (!config.swarselsystems.isCrypted) {
size = "100%";
content = {
inherit type subvolumes extraArgs;
postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
MNTPOINT=$(mktemp -d)
mount "/dev/disk/by-label/nixos" "$MNTPOINT" -o subvolid=5
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
'';
};
};
luks = lib.mkIf config.swarselsystems.isCrypted {
size = "100%";
content = {
type = "luks";
name = "cryptroot";
passwordFile = "/tmp/disko-password"; # this is populated by bootstrap.sh
settings = {
allowDiscards = true;
# https://github.com/hmajid2301/dotfiles/blob/a0b511c79b11d9b4afe2a5e2b7eedb2af23e288f/systems/x86_64-linux/framework/disks.nix#L36
crypttabExtraOpts = [
"fido2-device=auto"
"token-timeout=10"
];
};
content = {
inherit type subvolumes extraArgs;
postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
MNTPOINT=$(mktemp -d)
mount "/dev/mapper/cryptroot" "$MNTPOINT" -o subvolid=5
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
'';
};
};
};
};
};
};
};
};
};
fileSystems."/persist".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
fileSystems."/home".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
}

View file

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

View file

@ -0,0 +1,22 @@
{
"data": "ENC[AES256_GCM,data:8qaX0CjyxK8qoAyVyxwfXlejWyGSY579EVmmUCi9PPyB5LyPjfDvXxlRFCOlC6eYbSJ1AWLqqZ6yYgZaimUHkOTh7dL+D4wSkmGeRnxZoQhq9n9sYZPJUfqEhMwEGxlrAvchXJuruZG+Tp9+Ev0if9f9J9qdU1y+yLGQxc2vnibMg2uxdpfYjHaDWa9bybRQZxINkD//um8uxkRs0xvWgZu63ReQZMPjx9K3vNtdJTZsW5+ZUB368QA2mnry2Zf60PWJT/+NsNKIwyzjhUNJ/eTFxjNJ4zPj/AnXFezfGvpVu6XFYsLk5uPb3XfpUlCj4mTVvmVlA40lf4rOhyoRRAW8d28puJArBf3nPzIkWQUfmFwO5EE3qPDkjMlaRa/RdRx0dvrbLDv7Ujt1XaK8bl3Vkz77oumCYFPV7J4mAeu3/LFBAoWKik6Wj8WQE+QwUWo=,iv:ZQaOO2Blpqn+Xnzt4fcPu+rNAvEdluwJEYRxPVItLcU=,tag:rKJ5g27ZK1wCpcyCVfffpA==,type:str]",
"sops": {
"age": [
{
"recipient": "age1k73gy5em3js9zklnnkzp5hme9k04lny32fgahmzddknjw5c295asdyr4x6",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzbi9PZkRob2JkcjlEMUJu\nSG5TemplWkhWVXZNWStCVXhrUlFRSUtPeWk4CjZEQVN4b1lYVkxYQmU0SEJ0QnAv\nTE9IdHZUYmVjb0hxSno1QWxGN1ZMUFEKLS0tIEwrVU5uZmZPRGdZcjVsVk1IQ1Vv\nRXdMcW0xR2g5SCswKzF5RkIwUmtocDgKVI/EMQuvfKGeJH7wFm8VP5rKLhYKOlPt\nA+QIDAdrtFogW9Swwhzxu1tIOfMXzfyW9P+ec/b6/vU96PMqJQ6ZGg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-11-28T14:15:06Z",
"mac": "ENC[AES256_GCM,data:TxnVPtRHzUEr9StM3RlOgqD11036yM74HL1Q8ZkNSU89geAaUoDj8LJD1QKglDT5UNzfKeaZD4DT6bqill+H5FUuonOgLPxNoFKMyWhppQkMWM5F/bw8JUulacmE28b2Rd5zRVOYe3TkE11kMAbxRD+CvqEFBrLsZAndr9QdfUc=,iv:uzjzk1FUN52oAE0cuw7OLLmMRxE/VLQ+tUExxYQjwTQ=,tag:+BOG6wRb0h/jhyy7l8ZA/A==,type:str]",
"pgp": [
{
"created_at": "2025-11-25T18:32:49Z",
"enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ/+Mi33CAnGK/475xmMlZn2P4aR2iFjWFms6XU540JZnfQi\nF6/bjq1otgxGlnR6x3zhPQU3whCQIv538UeiYWMoS8oPxj5b5eF33agihYaCq2wx\nHv4p0+hOJMl2SJPCHfmTkClqYGYMOzTPe1g6oiY0N3FWVoiWXdbWNkIGVNjgkedz\n5f9JPFWn6iB/Z07qUMwG2OOzh8ZPlh/PgNCBrCVMUYrD/FrAck389uMw4yHFz8AV\n3ETnx2gHFTwL5F8H7x3uVungoBVCJk+NpXiKS6nVKwH4jliydiU2ZClSzjHpCqCW\nd365MCahC67IkuCkWhwuPwDaKIk7Qw4rZaLybcad5/TQ0zT+XCm6/2DYIYTj2gip\nqrBDZxHZhkpYcArjckWDRchO9t9E/c3qJfD1Zxi6fBz0vu2WcCuTT8Qd6Zn+DlMb\nVr0D2LPlZGRJ+kM9xuZXaY1bGNAA2POvLn698prPuTkMNxidQEhPNuNy4PlYKXAP\nFfRzJ5zFUneW19j8SgL6BxfLoYDFWkoHIutNDH5H290MJqnFDUrQ5bQn8odM+1OL\noJ1AchHN3J0J5aa2Z8X0NSVN7N0TmU3xVZ1GmfdqbH+3V+OR3NMgJ/FKMQEutT56\nAsBc7tSHtJGaRS9plJ+RryuPRRnqGmRkS3vVmBkrD+pY/TwUbXUBKjEOWhq9uwiF\nAgwDC9FRLmchgYQBEACD1XnsK/sTsgtvt69H/aBHWVIWQNTmdhwJBUHmqkusFhPf\nXxfGN+bvapWulYI+Wb4LAQQbUhMmz8drPnWpCEobS3LSeU8CDD3wBrGAJubI7YLK\nttn4oB7XK5mrg9SIQ8M8kOElv19oCMudkX8dRs4gs0TBO6jbr7/lsiyL/sN3Ylk+\nnyORFeSgE9vVcvJ8QnIF+MQXF9Re61zJFqjXiDMEklzbHHVeLzS5IlYgJoDvV3Gg\n9lTtvdO/FV5JtjFeYI16rjPb7ip/KtljU5pBM8wp6VU4Dre0VsRBgztm279g+WaL\nDJuf6lmfwNSk66tiLpsaJoEu7A+UhLURI10cv92E7fydbGRZMgSjK6ZK4Ue6WH1U\nYQJenngZPXcRcqfCeTVTjzG6ikL3aCfvbuJ3/oT8Y8oBA5Ch2PG7fWAJMMUVIFAM\nLO8KqCSdRCoJrJ69s8iyBycOhPhMiwLZU2HLlMux/kLq5OB2JMGm8P4nxoXTp9Dz\n2TPoPigZritYHsIXZ3cM2iR3OL3AiotKlaIp74ElUeuc0K+Bcp1C//OtKTPuYGnc\n0ttC/dx3c9vv6W80JJ6i7bCRoDiuGrrdx783ly2br4VLDFSaS8rNbrM5ccSTVImw\nUFxZO9rLO0n7N6z4hlgrKw3G1SWKYqbgOVXxIog7st8JvmPLQZYjEuH9Xwq6WdJc\nAU2esxsAaDKyIPHg+DAXOPBagzU1tBKFYtwaiFVDqYk5gNE/2hAnKcuU7O3sua1q\ntsgL2kY8VSHcFFv8N6FhDYPdCrDgAwOtJSZGf7uV92q7/vbMWx+vGq/7FaQ=\n=m1sm\n-----END PGP MESSAGE-----",
"fp": "4BE7925262289B476DBBC17B76FD3810215AE097"
}
],
"unencrypted_suffix": "_unencrypted",
"version": "3.11.0"
}
}

View file

@ -0,0 +1,41 @@
{ self, lib, minimal, ... }:
{
imports = [
./hardware-configuration.nix
./disk-config.nix
"${self}/modules/nixos/optional/systemd-networkd-server.nix"
];
topology.self = {
icon = "devices.cloud-server";
};
swarselsystems = {
flakePath = "/root/.dotfiles";
info = "VM.Standard.A1.Flex, 1 vCPUs, 8GB RAM";
isImpermanence = true;
isSecureBoot = false;
isCrypted = true;
isSwap = false;
rootDisk = "/dev/disk/by-id/scsi-360fb180663ec4f2793a763a087d46885";
isBtrfs = true;
isNixos = true;
isLinux = true;
isCloud = true;
mainUser = "jump";
};
} // lib.optionalAttrs (!minimal) {
swarselprofiles = {
server = true;
};
swarselmodules.server = {
nginx = false;
bastion = true;
# ssh = false;
};
# users.users.swarsel.enable = lib.mkForce false;
# home-manager.users.swarsel.enable = lib.mkForce false
}

View file

@ -0,0 +1,121 @@
{ lib, pkgs, config, ... }:
let
type = "btrfs";
extraArgs = [ "-L" "nixos" "-f" ]; # force overwrite
subvolumes = {
"/root" = {
mountpoint = "/";
mountOptions = [
"subvol=root"
"compress=zstd"
"noatime"
];
};
"/home" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/home";
mountOptions = [
"subvol=home"
"compress=zstd"
"noatime"
];
};
"/persist" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/persist";
mountOptions = [
"subvol=persist"
"compress=zstd"
"noatime"
];
};
"/log" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/var/log";
mountOptions = [
"subvol=log"
"compress=zstd"
"noatime"
];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = [
"subvol=nix"
"compress=zstd"
"noatime"
];
};
"/swap" = lib.mkIf config.swarselsystems.isSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = config.swarselsystems.swapSize;
};
};
in
{
disko = {
imageBuilder.extraDependencies = [ pkgs.kmod ];
devices = {
disk = {
disk0 = {
type = "disk";
device = config.swarselsystems.rootDisk;
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "defaults" ];
};
};
root = lib.mkIf (!config.swarselsystems.isCrypted) {
size = "100%";
content = {
inherit type subvolumes extraArgs;
postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
MNTPOINT=$(mktemp -d)
mount "/dev/disk/by-label/nixos" "$MNTPOINT" -o subvolid=5
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
'';
};
};
luks = lib.mkIf config.swarselsystems.isCrypted {
size = "100%";
content = {
type = "luks";
name = "cryptroot";
passwordFile = "/tmp/disko-password"; # this is populated by bootstrap.sh
settings = {
allowDiscards = true;
# https://github.com/hmajid2301/dotfiles/blob/a0b511c79b11d9b4afe2a5e2b7eedb2af23e288f/systems/x86_64-linux/framework/disks.nix#L36
crypttabExtraOpts = [
"fido2-device=auto"
"token-timeout=10"
];
};
content = {
inherit type subvolumes extraArgs;
postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
MNTPOINT=$(mktemp -d)
mount "/dev/mapper/cryptroot" "$MNTPOINT" -o subvolid=5
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
'';
};
};
};
};
};
};
};
};
};
fileSystems."/persist".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
fileSystems."/home".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
}

View file

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

View file

@ -0,0 +1,22 @@
{
"data": "ENC[AES256_GCM,data:GntHmFTkr7OKUlAVPP1aPeGJEoM1/W9xoZzdXG/udBrKB8eadaOsdsT9/I4Q4zydLnAUZAb+k+/pu3inqiGPClNWU0LUMj7wTwPuVe57EyLaO2oaN4z2nvWhJnwfatvdLrFICz3MN7XLnpEe3D+3ovN2hmys1pd6cAJtEKDtmLJ3RNAhEXrMwOZ0MSzylApoi9yXULH8PqNBX7jPOZYYZ0jlnIbZB267Ln19ES0bZcK7L0608NdB+Q3xb3TQ+oSfnvsdxKyPkPqjxAto40feG97UYVW6AgYV1KlRp9etjEhIRZgn1qDvigGM/Y4HLgLxPM83h79LIVHDj1OySMyYR4bfwAR1U+Ij2nX0Wv6Q/nKx0Nmghen40AqLYp762ACLVRd30DALthhtMxhsiYIT6za3dNFRNnL1Lfss1+IwDm+XHBehBQsjXbs06nZcQURfszW03Y9KH1h5ePIS93gmkdUyH5Ya1JT609s8faukz4fcNmnXlZcnCW4fUawW3YS1zpWPGDNm54GFI06vii5JuVORrf6m2HJEIyYSzeYASC+rZOfEF8gXGjyaeh/B9nAzSq2Q/Nfm+fsceXfOkhD+ZD/nYg+whYPPfA38B5oWvwnSNRNipJLYVvdLLd6M9pTV2FHuEsFKpXwumuwMAhl287jpDVb5B6gYPnWm4zOXYX3KXd68KVFNOGCC1XrrlqVBwQqraozD+1e77eCK4OEyF8R2Wt+mCFDwrMp5hKiiFCHEX67RYqWwmZVx2hS1bovBfacoXknUaSQnfpUd5GYIVYqonyqo6cdn6LKR/0d+7wR+JuL+PO83XcEQvegfHXAXmxIEzPdsL2PqVWGL2B/qyyAZGb3hoY7hmrpEeCCefYhSkxewVDCuvL7xLBCFjq0PsPJw0CqYE0KDIgXxcGLQ5f+pn6O07YDfN+7PVPrPAaN/UTwd+2Xa9UfVELdKKhAWiywsiDCUVO9vkpvgSoYYSrtB8Ceg3RXWohbO8VrjF6UhUxnslAw8TBnBx4FtaSuI73UiJnkg9V1es47NmOA7,iv:JYRzdtAYu24aWIL/hfWLbkS8xpcPw3ylZROuuUMVmIY=,tag:Ot7G/QiTLhmnlYe7Z9aOTQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age1ly2endyt0y9xyddj6yuj4nw6fa3ltvzlvew4cr4lzs6dv8dkavpqadmyxx",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGVU5HTGhyL0ZBRXkzZ3hq\ndzBMd1JZTktZbWNFMGRzcXhFK3RHb090cFdBCmpMa0FNMWFCenBjYk9FaDIrTkFS\nSnN6S210ejN5SVVhd2FWRG1SUHB4WWcKLS0tIDV2K0h1QWxwUXkwVnZlYnR6eEtl\nUVR0UGJOR1hadUtNcjYyWE9wblAwWFUKVM+J/pqtZFADYTQHfWCdvPzlhtgR6zAy\nu0EWk77+K2J0GeBuDr1W5yblUCknht6WZCJZcO6fW7AuWSQK3e/EVA==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-12-01T16:51:40Z",
"mac": "ENC[AES256_GCM,data:SWLGPgFcdiGSvN5BTmE8Nq7+pBiNJM05H1hhqJY6wJqYZehKhQrQRj6/DSlYWPvYE/DdWo5Tiuc3RNY3NANwhki+7kl0OBxHoaHqBgOTa96rdPwe6V3s55v++jtm0xg/qLHEPCqrKqw/aiBAQLJkDOh/IykeEXBMW3S6EM+aQ0U=,iv:2wn4jQHdWWhIzOyGhZxow8WG6W0VgA2gwhb5X+k9ja0=,tag:8g4wQb0u7vbIPkVX8Ey0eA==,type:str]",
"pgp": [
{
"created_at": "2025-12-01T15:59:42Z",
"enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ//cl6I+s/JLwwTCX7WKdzeOIkrsK9DpY3pXBuzoZRSRSJE\nwFJO99Uc7/uH1DSsEB/25CWI6eWx7k6l7YDbcbXQgi5ZNoAt7BePeCu2LK/3coZB\nJe4SManP0sPqxrSd92Tnm6Zl9EL4cJ/5D2C2RBTWOaOtZHR8gyxx5+rzCotCoTXA\nJseGE4B8r/M0O7PAS9+oD14AwCndhuvkmFOq0Y1/wXldV6yCdgc//0oJBSTCBJUZ\nYMSQLovEYGvF9bFfpWYU8J53WqlGn7QKVccDN0/gfi8IVGVZGccUA58VaVqkzR41\ndYlRZ/sjtd+VXmOg8Fx79bOlzTn+RBCp9y+q5yKnzUKGe0/Lrnt6+j7+ieIowi76\npBd0bEaoh6wqdCJ7GSjsj5kdSXRop3Ae0ff+J0pBQNctehpcWj5/TpeA1zyslwEC\nD1B/KVN+Gh0XBCg636dUkt2E4NPNDckSRuvTLy+8IkTm7aQqTjqDu3WUOSPzZiZK\nBUGZWwXAS+xPPMH26X6gPTfZj+7Gdv6yxTVIwkphDbWfihxIP//WNbKX1QN4VSHf\nCmoPOrriIdgZ7d2olZEJxPgEVzavkRkiMSFQbQgzjx5Af3ccdav3mxlubjXldmpe\n689Joj8cgBPg1Yfk/yl7tVK9TFJgYXTqKfsXwscrSlsV+dRAN0pHuq1uo9cTE/SF\nAgwDC9FRLmchgYQBEADCJ5IVMNp+PgUDOiajCfpNq3/HsntzIWG0tIjCb5L9TFWQ\nMA2LQWhcU5CRBh7Sakf8IFi/U40SD+dILUh8JR/7g2i9mCS+1e0pkUwSIYxzAI+z\nQeycuyOrdQJFrk+nFbTdZVAerElxew/wQUiC2uoI8tA5+XyNeNfipaptPh9FpFuz\nXhFbkZDJ4kapGzsAn4FgUdmdqAgZ5n2W46WAmDmVKM0W1F0zZdkBEdkEKkv1gRpZ\nRntb/mVEiGAdXv6yAzvHrxgIBkxazzstRmCMXa252RUIakXqvkP1vw7B6ChSFQR+\nq9WNo9x0EYXivd/+ROjHT7WNhEToWems/3CQpQd1LEFXajLdpAWd875acqhBJqtY\nkpKqUG5F4JmTZ7hMuGI0g30nOofMtmFhDX/gCpJ97lEudHyNrHe0KWaQAwtRknz+\nrcPrZQmGRRcf4xcBVe/EDUNlkp9fPWEhFAwKMsVkkvCAADZbvdhLR6URJMmUj5KG\nOuwglHnSOMxCovAQUd3vCtNkkAnRPNOW/WMThr+qfjq8oKdDIaYBxjzjSz1FIsho\nKiz4W3flRzUcALjKTXadQl/jJEhpP3C6Ivh0d29SiKyrWG+Y4KlDIRctub9UjH46\nb2wqbnBzSrC8u9xJINIB4yryXsZiQyP5b39guSKIPjURebus7LBxq+0I7Z1OptJe\nAYk5htmFDe9Sgc+Do1L0kdxjblaoWOc0OiwYshQ9cMv+/IsU0U6T7w2A+8QkzPFc\nGVEmrW1Jyz2O3eMpq/Nl2IsmPDYTEPqhkRtAshBuYsoZJUz73/EovcSxyJ2moA==\n=o5Pw\n-----END PGP MESSAGE-----",
"fp": "4BE7925262289B476DBBC17B76FD3810215AE097"
}
],
"unencrypted_suffix": "_unencrypted",
"version": "3.11.0"
}
}

View file

@ -11,7 +11,6 @@ in
sops = {
age.sshKeyPaths = lib.mkDefault [ "/etc/ssh/ssh_host_ed25519_key" ];
# defaultSopsFile = lib.mkForce "/home/swarsel/.dotfiles/secrets/moonside/secrets.yaml";
secrets = {
wireguard-private-key = { inherit sopsFile; };
wireguard-home-preshared-key = { inherit sopsFile; };
@ -138,9 +137,16 @@ in
isBtrfs = true;
isNixos = true;
isLinux = true;
server = {
restic = {
bucketName = "SwarselMoonside";
paths = [
"/persist/opt/minecraft"
];
};
};
syncthing = {
serviceDomain = config.repo.secrets.common.services.domains.syncthing3;
serviceIP = "localhost";
};
};
} // lib.optionalAttrs (!minimal) {
@ -155,6 +161,8 @@ in
shlink = true;
slink = true;
syncthing = true;
minecraft = true;
restic = true;
diskEncryption = lib.mkForce false;
};
}

View file

@ -1,5 +1,5 @@
{
"data": "ENC[AES256_GCM,data:RTj0FFJudZusWh2SuAPBHhpYEU20GmWbeZZSCG/vKCz83iUEJxpZ0lSDm71BN1Di7sz+VchcbWxkUjc+SV9paFOtuRKMPynW5n/HTyp/ub3y8oPUN4AjxiRnvfzh8Qxd/vnmxd6lSh2HxMlOqJURN0JY3D3g+tpHyTIvFUWef6HgzLNZCXDnP3HJzbIY53VPj9f+DsdxtFwU5OHkWd8gH2D4XuPPetN0Iv2HaR9+dvlVrbKEXgElgdENkU+ED78TFxvabk1hqPZqXhsfORF/5RpwF15ip5iSlVWPTwMdBREqCsHRiA+u5F9nwJ5C70U1wz39J40CJoa9oihIxyAmN3dktD0JuY0jiqyxwTRFZXYh7Ioe4CksaET0P7LbTa7+BpctgoBqvmnhM3ZDNcSZMNcCbtX98V30UqEPBoTn3kRYvg/1C1SycR96bVW/AiHMiIzD93dNw2gUWdyQX9xtHvgdxLo3U20pJhjMEcsk9V98H6lPiLp3lltrjAX35RsG5R629W8/WVOGoUQn9nX/y6m9VFKoUPf8/M7tvlxDT9A/QBQQvShdA4AM0K8mdNzb85ac5In+43gWDRXWQPPf72e5gL5nPIqPcZvAcoLHsYFH5ebr7VUaUbHm890jQDoNvtezZ1w9nRlZNGVTwdvwWB3rfzorzwCAKLhkFv6ATUYimP0tiHPOz0MxTQKXg12rtyPXbh8bwjhg0kdIlwljAYnYUKiX7SVSeYq7TQksQIiH83JwxCGrL4xjMWZhNkrg3KQUrEMHHaMbNCZvb5M2nMceBo6eA2zi5qYA9sLVnLTrlwx+3Wl7uFBv+9Z+8qvGg3adpGrtJTJjVf+cig01gzao5WrJtT9q4YD1tOHnWfBhwI9/3ny2A0WlyjlY/fS8WUiOmyhl/6N+ukdffzDZQOcTGf1QD0zO+9FYPqYhxr8eGKRHAB0R81Q5y+ORTLwXJ7EhRIK2f45FJisRIsiR+VTsI2cqy7n9HtubY8jQPxLMLnxuUqTu/OjtUMCcbJO8iqYDxWf6NlCZuTaLsQuUPWvO5uUelQpDmN6HhxSGKD9XG4M7/zCuCWNhKWoH0Z9xfw==,iv:Bs1fdmD4jbM/9hiPHxu+yENrVrwFsmhJ5J38W5+4PtM=,tag:UBpHq3ldgdVORaRxuswzVQ==,type:str]",
"data": "ENC[AES256_GCM,data:jGfSfCOqW+p24TaH0vlcNImiY/Pu9YhdIwri4N4RvG64f1fmfNV3z6LmoShCYBfIWF2P7DvOa92dPY2ek9UiC1bEmiMtc/scpGxpir4WNuMLUtMWb0IGmnhtzq7fRAH5FkYLJBSW7pAgVsoajRGbo8Dbk5Dqcm75Pfj2YcC79oAckYt3vSzBcskgJ+ccdCfJ6vDlnAilay/GatZbIQmbEefOi9Rplfln8Ounj/hH+Z6zat04+rI5Lj8bTPu7NOeUlUmgoApuJSFafTb3zgxqnvQL5axOgIaJqiXFWhIf5httmu0mjhJupMXxt14IXgKe+ESAZFF8hWHHUNOpE8gEt5tPRQ1hqA7eHoGSYCrEQK9rSXRweO9LCfGV1+UduXgX1hKgwKDS4A5u69MvcpXQoSYX33ZzuwY7tbykb1tbEb3jN2BOSCBB2ZKHRfsTMqAHTE1RekcBArMxp7+8BkM/oww8RTMJ3I8tcU3QAr/LoFvKwvfIVrbT9gSlKSZUeoBc0WMzmRdjXhAZmQe2pb/TOFmPm31ih/E98zKA8PXhNrqjzEVN99lfn/NKsOLd9a8LXK8XoTTueTWqENEdJRx6dHpWuqBy5GdkrDVCRzgiO3Hpkwg56nPmCGoD5o1IgnRLJItNYrIRejIRaISjlefpezCMYIGMIx+CusvAwiOuuWT6kNfDnaK1U4P3Ndk39lsz8Eg2GMruc4VZ3kpTCeQdvbl/jmFwNMPtzJYooiDualIAL95iZU+RW/K+2g3ZA/Q/gJrc+hB6I+z3PzMod5015Oj0FG97XQzn2TeBD1fuO8UtyxSNajGD3ZK3Laa5QrSNUrzlf7YONSn98Z8OqKsAz+D/vnr0Lg4kjrrhYvN6GpR/QqMnNZT7m4d/oxACDycao6ZUDNE/dvuXSA4nSJp+5cxDXjgSMhnOgS7/gCiLhEBkLwzwdexT/e5vGcqqMmyeMK8vSFsPpRoPv26nsyRalwctY2ClX5KrEEckHNf+p9djB7eJDyLxXkPRLm0yp3dcmcEyk0tUffpcJ6zqWnlm46yfAf29fmIJfQWJ8ehSY+bYwDnx2LmCPcfH+sRSSV2Y1Ay22ry9rVJU88SuRdSPsHOitCuu0TQU56Su0wG24ilh6Bq4Dk+0JxlL3wyPWsnoaYvaRiJ6cs3j0tTwwxepbwiakLzWnVcqHDSoQ+Bn0T4CmcF5ztmpuLZSe/UXA48k77JmbT8vne0ig+kVfRuKhG+qV6g+GnxTIPPXGzQ1hWTS3Fg8YBMt1XYyjX3xa218agvPwLhCru1v3dAfHKk6N8G6SN6EN78RQmJApjSHAGFO,iv:a18hH0e5s4BTTlVIkQT34z8a2jELj59ZHhBbb93o3t0=,tag:sj4baRiZic6sWnJXjhL7TQ==,type:str]",
"sops": {
"age": [
{
@ -7,8 +7,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2YjdYNFF5Q1VzQTZ0WU1z\nN2R6cEVObU9RMXdpd2x0Mjh2cmpvY0VvNjE4CmF5Sm1vZWRoOTFIY2pkQUVRQ3FY\nVEd3eGpCbGQ3cUpvTE9JdjJMWnQvckEKLS0tIFRpZDZ1ZGZKaXpObFhZVlNqV0hB\nT20rRGV6S3gvWkZLUzQzVVNGQWNGVkUK0bAeRuI0vb7MJTtpxuD56nwZAk39sHAa\njEhntqsV9ts1Vbw2f0mZEqDdzd64NTtDm/YIwygZ2udV27mXNhVUVw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-11-10T23:16:52Z",
"mac": "ENC[AES256_GCM,data:CuwVt8/XKRMUHs1rh7Yf4Bk5tWXqTz0HXUiEEjuLhj1TRuMWs6aTC1h9uTMoybP+FmjKeRTar1E8dgUmoheFUGaBFqxd1Kx/FmNeJVLhUOPgmT9XOIjEjTNnzOoaMsYvfhP+AnLKgx+CfOsLnLMOqdKEggx1t5jNfiI2rXqOdfI=,iv:4Mc3WcgMg3z99dERJk+EF4hPpgGZo4mfMt6X45zgp5I=,tag:MP0YDtR1Wq3088WVzXS+8A==,type:str]",
"lastmodified": "2025-11-27T14:12:09Z",
"mac": "ENC[AES256_GCM,data:6CqpegjS90H6fAllBsvz3d/y4MpNyMUo+v1sby4hHHw36GlQvnULHuv8dhXrlYaE+L21aoz1RITl7IEtNl/R8zjGh8b0dGIc2iUa2M5dNvHNPMTuucAEQPuEEvTiwI72winpEkdB86fHFFHvBwHwmlNVFJYx5b9bNlpjCofewQI=,iv:qOv8s8j5jOtcoKzgN/HkXvIsS/sk/DFZ4lcEKBLsrKA=,tag:ifXbcFGzpJ+DSJPkvaX0pw==,type:str]",
"pgp": [
{
"created_at": "2025-06-13T20:12:55Z",

View file

@ -0,0 +1,39 @@
{ self, lib, minimal, ... }:
{
imports = [
./hardware-configuration.nix
./disk-config.nix
"${self}/modules/nixos/optional/systemd-networkd-server.nix"
];
topology.self = {
icon = "devices.cloud-server";
};
swarselmodules.server.nginx = false;
swarselsystems = {
flakePath = "/root/.dotfiles";
info = "VM.Standard.A1.Flex, 1 vCPUs, 8GB RAM";
isImpermanence = true;
isSecureBoot = false;
isCrypted = true;
isSwap = false;
rootDisk = "/dev/disk/by-id/scsi-360e1a5236f034316a10a97cc703ce9e3";
isBtrfs = true;
isNixos = true;
isLinux = true;
isCloud = true;
isBastionTarget = true;
};
} // lib.optionalAttrs (!minimal) {
swarselprofiles = {
server = true;
};
swarselmodules.server = {
nsd = true;
nginx = false;
};
}

View file

@ -0,0 +1,121 @@
{ lib, pkgs, config, ... }:
let
type = "btrfs";
extraArgs = [ "-L" "nixos" "-f" ]; # force overwrite
subvolumes = {
"/root" = {
mountpoint = "/";
mountOptions = [
"subvol=root"
"compress=zstd"
"noatime"
];
};
"/home" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/home";
mountOptions = [
"subvol=home"
"compress=zstd"
"noatime"
];
};
"/persist" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/persist";
mountOptions = [
"subvol=persist"
"compress=zstd"
"noatime"
];
};
"/log" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/var/log";
mountOptions = [
"subvol=log"
"compress=zstd"
"noatime"
];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = [
"subvol=nix"
"compress=zstd"
"noatime"
];
};
"/swap" = lib.mkIf config.swarselsystems.isSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = config.swarselsystems.swapSize;
};
};
in
{
disko = {
imageBuilder.extraDependencies = [ pkgs.kmod ];
devices = {
disk = {
disk0 = {
type = "disk";
device = config.swarselsystems.rootDisk;
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "defaults" ];
};
};
root = lib.mkIf (!config.swarselsystems.isCrypted) {
size = "100%";
content = {
inherit type subvolumes extraArgs;
postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
MNTPOINT=$(mktemp -d)
mount "/dev/disk/by-label/nixos" "$MNTPOINT" -o subvolid=5
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
'';
};
};
luks = lib.mkIf config.swarselsystems.isCrypted {
size = "100%";
content = {
type = "luks";
name = "cryptroot";
passwordFile = "/tmp/disko-password"; # this is populated by bootstrap.sh
settings = {
allowDiscards = true;
# https://github.com/hmajid2301/dotfiles/blob/a0b511c79b11d9b4afe2a5e2b7eedb2af23e288f/systems/x86_64-linux/framework/disks.nix#L36
crypttabExtraOpts = [
"fido2-device=auto"
"token-timeout=10"
];
};
content = {
inherit type subvolumes extraArgs;
postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
MNTPOINT=$(mktemp -d)
mount "/dev/mapper/cryptroot" "$MNTPOINT" -o subvolid=5
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
'';
};
};
};
};
};
};
};
};
};
fileSystems."/persist".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
fileSystems."/home".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
}

View file

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

View file

@ -0,0 +1,22 @@
{
"data": "ENC[AES256_GCM,data:4C3fdXBKI/x/7B56b2n6OshGRaGgwYc4HQv4CRgXi+Y83hQj6wfbcqA55Xm9cXOfGAm2NNGIcUrVyuGHKlur7lUkvoNYe+a5A4GEkXVxiAoJKGcHa2nqfmR+GQJRAE6gNm9wgUL24CfKonEb09NgFBFfL7srXtkU8R1TMduUiYvzH7eNy45jQnWdQ3xgNYkb65iIZ3KCkcbjKrlOtN1Qu8+PuQmMl175gUVJcaLmpMgsz5IPetyHUWIkmqjgwhim4CyTZGwOaQW376Xq2mZUf9IOhdqLyR8GcKFLsY/GLDzp1eGfx9xUpAu3NMmjblHDdIyRcv0EjS+Cj/EUQwTrw3R2szXAb1m33sIVyloGT8RyVsu1J+RSIQOEKpVLaTxsCoulIfyBj5h9vajMVFdMmyqAFPJTVF8fNmy57VuBiDR1WYY5WT2QkBwe4A5ZZLpRmudeZAqEjD+R8Itcin4Ce8K4LtkpfLZeCUpnoaWk1u0CH5QuFCyd+s2+S2DBnFqfBmhTVzEtwXyd6zEeLo+LGCh2Eu2XwYi+DV5Xfdp4leTwEXQ+63MB2ZtOQkoxT6pi/w1rSlEcVknJJIc0HRhrRSx685i29qmcWGfjw765ECxCM2RKJKdwtYHwyLQGyTkGgzNlWr/EzskD7wwtanR0K0NUBS3MGbBaSmeI+bJ+B1ld2n7Efp1eg8AdMz/VHywvFQpS6HY5ItPCWNcDB9DMerUQINO1EtP1Dd57vafzQGGcduUKW+ywuwUdOU/XTXPaVP7VWdX9EFIlv/RMK4UX/l3Yy/Vf6iciT45zouIgoFECRe59Uz0185BHTn9xeE9oYGiLfKzlnxhNpXNaNmYGVRxKxKwfMNrA+hRtuoGrD0uE/Ev6F5ytMYMZGsQ5D6TJOHXPfAVWo5MzPA1Q2dgoCF9zZvYgCaOcSZTntoJY9X1MiwMkYIbtOtTQ4jJOI9DfXX+kOp/fejHrQEyAasCvh2zxCW2FjMckREdqtYxPEDsHGc8+0BDGgj+00a5wC19U60jolvdLsUwy41inmirgxBMaQhuavMXEpFXT0hEecZfJn8eJqPVPDVLC8LvlB+C593ByHeoR3VOIfFVv3bgCP+cQudAR+U/b8YO4gSpuVV4WF7JXLCwRCi0Flw7EzAuhuR9JYd8GKUEDctGmAYiPy1YiQCLFnAWmZvHQ2q6TeVDTQ5LPmjqM1b4iqoqn3AHhMu9HWswy4LFNujZblSo0hSHRZ+2P/+Xjrgfz2d3QF66ngEjW1tanw7hxGmiZJXXyPN+2bdB04B8ZnL/gBzQ2661fGYGYCBU=,iv:mU4ydooaOySi7MTe+b/DGfs1fzpDXbkASUo1cDsh4O8=,tag:Jh18+kJPLJFlGx5HymywOw==,type:str]",
"sops": {
"age": [
{
"recipient": "age1glge4e97vgqzh332mqs5990vteezu2m8k4wq3z35jk0q8czw3gks2d7a3h",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJZzY0QVQ4ZUxxZkdhQ2Zn\nOHpmTnRaR0R3cXh2Z2JFM1RDVDB2QnE3M3prCm43NjQyOS93UTZKaUlUUmhVcTdG\nUWp1YU1kVmZPc0tBN2FMY2FFVkI1a0UKLS0tIFovZi9FQlhMaXpvcnRYN2FiSm16\nTzJESjNyZ1NzajJRNDR6ZTd2TitoQTgKe2hC6OpYIzgqzhmeJuHWe0yXNE+/Ek26\nGt7s1B6OKnrj+S3es84ePOjAbLHr/ez282b/h0y55ws4R7jMemUIrQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-12-01T12:12:55Z",
"mac": "ENC[AES256_GCM,data:AhvfUvZnKSnhQCTHJpqs5OBELhGYv66on1+kSLX2lONyTbNfwHYsJHII4zHY+bS5cBkZbjtzMfJQkFWtDbU7c8wvdJnHN6H11MOEzC+GfI3R7UzwzJsUjNYE03u8FJCuLvI1SO3EObiKIgH80MV8qlXC+1+f7mKnfZNH8Kekor8=,iv:pAEz8tDZzaFee1EcNBd6zrl0yN55ywVK/eGof/B5MAU=,tag:LbjMr3rOb3By87yOfUK/3A==,type:str]",
"pgp": [
{
"created_at": "2025-11-20T01:03:05Z",
"enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ//eTxMD8ZbwJUqVsi1IKK2qdprLTjE0rqdDue+OvP0V+Ns\n1uTnw+b2UBykbIofXcG4P61OxAFdEs8whiIdffQtkDTkOgzV9IQCBOSGxZGEJXMe\nrl5BZLlF98JZ5R15v8V8vMwWwtC90GZ7gZLDV+yZz40Zqm3mTrFz/3PERukwu4Gb\nLTJDOsGmpooyI8KnrIsBhfEwo7/ouAayuKQfvt2i2Tngk9Em73R91BlpcxsOEmqr\n5KWA4GCsjUOmZZKLj2vyENPgQh8t8bP5fGJ3Rf4J1MCWAB89omcE0aRWId/l5sdA\n/Nxinh3xQsiXHPzPLZQ+UjHs+MjNdUoZapoDBP84j2tHsSxh0RMRhlHpESDWq3Mm\n1acWrChyyds6Lz5ZqkioqvAZ3lslS0kPdQqfsLzYWBhA9kLOIJKYfat+vxsAPwAa\n6kceXtxSzUpThtDUPDibjomn7Mrj7ZoHhiJZup/M27glf/V4P3zk+ctpXMSIE7Ia\nQ/jgRDzpcs+u05RsP32jFbCAfi//WxRo77MoxGMJxDhYibBp+aRkFAgVYiElhxbt\n/NedcIAHSJZFyDPm0wn411+DPnUTPn9D9LCkmSG68ZeGDGZJl7Sz3bJ3obWWecTG\nBjqxMZVwRuU2gdg1IwempP9u1dP0Q+g8B3veui/gczGx3J5kvNv8hnUBTeUl2EyF\nAgwDC9FRLmchgYQBD/oCciOvXMrH9/hWIIYb1sKiuCmgdVfs7H0q92XdVNgkbPRz\nXAakX7dl5cZt748u/eCHlGUGr4q7yA1tDx9Vm/J+O2HljN3lBVCbm7HP+YcI+5g0\nvvxr0cIPtr5CXlZz6hJjTgzE4HfEKagGdjgllbHYBB+0rtq/2pZTa20fG0w4coeI\nB/D0iVFwyuM3Wxt/7gXpPtI+m/3qt8QoFIGsZkck7X5hdJwGF4DD5jKxYB28s5Hc\n4ZBG19jezjMIVJUGE58TTVDTvZvJ5Vaw2RizV8DRkFS3q0UIOapOESpZiRnoOqA1\nDQpAU26RSEj8wlYsgNrVWUpdwlYs5e3EWYNkGROTRSB/dGcCSVF31A76W7af+6uv\nwZdMCrAGlD4GBj/yojdnqstfB2Jxu99VubcImWKfaJEXYx5xoREGmK9+t896GJi+\nE8mjiMOMRZFV2n2nwTxAFMaiDJ+VpKpKGVKCOSDwqsePhY/A4kb+N1nnhutmSl/v\n1SCDDvC9+jYNLUC1IaJfFOrNClA43IdJELOAavRx2t1RdyfyOx3D8rrWhF4+NB9Z\nlAc2e7hOoP/OEtf4YjZWq3dQtWSdwePWBxD9xyvF/kEmd2NcezqdfggH3g84qBxy\nUxBDD3ojMMAXlkPU3hRiDeLd1mHxDizVxqYkIYDSeAKtuv2ECH8y7/mv3sKrFtJe\nAQvSMW7gOmIdtQaIpsXHMxzXf+Nv0l3dZeWYD/TnVvoeVOaRQ9dHrtl3J0U9UN3j\nBOJdFaptlS4SIRkva6v6srrM7dXKvjR6IabdzaWl098VW9RFD+YGJ6ZhuQ+zOA==\n=l0k2\n-----END PGP MESSAGE-----",
"fp": "4BE7925262289B476DBBC17B76FD3810215AE097"
}
],
"unencrypted_suffix": "_unencrypted",
"version": "3.11.0"
}
}

View file

@ -0,0 +1,36 @@
{ self, lib, minimal, ... }:
{
imports = [
./hardware-configuration.nix
./disk-config.nix
"${self}/modules/nixos/optional/systemd-networkd-server.nix"
];
topology.self = {
icon = "devices.cloud-server";
};
swarselsystems = {
flakePath = "/root/.dotfiles";
info = "VM.Standard.A1.Flex, 2 vCPUs, 8GB RAM";
isImpermanence = true;
isSecureBoot = false;
isCrypted = true;
isSwap = false;
rootDisk = "/dev/disk/by-id/scsi-3608deb9b0d4244de95c6620086ff740d";
isBtrfs = true;
isNixos = true;
isLinux = true;
isCloud = true;
};
} // lib.optionalAttrs (!minimal) {
swarselprofiles = {
server = true;
};
swarselmodules.server = {
nginx = false;
};
}

View file

@ -0,0 +1,121 @@
{ lib, pkgs, config, ... }:
let
type = "btrfs";
extraArgs = [ "-L" "nixos" "-f" ]; # force overwrite
subvolumes = {
"/root" = {
mountpoint = "/";
mountOptions = [
"subvol=root"
"compress=zstd"
"noatime"
];
};
"/home" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/home";
mountOptions = [
"subvol=home"
"compress=zstd"
"noatime"
];
};
"/persist" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/persist";
mountOptions = [
"subvol=persist"
"compress=zstd"
"noatime"
];
};
"/log" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/var/log";
mountOptions = [
"subvol=log"
"compress=zstd"
"noatime"
];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = [
"subvol=nix"
"compress=zstd"
"noatime"
];
};
"/swap" = lib.mkIf config.swarselsystems.isSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = config.swarselsystems.swapSize;
};
};
in
{
disko = {
imageBuilder.extraDependencies = [ pkgs.kmod ];
devices = {
disk = {
disk0 = {
type = "disk";
device = config.swarselsystems.rootDisk;
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "defaults" ];
};
};
root = lib.mkIf (!config.swarselsystems.isCrypted) {
size = "100%";
content = {
inherit type subvolumes extraArgs;
postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
MNTPOINT=$(mktemp -d)
mount "/dev/disk/by-label/nixos" "$MNTPOINT" -o subvolid=5
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
'';
};
};
luks = lib.mkIf config.swarselsystems.isCrypted {
size = "100%";
content = {
type = "luks";
name = "cryptroot";
passwordFile = "/tmp/disko-password"; # this is populated by bootstrap.sh
settings = {
allowDiscards = true;
# https://github.com/hmajid2301/dotfiles/blob/a0b511c79b11d9b4afe2a5e2b7eedb2af23e288f/systems/x86_64-linux/framework/disks.nix#L36
crypttabExtraOpts = [
"fido2-device=auto"
"token-timeout=10"
];
};
content = {
inherit type subvolumes extraArgs;
postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
MNTPOINT=$(mktemp -d)
mount "/dev/mapper/cryptroot" "$MNTPOINT" -o subvolid=5
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
'';
};
};
};
};
};
};
};
};
};
fileSystems."/persist".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
fileSystems."/home".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
}

View file

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

View file

@ -0,0 +1,22 @@
{
"data": "ENC[AES256_GCM,data:G3Q+Hn7QkvBZeXzNR+0Bax+Va5sK5E0K3hNTkdsNJx4C6pIwrBEBOt3IKv/c00QhpAnPqo9gbKqWU9gv7I56nEOwVtVH3lrMlbxNl9LIiSv9SvSxVkTOow2msSJV/U+1KpjNQ/LnOo2Fxebfz1yiRtgi7hSazzqzIazZAFBldlKkjLR5SFCG8t5s/nccqZU+cLmS7hJDS5LtgW1XeunqUY7jnKuh7gT2I6fPsu15Vy+YeKLmYIt0a20bWGePBIlyiGRtpnMgtIt5gk5+OpSndO8P/GMgUzRwRZEL1b8U57jbhkPLdnwwy/iV6rEFCD9i6qB0ufVW/euc+y5mN0dx8op9FwJVzkJhUIIy9Qbbc8WOjjjWlwbKJNkWfYX7pTtx+xfBKuPF+IwaoMS9j+C3etkoYe5QCr9YGYM5Xer/HL0otYNacQU5S0VqPBzDnLu7NxzB4i22,iv:aFPDBmZasoqEFCbhrRtA2QMB27khuT3rdfCGAafjov0=,tag:GQGuHL5aYPc98tzc6Bb5mA==,type:str]",
"sops": {
"age": [
{
"recipient": "age1g7atkxdlt4ymeh7v7aa2yzr2hq2qkvzrc4r49ugttm3n582ymv9qrmpk8d",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqdEhDamZTRUhQZFNDTTl4\nVVVNNGZXa2h2THVzY0JWMjE2WjNJT0ZoblV3ClYzeEt4c0dWRzlISnN3NGthR21M\nTEtDQ011dFdhRVdPWlpweS9ma0N3dmsKLS0tIHFPQzQ5VzkyODZyY1JpcE4xR2Nl\nY2MrSERXTWkvNVZCR2xHUGh4ZXMvYTgK7pxPjnh3idl4QzBkR6LHyRskgqA3apS2\nkbg7As6wlEs34TAO8reyZknKTUd3Xif1v9RXiTcu1sEKHqkcqEoDog==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-12-01T22:45:54Z",
"mac": "ENC[AES256_GCM,data:b2sWPq+S5qqSM6lON+9A//LehgR7Wy7x8EfqeiFOFo9RT3niwaKjfp/Jnf6nKbXF43XM4dsn+dIX52fgxyd0KVLnJTqinhz97sSSs7hYFdXa2FGRhI+VwmuGVvr2ylAJODQgTn+MD7I+s/3DTfh6h0V47IZvxrUpYgg7tJrxzBc=,iv:g4XVN24+COVtRQPzTiI4iki1crjBUVc7vpnJ/vucd2A=,tag:gcnfSvPWvLqG2wTZELRMsg==,type:str]",
"pgp": [
{
"created_at": "2025-12-01T23:06:36Z",
"enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ//RhpX1uVa49yA8FIfj/y/2C92Z7iBl+l1TGjaYMnuLAp5\nYybqAHwi1gzbnhKvpqO3ndm7qHNwbPBuYBDhu1ZDkQnzyzIthx3JA2G+je4Jem+N\nF8XWUglO+lEUpHD62s9JdOSS2dNRHSd/mcu/GV+k0/DzkXDn3TzzOciKBLn1u03+\n6T3mipG5cm00EEstR+iX46FSzOPX3M2+hYY+HY9rQa1RKUrUUsBBdCEYWgMsQOA9\nDGyweibxkcyxIGZIc882gxa06QxM07ON7NuZjW7vvUz3k7CI3bf5IBfaCvDywaDL\n0AKeTAVGVLnzdapZoP9lZmu6T639wu8BKMxSHiGeUenOrhs/Gl+CA2iCU5XimZCw\nbwPvKRbOGLu2eiBL/BHEMg1XpRw6bh24o3vNIchGRqDKbXICgkKr2gXhvli3qPrH\nCXokXF48e51bERfr9YWi0ryW5tgVEMwyubRi85cYnslwqfT78xzKMNRwF8wJ6PxG\ngwT6bEJ/f7QzXkw9VPY2HbaBBhe7XUBRDhLnV5sPBiZW2JDOt9rXH1LqWQLo7Ot6\nLWvOicAtmY5vnRIm9x1pPFKipmTWj7NzRCLEq5yt0borQsPO5RTC6fvhL/1Lpe1B\nzjAIjJBfQptEn4xjA0unZk6x45UDp9KpJz5zdKF43DSvGOkEF8NuTdEXNpeYHzCF\nAgwDC9FRLmchgYQBEADA36phB2C1d2DvEzi7AB7lK5gGExmaYSCzMJkSfjNQ4SO5\nwMhvRZZyIf5PT9wdJ6hCtOSqqhh0cubmZadrFnz/qjXLVSv9aTD4PFshF5lYgT0x\n2GkiIOkrVZ6vuP6/iIW/p+CqztDymVRR6DAhNNX6gx2NARdhii2K/hitW0QejoJk\nWY07qUIb2z0fPVp5TfAf3Nr87u3faYr0usW8GGABFA7IzJwCK1VA1284UZm4zj6Z\naHm+0wK/1g7Ck2sjzbhqzK3HlZVKd6lBIhmwdzcG1y0Ua5L7PIauLR6ArZkFD3WO\naHyyZ5hyNmoyOMjuTvPCIhiZ3T+aQK2f8pzyOApEWX4piCNhIvcSSy9AQ/f5hvVd\nWLG68dIMnmOWYxHX68jdNttSCcc9oJKNboOPKDdmEblZxGx5HZpYYL7X+Q0JKoMO\nqCXVc7GlIVLX0GghAvgC9Xww8XMQTWgJJJAVOa0tlTDJ4ybvCiyy850+ZPTevlHV\nfvlKSSCGHtjVIuZ5b+jMtBqg0aPDY0OqNFSvJ6x6wk0uICMesv2LNAKF7tUkMvHF\ncHljW96IOLocW96bwVR+nQG7U/ZY7/P6+2Nva8AgbrCd0erEZ/2lIvRV4IEzCk2g\nVzuzg+7pjkh1iHYUX+VX6CbyIPyx2Ic+VNaMrbqtC1YiPK6Bx+SF3eYHw9DYJ9Jc\nASJeqALtG3vg/TOKZwOfTp1GNvSExTUKqhEHpcCCty1UxIpNCPByvvsUqY0Q63DA\nyJ4TVO1QLCLwKz8nK8NWSRGrZ29jNJfAjcNDV/FrPiFqSPHVAErd4Vnbeu8=\n=Yn71\n-----END PGP MESSAGE-----",
"fp": "4BE7925262289B476DBBC17B76FD3810215AE097"
}
],
"unencrypted_suffix": "_unencrypted",
"version": "3.11.0"
}
}

View file

@ -10,6 +10,10 @@ in
./disk-config.nix
./hardware-configuration.nix
"${self}/modules/nixos/optional/gaming.nix"
"${self}/modules/nixos/optional/nswitch-rcm.nix"
"${self}/modules/nixos/optional/virtualbox.nix"
];
swarselsystems = {
@ -31,7 +35,6 @@ in
isSwap = true;
rootDisk = "/dev/nvme0n1";
swapSize = "4G";
hostName = config.node.name;
};
home-manager.users."${primaryUser}" = {

View file

@ -0,0 +1,38 @@
{ self, lib, minimal, ... }:
{
imports = [
./hardware-configuration.nix
./disk-config.nix
"${self}/modules/nixos/optional/systemd-networkd-server.nix"
];
topology.self = {
icon = "devices.cloud-server";
};
swarselsystems = {
flakePath = "/root/.dotfiles";
info = "2vCPU, 4GB Ram";
isImpermanence = true;
isSecureBoot = false;
isCrypted = true;
isCloud = true;
isSwap = true;
swapSize = "4G";
rootDisk = "/dev/sda";
isBtrfs = true;
isNixos = true;
isLinux = true;
proxyHost = "eagleland";
};
} // lib.optionalAttrs (!minimal) {
swarselmodules.server.mailserver = true;
swarselprofiles = {
server = true;
};
}

View file

@ -0,0 +1,121 @@
{ lib, pkgs, config, ... }:
let
type = "btrfs";
extraArgs = [ "-L" "nixos" "-f" ]; # force overwrite
subvolumes = {
"/root" = {
mountpoint = "/";
mountOptions = [
"subvol=root"
"compress=zstd"
"noatime"
];
};
"/home" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/home";
mountOptions = [
"subvol=home"
"compress=zstd"
"noatime"
];
};
"/persist" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/persist";
mountOptions = [
"subvol=persist"
"compress=zstd"
"noatime"
];
};
"/log" = lib.mkIf config.swarselsystems.isImpermanence {
mountpoint = "/var/log";
mountOptions = [
"subvol=log"
"compress=zstd"
"noatime"
];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = [
"subvol=nix"
"compress=zstd"
"noatime"
];
};
"/swap" = lib.mkIf config.swarselsystems.isSwap {
mountpoint = "/.swapvol";
swap.swapfile.size = config.swarselsystems.swapSize;
};
};
in
{
disko = {
imageBuilder.extraDependencies = [ pkgs.kmod ];
devices = {
disk = {
disk0 = {
type = "disk";
device = config.swarselsystems.rootDisk;
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "defaults" ];
};
};
root = lib.mkIf (!config.swarselsystems.isCrypted) {
size = "100%";
content = {
inherit type subvolumes extraArgs;
postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
MNTPOINT=$(mktemp -d)
mount "/dev/disk/by-label/nixos" "$MNTPOINT" -o subvolid=5
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
'';
};
};
luks = lib.mkIf config.swarselsystems.isCrypted {
size = "100%";
content = {
type = "luks";
name = "cryptroot";
passwordFile = "/tmp/disko-password"; # this is populated by bootstrap.sh
settings = {
allowDiscards = true;
# https://github.com/hmajid2301/dotfiles/blob/a0b511c79b11d9b4afe2a5e2b7eedb2af23e288f/systems/x86_64-linux/framework/disks.nix#L36
crypttabExtraOpts = [
"fido2-device=auto"
"token-timeout=10"
];
};
content = {
inherit type subvolumes extraArgs;
postCreateHook = lib.mkIf config.swarselsystems.isImpermanence ''
MNTPOINT=$(mktemp -d)
mount "/dev/mapper/cryptroot" "$MNTPOINT" -o subvolid=5
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
'';
};
};
};
};
};
};
};
};
};
fileSystems."/persist".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
fileSystems."/home".neededForBoot = lib.mkIf config.swarselsystems.isImpermanence true;
}

View file

@ -0,0 +1,18 @@
{ lib, modulesPath, ... }:
{
imports =
[
(modulesPath + "/profiles/qemu-guest.nix")
];
boot = {
initrd = {
availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
kernelModules = [ ];
};
kernelModules = [ ];
extraModulePackages = [ ];
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

View file

@ -0,0 +1,22 @@
{
"data": "ENC[AES256_GCM,data:nIgv3b+6o5Ce9X9xZtBK62f6dgsAGLPqq7aVFCw2qjD9UiHCrAY9vTn5NSW2O2pbLAfx6h7falS3/0yU+AkJ2H3zhxBy7ZxQ0m9dLoQGrYY/E9Z45xZmdFRxtzexCaxr2DxbP8haJKomQ22cHk07HGsrEZ/CFGkyjRxUr3Y4rewgZPBXahVtM75mWbNpVGApc8cs/W4JbjuXw3qlCQcACz8sZVPHKCjbEypypo6nTmU7NO7worrAJ2QgU75oGJ9g96wp9paFMEDofVp2Y25IVYReGg8T1Qi/kTcZzfzGfSpEwnQBB/ZCW6gNYhMK3shfB8DxKy6+romVXm1K+/0yUmwsCM8xC5zJX0GsO8Uu63YFrW/Y2E6aYZfBHdIgfy4lYOFKC2o0ixirw9EO8HyfsDt47QYB970vLPjYZfKNAZBgltbV3KPsOHxmgiZbTbAl0cb9zRc+jV2voH9T5VhFiUWdfaLBY1HUAVAjU7h62uZoCsi1HWyAroEROKS96npTD+3/vHehYuEGBf1IxYnLwHnKeqsr/Bqoukf3OecOH2EkMTTFQ7E0k9s0keRypoHmeYIh2a3dRcaXXbNEgiAMfabhgUh1NNcYKSZhcIekN8WN8azXjbVIrfEakJ8S+PUf5fJdspN/3Ppm06fDLv7yLHnLc8Eae2COOR8vYKIo3Onu4doxNjisfpHujLXYaCGhWpINEGWF7fkeC1B7,iv:v9MxvhcHg+P00UnOWujSgVlMNcOnDm/gK8kNcN54E2E=,tag:XnPMzsDeGJMt9yv6GnFzqg==,type:str]",
"sops": {
"age": [
{
"recipient": "age1cmzh82q8k59yzceuuy2epmqu22g7m84gqvq056mhgehwpmvjadfsc3glc8",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJR1ZPZFUxRTh0QjB6UDJ4\nOFd2c2lFejhHck5UdUxVbmFFbVRYNEJaSzJZCkNxbndVVThObDkxUmx2WW9ESzhh\na2o0LzFCbWdJVlRIV00rTVUwTktoek0KLS0tIC9qalVvZmpGQXZsV3RIYWRPbmRY\nam80NkRkT2l0ak8wV3pTSW9kSC9nZ3cKCH8eEMmku6WMliEDdAiW2Lk1jAGH9SoP\nWQ5Y6e90jEnp8XbGE7KYiG+jy5fHSc6Y5/YyMmi/b9bF9AhmRT6rdw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-11-28T10:50:22Z",
"mac": "ENC[AES256_GCM,data:lwkkp8YSzX8NM7E65kmPpF/q9Vn+FnCTeePLswDH6AVgndo/7QOy0GtJeXmiwt2YsA4AhRqxexWl2R8tjEysP35pyfQJ4vEkVi+V2tEnoLgftriNJzpoeVuRNXLxTPhPezOZgAcTDDL4yyqJXpcFj0PE1DPHKxazT28BoilaBYE=,iv:3dcAqkw/y6rAPL8wb5iewz37S4xszYFGHxvQiQ98sLk=,tag:SEmbptei6GrTXXyb7zwrIg==,type:str]",
"pgp": [
{
"created_at": "2025-11-23T15:25:41Z",
"enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ/+OOUtfNq9RBpm1/AbgTjenkcsRwzvyxMQ+VfT7AN/OjEH\naYaVnoU+IYoUJIw8u0zfFuJGyhcU862pMN+isngqNNZiEqY8C9rP4+l82Ks4qLU2\nanUk8HPcUc7bQC19zoSpl5MIeppV4SNC5OAph+YKVcj95l6OFw1EieptfhRFtTps\nwUKMf3p9FC/ndxjDG6Rxro7RQsETJgZ3DE3tRFPsBzMiC3sf+fsOzFgVyABqYZ1k\nDr+pkdBzGB3LXOyeDJWK38DxY/NEEfDgdSGLC6ntQ8eS9fbcNajT6FUwH2uwHJ4y\niWT6Q8z+XFjh3Z458tZhcnBGv6AKGeQ/QG9z+0DALKkkmij+vJqRAGjJxur6XM3K\nf0anUMXLeCINcLEa+Wv7inYJaPXu2NSmqtd1yYYXoAbVcnmzmgW9D2in+JnG5urQ\nCq0MEALyp1axExIaD3BHrFIaK9IX2PO1E/PLDng8AtGEx5Fn//OQX0Wt/yB2eEk2\n3uubPz1a1eMfRz1pK5CFOpJoZ8bmyg5n4g/5MgVgoxzA5nhjfMYD/HD8EG3ta8PI\nrQZhtlg7C+5nEsNevD4RPmzO7z1JdqJGMIWPPUJKZ7WozA5192aAw6HVKdtI4FH7\nXv4KY+GcmUvsKhpaWidW7vsY4MWSfn4m6Ybg2vqHsCUjj5fHVHF9BeKQecIcTTyF\nAgwDC9FRLmchgYQBD/4mfMCt5Ez8WITcru+pwlMHCeSUOxfftsydqdtt/gZ2oJTH\nhMMN2A26x3LXIfZ8IA6to6ldxQLfj3gDF8H+akHbRyndrA1V0U+EhoNZ/DYECkNB\nx8xtrJwsY47siT7sWlounXqnQr5E4nfSfDOsfSv04aUyyUsMqdjFRVY1/b5BCkoJ\nOptFJJjdosfmGfsHCGYvqj0XNycVQj3ioYEwOdDMlZ8riSyRTRPL9UAfgFeQ5swG\n1I1qWaF2+8KUk01wQwmwYLKs1JUnVOl6Uy4XpHbcZcCEIW3VVnwxFVCYcHwhDXWT\n4YGeGFfosuthL4AjJ2EmNKLq+sUxmD7ANS2E561+0BDAakQ3Z0eA/wpJ6VWQtfV0\n05tw6zS3BWwTi5fiiN4JvXqnj+8aT1PBtgxrCeDCjQ36KGViLzDsZOCMNYcr1EZI\nEFMTmaUDFWtoHQKi7ZU+oiRGGfZdnbh0icCsnBecePo4//LaCvBn6lA+vFBmuHLo\nZ2Idh5JSYFoEvhdX3j+sO0dOqzQdDEDy6+Y3S3T4vuSB3w5k1B5c3EDseKfLHUY/\nhgAIxO7rtELyhlFODMmEOzLWwOfxq/5ar/izxkdQS5HPNyVXT6SKikTGmI2z8Uw3\njyCaXv7ny5IVG/kR5aTP+DIHhichcpxJk7j+wZfZV/g8O2PWQpYXfxr36gSo49Je\nARJUBGaEVAhqoNfaHCUbvHCSbbI2yKY+sliX3p7MmcMdy/cvKyowQUuw/FYtdbGD\nHwCe6GZZzHWJZkX3nju3zhOy3gBDBDB1fbF4W0VjsjOwYjy/7MNMVH0eXli20Q==\n=qkvc\n-----END PGP MESSAGE-----",
"fp": "4BE7925262289B476DBBC17B76FD3810215AE097"
}
],
"unencrypted_suffix": "_unencrypted",
"version": "3.11.0"
}
}

View file

@ -1,5 +1,5 @@
{
"data": "ENC[AES256_GCM,data:RwbQZyqU0OjA/wD3o0HppPWFjfHNAHsGF8DzdJrXZLlE5RPUigHWtMLcX+2bNd0DpS3r7WHCSyiu+mmg6GWFiE6wAOBU1Q19BpQ8k3oTt8sP3N4/5PfzYcXlHRfwxmB9/pv8YCi5+cOU5ExWiQ+kC767UbgPIC2ugUD6tkP14KkhW0EGgEhF3elBfOGrSHGgjltgIFMYm/WKZjM=,iv:EBpghMcCGd/wow68V3zoDfzwywDGwmlqn3btNHrfxbk=,tag:jvSZyRIQ7BmQdKc6YEBIZQ==,type:str]",
"data": "ENC[AES256_GCM,data:trvZ+abrf69YhdmIQ1ekgDW82PtPnJkC5bfvh6lABb1BBkPWZk8Ds7Ug4CtulspitB/Spwd0ksGHSuEpk7Xg9V+5O9nm4/8JWWh7EF4qKWeRiwqj/dpfHTtTQPOzywHQFwLg6EWS3wSwUu60dZqJ8f36rvr+KAZc71jZayZmm3TIpeDaMsCAyO+TrfzeKM8AYN4uUVr30raquNjd2XzGgufE3FFCQdo4yhvzVGHGq0+wrZGr,iv:Yx4RkCBSkB4gK1dnMGudPwPP6moR4/7ovDZ77f1WL9o=,tag:9tTUU6ax2K2CqKjxHn2ZaQ==,type:str]",
"sops": {
"age": [
{
@ -7,8 +7,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0VHAxaWdiV1VlWEY2UktF\ncE96UHJnWGNpY0ZFUmZVSi9xSXpBMmI2S1VFCjB6cWtDTTJrNFhZRC9yUHRYdUpS\naytwOUJ4NTRxTmJmc0R0Wmh5dFVKbzQKLS0tIHQ2NUtqRjh6MVF6VHJFSHVFTFFD\nNWh0MDVjekFDUWZvTUZNK0Z4M0lJbVEKGZk1BvZsNTkIor5rTcpi2UE4W/BqNMWU\nIAe3irNN6p1si2zebrCEyiaJYuaVn7uYVwXcscJlNTfkr9szm8TjSA==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-11-10T01:10:14Z",
"mac": "ENC[AES256_GCM,data:NSUKiOFGZyTb9U6e8cJoOJPAMfnk5iuw7pLK0JJzdwf4pI1aMSqjSDylQ5EqqbdFKZKRmaIjjHSpcJep6q0TRFA6wOznHWyv/UCECGwqZrS3EXgcQF5lZl7NVXPPSsMZgPReEVQcMtMivatPrfksEeCaam4WC/M+dqd2d2RrOXI=,iv:KnBNepDoaQeQ9MSrSN6dkrbS6YqkMYMpmXFd5v+oWoI=,tag:vPhsazyi8d3ugGoW8Z1Asg==,type:str]",
"lastmodified": "2025-11-23T18:19:50Z",
"mac": "ENC[AES256_GCM,data:IA71SHchjrqqU5tRlJ4Ozgx2rRxhKE42CsC7ygBLdAZcyZs+7iMpskYejIue8+JXto7zJxe38UbolnLOaTkHzSVGJkKMYQQQ/sXoDtaWlsYTN648ug4zAbgN1neifNnG+756abcg9NEuJRXBhXDzqmAecHkzv6U0HW9LHPO9W1s=,iv:dEiu6FnSqALXDOtpCZ3FiQ8D6GU0FjQAFA12SPaSIAY=,tag:/SXghsNzu8ceOQk/2w8e7w==,type:str]",
"pgp": [
{
"created_at": "2025-11-11T17:51:27Z",

View file

@ -10,15 +10,16 @@ in
./disk-config.nix
./hardware-configuration.nix
];
"${self}/modules/nixos/optional/amdcpu.nix"
"${self}/modules/nixos/optional/amdgpu.nix"
"${self}/modules/nixos/optional/framework.nix"
"${self}/modules/nixos/optional/gaming.nix"
"${self}/modules/nixos/optional/hibernation.nix"
"${self}/modules/nixos/optional/nswitch-rcm.nix"
"${self}/modules/nixos/optional/virtualbox.nix"
"${self}/modules/nixos/optional/work.nix"
swarselmodules = {
optional = {
amdcpu = true;
amdgpu = true;
hibernation = true;
};
};
];
swarselsystems = {
lowResolution = "1280x800";
@ -67,9 +68,5 @@ in
} // lib.optionalAttrs (!minimal) {
swarselprofiles = {
personal = true;
optionals = true;
work = true;
uni = true;
framework = true;
};
}

View file

@ -1,9 +1,11 @@
{ inputs, lib, config, minimal, nodes, globals, ... }:
{ self, inputs, lib, config, minimal, nodes, globals, ... }:
{
imports = [
./hardware-configuration.nix
./disk-config.nix
"${self}/modules/nixos/optional/microvm-host.nix"
];
boot = {
@ -30,9 +32,6 @@
};
swarselmodules = {
optional = {
microvmHost = true;
};
server = {
diskEncryption = lib.mkForce false; # TODO: disable
nfs = false;

View file

@ -1,5 +1,8 @@
{ lib, minimal, ... }:
{ self, lib, minimal, ... }:
{
imports = [
"${self}/modules/nixos/optional/microvm-guest.nix"
];
swarselsystems = {
info = "ASUS Z10PA-D8, 2* Intel Xeon E5-2650 v4, 128GB RAM";
@ -11,12 +14,6 @@
server = false;
};
swarselmodules = {
optional = {
microvmGuest = false;
};
};
microvm = {
mem = 1024 * 4;
vcpu = 2;

View file

@ -25,13 +25,28 @@
isBtrfs = false;
isLinux = true;
isNixos = true;
server.garage = {
data_dir = [
{
proxyHost = "moonside";
server = {
restic = {
bucketName = "SwarselWinters";
paths = [
"/Vault/data/paperless"
"/Vault/data/koillection"
"/Vault/data/postgresql"
"/Vault/data/firefly-iii"
"/Vault/data/radicale"
"/Vault/data/matrix-synapse"
"/Vault/Eternor/Paperless"
"/Vault/Eternor/Bilder"
"/Vault/Eternor/Immich"
];
};
garage = {
data_dir = {
capacity = "200G";
path = "/Vault/data/garage/main";
}
];
path = "/Vault/data/garage/data";
};
};
};
};

View file

@ -1,5 +1,5 @@
{
"data": "ENC[AES256_GCM,data:dwoz+/DxlUbk05hmg/EwtmUkuD759sQ4iVbjHqcPpY9y2l/gzuPSJT2CMI2GbZs5SKhtlqoqZ5jHG3LwcQjgulmYHB2ThJR4ALi7usJm08q0UfMirnm6mPxjnhdhJXdO6YQ4LaRyP81txSphrl28eJwp2efz3rkUp8nAA3keL6MLZsBkdOXujOJhpreTr1mprWTA6U8aRWFBW7Y1vWvxAH3dtQ03XhYXM88pY6k+HKMvcXSsiDhvwnxG/+UYvSIHcanmboCJDYbgXZECnIGsar7ZOmbsZ3GM6X37qPJpxNmUjc4OoRaJJCcn6saH8kOJkx2rxMyzgMryuGdBq4R/m2JsvDoCPDh+gKO+luCI+hH/iduxnDgYjZAQ2gv3Q14MGNe9nvPWVfiRXXzqRf/8vDXjpnD2FFKmMSqiCvPJHRL52uwO3R2zYUrUfQgDN0Jk6nII8B64l+l69Q8Mod1J5nEMwoUOihhOsjaz6TMIUo6b0GKvxZG04Noyd7S+KuxZe1BsrxSnn7REt6qyQKqAHnMYVXpBmOxOpzhAhOrBIOz6LuqHPzmooQukuBDH/Ej2rC5hLBAFW7mvHIcTqo9sJFbnT3lYYtwLSlHBE3R26vud9pG8K2SuVdy2MWJMpLscR48V9r3nAbWsXKXLZALW38z33/UMfzTJ4g4L7Eo/4E5RXlihyL5/p8ISsoQdf6Uj718pVPTToBRBbIEMOSoJ4ntPoVxQbcpdrGO9zrqqPeZWQSE1JM8anGeZVqeMEVmZJxIbfquX8eMKJrkTroa/9HysuIi0O311F/kntoCtDOYCd3mYPcT8UnZHW3wuG7lqYRd15i/eaMhj3z1eTWoZ40R8w+2TaQB+TjyoLoGGzHvyktI5UkYiaMwa2FoFz40tz5YdZ8aODLQhwJc1mv3Fm0VLudXm7NUcfc4tr35EKbDg1wKtUS13VMSHjbi8ANbTB3nBvpBsPKtD12BTqaP4Q0HJipdnDbcwas/MoG27rFO5+q8+cb82IgjSpCeekrIgUY1wsnOyR3j3ByITp8jfmCRMF1vjKifKr0pgREF1dW59VQ33TvUyjfveQV0ixeV+vM9QueQsUVFzeqYTagsPSM/Czx/UNo8hyG1ze0p+acoOb257Q/Um8nkj3iNPAzx3WN6IdjJkpN1Ldp1SvU5qd3o3DDcSw2ztz8usBkH91BrBaV9MYGH/FSM/HL2CfTZoZodP1VqKFi1Hl3pHHyPEagvoJp1ayUZqmymKu4x1wFxC5FMUXjWUwWZZx1PIOwOtf8pLqVd6FySJlwG/MA4Bfxcnc+eSZ1EYcuHU3ziGbtGiB0eqWXA0fhUwIHHUFnV7H8NoRaJnbDS+kviFdTQKvoF3OmymEwhaq/Oak0ZQk8NLHC7KTQ6xVCb7bBtLpkBdXFE3YB5ltXvEYvSL02qX9i6oBf8GRi4Tl+k6zca6QVJzHG4hU8Nh3cxXBmF2IIY4JiKy0YlsVXCg7OHEWMEl4qT09dAsrDcKQC205YRF7XO8AXimENFQM2Nr/moadk2SF3D2DuJEE2HnSBk4H2tVlMNns32MpTFBZwbf3JOIHJV9CFyVSjhjuNjVjMK4vVdpnEzhmnaKjDqMnuRGNZmrl6p8gKM26KlWcYpIclQkPxy1pY1iFINxGH4YEGdAztpx1YhBkQNkQT492InrPA/PE5XFStP4WsKsLW72lhSVgH8D27S76yGihXyaVXXfd0VF5Fx/gUnbd7fph4Vi1VtFonhfK+ctHg==,iv:aQoC+pr7OoTyTT0FE4MbENfzfJ0Beq1Lsz9G1jnFQPs=,tag:JuYmfDP2foCVDH8CwfL4fQ==,type:str]",
"data": "ENC[AES256_GCM,data:vevuVfscWMiD3Lzc/bAS+jAqpzgkfBfcFAB7ChacGaj/PJfoi5AzpmlkDhm11GBcvUXcveMnbLbQexaF3dgPVwvbD9xr6e+mcMJjIry5c5a5wOcZkyGxXgPuPg415An9AQrO56XeTTSaUL+ScQB3kv6eIyzCtxZag7pRLnOgwFuGYqfwcDIcX8QHCc0ijf3XLPaM6dEgiFYDeOMFhOF4+Z8/d9eHoEQ3tOkWTmkoVqZFz80ZicEraliWnWMvCBhRLKo3gb7KFRce/AAEZQaS3CZOJz7v7var4Ds1+PZnU282aSU/xsY5Dq1vOrsZuoYqXA5WrdC9HaXAYLGaGFCzLwRTAfJvigV4PNwOePskCSa/qRlOGpyO1t1B01Y4pghdERNlS+1ltEz8nKVfIi4DR6dKy8NIhLl3huJQy6KHsLrjDHnmxeypo2sJ+NeyuNTKqwJo9x3krcIBt8SaUoFIDkBgshcDCp2eBcKvRIOFIa8r3rsxQ7gwG3YV7hS+NR0nwsUXodGXVzrdehDNddr+mI4GEMl8TTP9sdVSaPhKpN+QB3GGGoYwX2HJYXdY9CKIIlYcgFiDfPz9x4HqGnGfSpeB6QgTK40pmRmG6jQyIFZiW+hQBS4XHtKQ8CJx4zUNpiUArYzustw6riPkfYDex21SzsUIjpRYxB8uGHFvJlJVgr4FkQQg6frebKf2EjIhjc9Mjdw+g7cGb5+WavUfy+fIXztYwRI0l8aftosfCMdGsSChntKCymz0kpGREx00HF5blA6oyifHaVxRYoqraxCwbe+p1RTFlGonaYtb0gBWpdrQU+24HVQU1rMhc8HFHPjcWofE/ymEPkhRzkxIXMmNQFi/18KvZWoy2qOVtPmsEc4mOVRtC6w9AZZpcxI9CXhhuyDZlJ/k4bJzkZFrcNW8I7OjEXTNmsYkzJDSVzD3Od/1zhubU8LYZBBXuejzeH0TXNsXbS6tQXCJ2D7Gzrcx8LpXL/a1IjAUmIXguVtPT9nGallXO9jHV9g7GGjF7weTaEMb/eNSuLgQOpq8vziN1XLWhVo0WEQ8zU97KSVJS5moaTEPAEUlHC4PfM3AQHpWMW4EL7FZu5r1yw+EDOUA4k9u9HIVbn5XVZbWb18aVVkYZoulLIVU7I74LJlYE/BSYhGzp6Ff1k6qzPNTbVgXEtiNuLQKa//8gHoQUCsu019MEVAU4LhZ+nt4genG4qFUTuBujTriO4Vhdel9Qsoq95FLXDzdwRInUzfUhbLli/rKv+LDW7wIdh/peWslq5XkWBeMqJC97OSGzM/MaWIzzMY68FjCJfYX6I2nskFD1xZiECKukn0LV/wqQhrkmUuyG6RsZGAZuOoStWJMs8v+x+ZIMHzg1jItXO2ozt8P73EvdgOExJi5/aSf8sQwX7H5lesDtnGYU5+xV9k6R8icsIqG/TLuFAiqK1hmFQv7H/9pFkRq1LUXFmJXoKDfDByG6xUjMeyYOwT6yLShhH3MMWvh3yjflwzGo7uTU1BTpNbKT0LEh3Q9C1txZ0uKROhWKu70iH+kHRFVlhUbyYpZovu3BPB3WDhLiLuXIOss5+dVv5RBSYUtxpzp7Oq7mbMRIGCY1hOVCiCcUEvcXXiQ8JBCklWUEEJ15BAIewetgDiVci4USgZZYrALplmSFkKTZbFjYEIrf3ghKFXfVTkMixRmzTHoxKpYXzvB3TZnkmAXVhvJbGEiHsAaHpcfycAXygQAWsIFYzYSDrqYXmRhwEy/A5cqy8dYx+UA3bBAi4v0QPMoro3UtdI2ipM=,iv:+QSRj/TyZl6xbwLDbuwb83RkBiLUi85VYcpss8Jn8fk=,tag:uPqu0GaUGmChLweOGN10yQ==,type:str]",
"sops": {
"age": [
{
@ -11,8 +11,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNeGtTZ0ZSV0trWlQrS2dV\nSFo0dytGYXhRTjl6cDZrUU0wZ1IybDVRaFZrCmZmRmxJNmdwS0xodHdEOGU4bldU\nR1JScHAvZHhlVTBJbWExb0VpR0h2MXMKLS0tIDYwQmZpMjdYRmpBeXFNOXArN0h5\nVGN1THljeCtVV0hXenMyRVJkMjlHNEEKm+yZTT48nYr3H0Bd1OKw/CYk1kwnrBzk\nTgSQHsGXhmOyDag9cSZ4wAOmqtqSjA9bouFBuhl2lSbgpjnarvFaXQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-11-10T01:10:47Z",
"mac": "ENC[AES256_GCM,data:2gKEGIYctY7g7mL7lay1T7XmxGdsRzz/dIC1p98zDTnIoBrq5mf5CV/FjAGi5jDsmEMoCSUTWFaT/0Wq3nmRC+OyjL3/Hsit+HJDBVbyf/mY+zs2UQd3KVYoxmpDeAJ1E9s8ygxEu5lJGzacWbJ9BggKUUnywXYfNg0fS7ntjUw=,iv:5xedOuJ3VFm4pEjXyVBM9Iwe5pK1dYP4nTRkk7exrvo=,tag:sEVygcLMqkI9CWQDjoaEqQ==,type:str]",
"lastmodified": "2025-11-23T18:03:21Z",
"mac": "ENC[AES256_GCM,data:8KSKQH7qF2vLnR17a3XhYGAqYq4YNgf7XEkpeNVHD39Aj8MzdlsGPr9vI2o/N1yTpQyJrPW1ntKVvI9rHwcJhm5nyaQiHVwKHWcxcn7li6AeztV4HUqwKxQwf3MHfZ4fhWJrI7NYAuMAbmK6epa/ROGsIGnT6vQh3SImcn+Kkcg=,iv:dT8dBuSsYRxGe93/9ie/6/X4Ru5NDycz2pgMVI83wbc=,tag:r1mPjG/JOQsRDzCktIlisQ==,type:str]",
"pgp": [
{
"created_at": "2025-08-24T23:36:17Z",

4146
index.html

File diff suppressed because it is too large Load diff

96
install/kexec.nix Normal file
View file

@ -0,0 +1,96 @@
{ lib, pkgs, modulesPath, options, ... }:
{
disabledModules = [
# This module adds values to multiple lists (systemPackages, supportedFilesystems)
# which are impossible/unpractical to remove, so we disable the entire module.
"profiles/base.nix"
];
imports = [
# reduce closure size by removing perl
"${modulesPath}/profiles/perlless.nix"
# FIXME: we still are left with nixos-generate-config due to nixos-install-tools
{ system.forbiddenDependenciesRegexes = lib.mkForce [ ]; }
];
config = {
networking.hostName = "brickroad";
system = {
# nixos-option is mainly useful for interactive installations
tools.nixos-option.enable = false;
# among others, this prevents carrying a stdenv with gcc in the image
extraDependencies = lib.mkForce [ ];
};
# prevents shipping nixpkgs, unnecessary if system is evaluated externally
nix.registry = lib.mkForce { };
# would pull in nano
programs.nano.enable = false;
# prevents strace
environment = {
defaultPackages = lib.mkForce [
pkgs.parted
pkgs.gptfdisk
pkgs.e2fsprogs
];
systemPackages = with pkgs; [
cryptsetup.bin
];
# Don't install the /lib/ld-linux.so.2 stub. This saves one instance of nixpkgs.
ldso32 = null;
};
# included in systemd anyway
systemd.sysusers.enable = true;
# normal users are not allowed with sys-users
# see https://github.com/NixOS/nixpkgs/pull/328926
users.users.nixos = {
isSystemUser = true;
isNormalUser = lib.mkForce false;
shell = "/run/current-system/sw/bin/bash";
group = "nixos";
};
users.groups.nixos = { };
security = {
# we have still run0 from systemd and most of the time we just use root
sudo.enable = false;
polkit.enable = lib.mkForce false;
# introduces x11 dependencies
pam.services.su.forwardXAuth = lib.mkForce false;
};
documentation = {
enable = false;
man.enable = false;
nixos.enable = false;
info.enable = false;
doc.enable = false;
};
services = {
# no dependency on x11
dbus.implementation = "broker";
# we prefer root as this is also what we use in nixos-anywhere
getty.autologinUser = lib.mkForce "root";
# included in systemd anyway
userborn.enable = false;
};
# we are missing this from base.nix
boot.supportedFilesystems = [
"ext4"
"btrfs"
"xfs"
];
} // lib.optionalAttrs (options.hardware ? firmwareCompression) {
hardware.firmwareCompression = "xz";
};
}

View file

@ -23,5 +23,8 @@ dd DRIVE ISO:
sync USER HOST:
rsync -rltv --filter=':- .gitignore' -e "ssh -l {{USER}}" . {{USER}}@{{HOST}}:.dotfiles/
bootstrap DEST CONFIG ARCH="x86_64-linux":
nix develop .#deploy --command zsh -c "swarsel-bootstrap -n {{CONFIG}} -d {{DEST}} -a {{ARCH}}"
secrets USER HOST:
rsync -rltv -e "ssh -l {{USER}}" /var/tmp/nix-import-encrypted/1000/ {{USER}}@{{HOST}}:/var/tmp/nix-import-encrypted/0
bootstrap DEST CONFIG ARCH="x86_64-linux" NODISKODEPS="":
nix develop .#deploy --command zsh -c "swarsel-bootstrap {{NODISKODEPS}} -n {{CONFIG}} -d {{DEST}} -a {{ARCH}}"

View file

@ -1,4 +1,4 @@
{ lib, config, pkgs, globals, inputs, nixosConfig ? config, ... }:
{ lib, config, pkgs, globals, inputs, confLib, ... }:
let
moduleName = "anki";
inherit (config.swarselsystems) isPublic isNixos;
@ -23,11 +23,11 @@ in
syncMedia = true;
autoSyncMediaMinutes = 5;
url = "https://${globals.services.ankisync.domain}";
usernameFile = nixosConfig.sops.secrets.anki-user.path;
usernameFile = confLib.getConfig.sops.secrets.anki-user.path;
# this is not the password but the syncKey
# get it by logging in or out, saving preferences and then
# show details on the "settings wont be saved" dialog
keyFile = nixosConfig.sops.secrets.anki-pw.path;
keyFile = confLib.getConfig.sops.secrets.anki-pw.path;
};
addons =
let

View file

@ -8,6 +8,7 @@ in
programs.atuin = {
enable = true;
enableZshIntegration = true;
enableBashIntegration = true;
settings = {
auto_sync = true;
sync_frequency = "5m";

View file

@ -0,0 +1,20 @@
{ config, lib, ... }:
{
options.swarselmodules.bash = lib.mkEnableOption "bash settings";
config = lib.mkIf config.swarselmodules.bash {
programs.bash = {
enable = true;
# needed for remote builders
bashrcExtra = lib.mkIf (!config.swarselsystems.isNixos) ''
export PATH="/nix/var/nix/profiles/default/bin:$PATH"
'';
historyFile = "${config.home.homeDirectory}/.histfile";
historySize = 100000;
historyFileSize = 100000;
historyControl = [
"ignoreboth"
];
};
};
}

View file

@ -1,4 +1,4 @@
{ lib, config, ... }:
{ lib, config, globals, ... }:
let
moduleName = "element-desktop";
in
@ -10,7 +10,7 @@ in
settings = {
default_server_config = {
"m.homeserver" = {
base_url = "https://swatrix.swarsel.win/";
base_url = "https://${globals.services.matrix.domain}/";
};
};
UIFeature = {

View file

@ -109,12 +109,14 @@ in
secrets = {
fever-pw = { path = "${homeDir}/.emacs.d/.fever"; };
emacs-radicale-pw = { };
github-forge-token = { };
};
templates = {
authinfo = {
path = "${homeDir}/.emacs.d/.authinfo";
content = ''
machine ${globals.services.radicale.domain} login ${radicaleUser} password ${config.sops.placeholder.emacs-radicale-pw}
machine api.github.com login ${mainUser}^forge password ${config.sops.placeholder.github-forge-token}
'';
};
};

View file

@ -1,8 +1,8 @@
{ lib, config, nixosConfig ? config, ... }:
{ lib, config, confLib, globals, ... }:
let
inherit (nixosConfig.repo.secrets.common.mail) address1 address2 address3 address4 allMailAddresses;
inherit (nixosConfig.repo.secrets.common.calendar) source1 source1-name source2 source2-name source3 source3-name;
inherit (nixosConfig.repo.secrets.common) fullName openrouterApi;
inherit (confLib.getConfig.repo.secrets.common.mail) address1 address2 address3 address4 allMailAddresses;
inherit (confLib.getConfig.repo.secrets.common.calendar) source1 source1-name source2 source2-name source3 source3-name;
inherit (confLib.getConfig.repo.secrets.common) fullName openrouterApi instaDomain sportDomain;
inherit (config.swarselsystems) isPublic homeDir;
DISPLAY = ":0";
@ -16,7 +16,14 @@ in
} // (lib.optionalAttrs (!isPublic) { });
systemd.user.sessionVariables = {
DOCUMENT_DIR_PRIV = lib.mkForce "${homeDir}/Documents/Private";
FLAKE = "${config.home.homeDirectory}/.dotfiles";
} // lib.optionalAttrs (!isPublic) {
SWARSEL_DOMAIN = globals.domains.main;
SWARSEL_RSS_DOMAIN = globals.services.freshrss.domain;
SWARSEL_MUSIC_DOMAIN = globals.services.navidrome.domain;
SWARSEL_FILES_DOMAIN = globals.services.nextcloud.domain;
SWARSEL_INSTA_DOMAIN = instaDomain;
SWARSEL_SPORT_DOMAIN = sportDomain;
SWARSEL_MAIL1 = address1;
SWARSEL_MAIL2 = address2;
SWARSEL_MAIL3 = address3;
@ -29,7 +36,7 @@ in
SWARSEL_CAL3NAME = source3-name;
SWARSEL_FULLNAME = fullName;
SWARSEL_MAIL_ALL = lib.mkDefault allMailAddresses;
GITHUB_NOTIFICATION_TOKEN_PATH = nixosConfig.sops.secrets.github-notifications-token.path;
GITHUB_NOTIFICATION_TOKEN_PATH = confLib.getConfig.sops.secrets.github-notifications-token.path;
OPENROUTER_API_KEY = openrouterApi;
};
};

View file

@ -1,6 +1,6 @@
{ lib, config, nixosConfig ? config, ... }:
{ lib, config, confLib, ... }:
let
inherit (nixosConfig.repo.secrets.common.location) latitude longitude;
inherit (confLib.getConfig.repo.secrets.common.location) latitude longitude;
in
{
options.swarselmodules.gammastep = lib.mkEnableOption "gammastep settings";

View file

@ -1,7 +1,7 @@
{ lib, config, globals, minimal, nixosConfig ? config, ... }:
{ lib, config, globals, minimal, confLib, ... }:
let
inherit (nixosConfig.repo.secrets.common.mail) address1;
inherit (nixosConfig.repo.secrets.common) fullName;
inherit (confLib.getConfig.repo.secrets.common.mail) address1;
inherit (confLib.getConfig.repo.secrets.common) fullName;
gitUser = globals.user.name;
in

View file

@ -1,7 +1,7 @@
{ lib, config, nixosConfig ? config, ... }:
{ lib, config, confLib, ... }:
let
moduleName = "hexchat";
inherit (nixosConfig.repo.secrets.common.irc) irc_nick1;
inherit (confLib.getConfig.repo.secrets.common.irc) irc_nick1;
in
{
options.swarselmodules.${moduleName} = lib.mkEnableOption "enable ${moduleName} and settings";

View file

@ -1,7 +1,7 @@
{ lib, config, inputs, nixosConfig ? config, ... }:
{ lib, config, inputs, globals, confLib, ... }:
let
inherit (nixosConfig.repo.secrets.common.mail) address1 address2 address2-name address3 address3-name address4 address4-user address4-host;
inherit (nixosConfig.repo.secrets.common) fullName;
inherit (confLib.getConfig.repo.secrets.common.mail) address1 address2 address2-name address3 address3-name address4;
inherit (confLib.getConfig.repo.secrets.common) fullName;
inherit (config.swarselsystems) xdgDir;
in
{
@ -123,24 +123,43 @@ in
maildirBasePath = "Mail";
accounts = {
swarsel = {
address = address4;
userName = address4-user;
realName = fullName;
passwordCommand = "cat ${nixosConfig.sops.secrets.address4-token.path}";
smtp = {
host = address4-host;
port = 587;
tls = {
enable = true;
useStartTls = true;
};
imap = {
host = globals.services.mailserver.domain;
port = 993;
tls.enable = true; # SSL/TLS
};
mu.enable = false;
smtp = {
host = globals.services.mailserver.domain;
port = 465;
tls.enable = true; # SSL/TLS
};
thunderbird = {
enable = true;
profiles = [ "default" ];
};
address = address4;
userName = address4;
realName = fullName;
passwordCommand = "cat ${confLib.getConfig.sops.secrets.address4-token.path}";
mu.enable = true;
msmtp = {
enable = true;
};
mbsync = {
enable = false;
enable = true;
create = "maildir";
expunge = "both";
patterns = [ "*" ];
extraConfig = {
channel = {
Sync = "All";
};
account = {
Timeout = 120;
PipelineDepth = 1;
AuthMechs = "LOGIN";
};
};
};
};
@ -150,7 +169,7 @@ in
address = address1;
userName = address1;
realName = fullName;
passwordCommand = "cat ${nixosConfig.sops.secrets.address1-token.path}";
passwordCommand = "cat ${confLib.getConfig.sops.secrets.address1-token.path}";
gpg = {
key = "0x76FD3810215AE097";
signByDefault = true;
@ -164,7 +183,7 @@ in
address = address2;
userName = address2;
realName = address2-name;
passwordCommand = "cat ${nixosConfig.sops.secrets.address2-token.path}";
passwordCommand = "cat ${confLib.getConfig.sops.secrets.address2-token.path}";
}
defaultSettings;
@ -174,7 +193,7 @@ in
address = address3;
userName = address3;
realName = address3-name;
passwordCommand = "cat ${nixosConfig.sops.secrets.address3-token.path}";
passwordCommand = "cat ${confLib.getConfig.sops.secrets.address3-token.path}";
}
defaultSettings;

View file

@ -14,11 +14,13 @@
in
{
enable = true;
package = pkgs.symlinkJoin {
name = "nix-index";
paths = [ commandNotFound ];
};
};
programs.nix-index-database.comma.enable = true;
};
}

View file

@ -1,7 +1,7 @@
{ lib, config, pkgs, nixosConfig ? config, ... }:
{ lib, config, pkgs, confLib, ... }:
let
moduleName = "obsidian";
inherit (nixosConfig.repo.secrets.common.obsidian) userIgnoreFilters;
inherit (confLib.getConfig.repo.secrets.common.obsidian) userIgnoreFilters;
name = "Main";
in
{

View file

@ -1,4 +1,4 @@
{ lib, config, ... }:
{ lib, config, globals, ... }:
let
moduleName = "opkssh";
in
@ -13,7 +13,7 @@ in
providers = [
{
alias = "kanidm";
issuer = "https://sso.swarsel.win/oauth2/openid/opkssh";
issuer = "https://${globals.services.kanidm.domain}/oauth2/openid/opkssh";
client_id = "opkssh";
scopes = "openid email profile";
redirect_uris = [

View file

@ -25,6 +25,9 @@
# ssh login using idm
opkssh
# cache
attic-client
# dict
(aspellWithDicts (dicts: with dicts; [ de en en-computers en-science ]))
@ -60,7 +63,6 @@
nix-inspect
nixpkgs-review
manix
comma
# shellscripts
shfmt

View file

@ -1,6 +1,7 @@
{ self, outputs, lib, pkgs, config, ... }:
{ self, outputs, lib, pkgs, config, globals, confLib, ... }:
let
inherit (config.swarselsystems) mainUser flakePath isNixos isLinux;
inherit (confLib.getConfig.repo.secrets.common) atticPublicKey;
in
{
options.swarselmodules.general = lib.mkEnableOption "general nix settings";
@ -22,7 +23,7 @@ in
};
in
''
plugin-files = ${nix-plugins}/lib/nix/plugins
plugin-files = ${nix-plugins}/lib/nix/plugins
extra-builtins-file = ${self + /nix/extra-builtins.nix}
'';
settings = {
@ -33,7 +34,17 @@ in
"cgroups"
"pipe-operators"
];
trusted-users = [ "@wheel" "${mainUser}" ];
substituters = [
"https://${globals.services.attic.domain}/${mainUser}"
];
trusted-public-keys = [
atticPublicKey
];
trusted-users = [
"@wheel"
"${mainUser}"
(lib.mkIf config.swarselmodules.server.ssh-builder "builder")
];
connect-timeout = 5;
bash-prompt-prefix = "$SHLVL:\\w ";
bash-prompt = "$(if [[ $? -gt 0 ]]; then printf \"\"; else printf \"\"; fi)λ ";

View file

@ -6,8 +6,8 @@ in
options.swarselmodules.sops = lib.mkEnableOption "sops settings";
config = lib.optionalAttrs (inputs ? sops) {
sops = {
age.sshKeyPaths = [ "${homeDir}/.ssh/sops" "${homeDir}/.ssh/ssh_host_ed25519_key" ];
defaultSopsFile = "${homeDir}/.dotfiles/secrets/general/secrets.yaml";
age.sshKeyPaths = [ "${homeDir}/.ssh/sops" "${if config.swarselsystems.isImpermanence then "/persist" else ""}${homeDir}/.ssh/ssh_host_ed25519_key" ];
defaultSopsFile = "${if config.swarselsystems.isImpermanence then "/persist" else ""}${homeDir}/.dotfiles/secrets/general/secrets.yaml";
validateSopsFiles = false;
};

View file

@ -1,7 +1,7 @@
{ lib, config, nixosConfig ? config, ... }:
{ inputs, lib, config, confLib, ... }:
{
options.swarselmodules.ssh = lib.mkEnableOption "ssh settings";
config = lib.mkIf config.swarselmodules.ssh {
config = lib.mkIf config.swarselmodules.ssh ({
programs.ssh = {
enable = true;
enableDefaultConfig = false;
@ -18,11 +18,15 @@
serverAliveCountMax = 3;
hashKnownHosts = false;
userKnownHostsFile = "~/.ssh/known_hosts";
controlMaster = "no";
controlMaster = "auto";
controlPath = "~/.ssh/master-%r@%n:%p";
controlPersist = "no";
controlPersist = "5m";
};
} // nixosConfig.repo.secrets.common.ssh.hosts;
} // confLib.getConfig.repo.secrets.common.ssh.hosts;
};
};
} // lib.optionalAttrs (inputs ? sops) {
sops.secrets = lib.mkIf (!config.swarselsystems.isPublic && !config.swarselsystems.isNixos) {
builder-key = { path = "${config.home.homeDirectory}/.ssh/builder"; mode = "0600"; };
};
});
}

View file

@ -1,4 +1,4 @@
{ config, lib, vars, nixosConfig ? config, ... }:
{ config, lib, vars, confLib, ... }:
let
eachOutput = _: monitor: {
inherit (monitor) name;
@ -381,7 +381,7 @@ in
export XDG_CURRENT_DESKTOP=sway;
export XDG_SESSION_DESKTOP=sway;
export _JAVA_AWT_WM_NONREPARENTING=1;
export GITHUB_NOTIFICATION_TOKEN_PATH=${nixosConfig.sops.secrets.github-notifications-token.path};
export GITHUB_NOTIFICATION_TOKEN_PATH=${confLib.getConfig.sops.secrets.github-notifications-token.path};
'' + vars.waylandExports;
# extraConfigEarly = "
# exec systemctl --user import-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK

View file

@ -1,4 +1,4 @@
{ lib, config, inputs, nixosConfig ? config, ... }:
{ lib, config, inputs, confLib, ... }:
let
inherit (config.swarselsystems) homeDir;
in
@ -9,8 +9,8 @@ in
pam.yubico.authorizedYubiKeys = lib.mkIf (config.swarselsystems.isNixos && !config.swarselsystems.isPublic) {
ids = [
nixosConfig.repo.secrets.common.yubikeys.dev1
nixosConfig.repo.secrets.common.yubikeys.dev2
confLib.getConfig.repo.secrets.common.yubikeys.dev1
confLib.getConfig.secrets.common.yubikeys.dev2
];
};
} // lib.optionalAttrs (inputs ? sops) {

View file

@ -1,4 +1,4 @@
{ config, pkgs, lib, minimal, inputs, globals, nixosConfig ? config, ... }:
{ config, pkgs, lib, minimal, inputs, globals, confLib, ... }:
let
inherit (config.swarselsystems) flakePath isNixos;
crocDomain = globals.services.croc.domain;
@ -67,7 +67,10 @@ in
};
history = {
expireDuplicatesFirst = true;
path = "$HOME/.histfile";
append = true;
ignoreSpace = true;
ignoreDups = true;
path = "${config.home.homeDirectory}/.histfile";
save = 100000;
size = 100000;
};
@ -124,8 +127,8 @@ in
'';
sessionVariables = lib.mkIf (!config.swarselsystems.isPublic) {
CROC_RELAY = crocDomain;
CROC_PASS = "$(cat ${nixosConfig.sops.secrets.croc-password.path or ""})";
GITHUB_TOKEN = "$(cat ${nixosConfig.sops.secrets.github-nixpkgs-review-token.path or ""})";
CROC_PASS = "$(cat ${confLib.getConfig.sops.secrets.croc-password.path or ""})";
GITHUB_TOKEN = "$(cat ${confLib.getConfig.sops.secrets.github-nixpkgs-review-token.path or ""})";
QT_QPA_PLATFORM_PLUGIN_PATH = "${pkgs.libsForQt5.qt5.qtbase.bin}/lib/qt-${pkgs.libsForQt5.qt5.qtbase.version}/plugins";
# QTWEBENGINE_CHROMIUM_FLAGS = "--no-sandbox";
};

View file

@ -1,7 +1,6 @@
{ lib, config, ... }:
_:
{
options.swarselmodules.optional.framework = lib.mkEnableOption "optional framework machine settings";
config = lib.mkIf config.swarselmodules.optional.framework {
config = {
swarselsystems = {
inputs = {
"12972:18:Framework_Laptop_16_Keyboard_Module_-_ANSI_Keyboard" = {

View file

@ -1,10 +1,9 @@
{ lib, config, pkgs, nixosConfig ? config, ... }:
{ config, pkgs, confLib, ... }:
let
inherit (config.swarselsystems) isNixos;
in
{
options.swarselmodules.optional.gaming = lib.mkEnableOption "optional gaming settings";
config = lib.mkIf config.swarselmodules.optional.gaming {
config = {
# specialisation = {
# gaming.configuration = {
home.packages = with pkgs; [
@ -44,7 +43,7 @@ in
gamescope
umu-launcher
];
steamPackage = if isNixos then nixosConfig.programs.steam.package else pkgs.steam;
steamPackage = if isNixos then confLib.getConfig.programs.steam.package else pkgs.steam;
winePackages = with pkgs; [
wineWow64Packages.waylandFull
];

View file

@ -1,5 +1,8 @@
{ config, pkgs, lib, vars, ... }:
{ inputs, config, pkgs, lib, vars, ... }:
{
imports = [
inputs.niri-flake.homeModules.niri
];
options.swarselmodules.niri = lib.mkEnableOption "niri settings";
config = lib.mkIf config.swarselmodules.niri
{

View file

@ -1,24 +1,22 @@
{ config, lib, nixosConfig ? config, ... }:
{ confLib, ... }:
{
options.swarselmodules.optional.uni = lib.mkEnableOption "optional uni settings";
config = lib.mkIf config.swarselmodules.optional.uni
{
services.pizauth = {
enable = true;
accounts = {
uni = {
authUri = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
tokenUri = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
clientId = "08162f7c-0fd2-4200-a84a-f25a4db0b584";
clientSecret = "TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82";
scopes = [
"https://outlook.office365.com/IMAP.AccessAsUser.All"
"https://outlook.office365.com/SMTP.Send"
"offline_access"
];
loginHint = "${nixosConfig.repo.secrets.local.uni.mailAddress}";
};
config = {
services.pizauth = {
enable = true;
accounts = {
uni = {
authUri = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
tokenUri = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
clientId = "08162f7c-0fd2-4200-a84a-f25a4db0b584";
clientSecret = "TxRBilcHdC6WGBee]fs?QR:SJ8nI[g82";
scopes = [
"https://outlook.office365.com/IMAP.AccessAsUser.All"
"https://outlook.office365.com/SMTP.Send"
"offline_access"
];
loginHint = "${confLib.getConfig.repo.secrets.local.uni.mailAddress}";
};
};
};
};
}

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
{ self, lib, pkgs, config, ... }:
{ self, lib, pkgs, config, globals, ... }:
let
certsSopsFile = self + /secrets/certs/secrets.yaml;
clientSopsFile = self + /secrets/${config.node.name}/secrets.yaml;
@ -50,7 +50,7 @@ in
networking = {
inherit (config.swarselsystems) hostName;
hosts = {
"192.168.178.24" = [ "store.swarsel.win" ];
"${globals.networks.home-lan.hosts.winters.ipv4}" = [ globals.services.transmission.domain ];
};
wireless.iwd = {
enable = true;

View file

@ -30,8 +30,9 @@
libsForQt5.qt5.qtwayland
# nix package database
nix-index
# do not do this! clashes with the flake
# nix-index
nixos-generators
# commit hooks
@ -47,6 +48,9 @@
# better make for general tasks
just
# sops
ssh-to-age
sops
# keyboards
qmk

View file

@ -0,0 +1,85 @@
{ lib, config, globals, ... }:
let
inherit (config.swarselsystems) homeDir mainUser isClient;
in
{
options.swarselmodules.remotebuild = lib.mkEnableOption "enable remote builds on this machine";
config = lib.mkIf config.swarselmodules.remotebuild {
sops.secrets = {
builder-key = lib.mkIf isClient { owner = mainUser; path = "${homeDir}/.ssh/builder"; mode = "0600"; };
nixbuild-net-key = { owner = mainUser; path = "${homeDir}/.ssh/nixbuild-net"; mode = "0600"; };
};
nix = {
settings.builders-use-substitutes = true;
distributedBuilds = true;
buildMachines = [
(lib.mkIf isClient {
hostName = config.repo.secrets.common.builder1-ip;
system = "aarch64-linux";
maxJobs = 20;
speedFactor = 10;
})
(lib.mkIf isClient {
hostName = globals.hosts.belchsfactory.wanAddress4;
system = "aarch64-linux";
maxJobs = 4;
speedFactor = 2;
protocol = "ssh-ng";
})
{
hostName = "eu.nixbuild.net";
system = "x86_64-linux";
maxJobs = 100;
speedFactor = 2;
supportedFeatures = [ "big-parallel" ];
}
];
};
programs.ssh = {
knownHosts = {
nixbuild = {
hostNames = [ "eu.nixbuild.net" ];
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPIQCZc54poJ8vqawd8TraNryQeJnvH1eLpIDgbiqymM";
};
builder1 = lib.mkIf isClient {
hostNames = [ config.repo.secrets.common.builder1-ip ];
publicKey = config.repo.secrets.common.builder1-pubHostKey;
};
jump = lib.mkIf isClient {
hostNames = [ globals.hosts.liliputsteps.wanAddress4 ];
publicKey = config.repo.secrets.common.jump-pubHostKey;
};
builder2 = lib.mkIf isClient {
hostNames = [ globals.hosts.belchsfactory.wanAddress4 ];
publicKey = config.repo.secrets.common.builder2-pubHostKey;
};
};
extraConfig = ''
Host eu.nixbuild.net
ConnectTimeout 1
PubkeyAcceptedKeyTypes ssh-ed25519
ServerAliveInterval 60
IPQoS throughput
IdentityFile ${config.sops.secrets.nixbuild-net-key.path}
'' + lib.optionalString isClient ''
Host ${config.repo.secrets.common.builder1-ip}
ConnectTimeout 1
User ${mainUser}
IdentityFile ${config.sops.secrets.builder-key.path}
Host ${globals.hosts.belchsfactory.wanAddress4}
ConnectTimeout 5
ProxyJump ${globals.hosts.liliputsteps.wanAddress4}
User builder
IdentityFile ${config.sops.secrets.builder-key.path}
Host ${globals.hosts.liliputsteps.wanAddress4}
ConnectTimeout 1
User jump
IdentityFile ${config.sops.secrets.builder-key.path}
'';
};
};
}

View file

@ -5,9 +5,8 @@
sops = {
# age.sshKeyPaths = lib.swarselsystems.mkIfElseList config.swarselsystems.isBtrfs [ "/persist/.ssh/sops" "/persist/.ssh/ssh_host_ed25519_key" ] [ "${config.swarselsystems.homeDir}/.ssh/sops" "/etc/ssh/sops" "/etc/ssh/ssh_host_ed25519_key" ];
age.sshKeyPaths = [ "${config.swarselsystems.homeDir}/.ssh/sops" "/etc/ssh/sops" "/etc/ssh/ssh_host_ed25519_key" ];
# defaultSopsFile = lib.swarselsystems.mkIfElseList config.swarselsystems.isBtrfs "/persist/.dotfiles/secrets/general/secrets.yaml" "${config.swarselsystems.flakePath}/secrets/general/secrets.yaml";
defaultSopsFile = "${config.swarselsystems.flakePath}/secrets/general/secrets.yaml";
age.sshKeyPaths = [ "${config.swarselsystems.homeDir}/.ssh/sops" "/etc/ssh/sops" "${if config.swarselsystems.isImpermanence then "/persist" else ""}/etc/ssh/ssh_host_ed25519_key" ];
defaultSopsFile = "${if config.swarselsystems.isImpermanence then "/persist" else ""}${config.swarselsystems.flakePath}/secrets/general/secrets.yaml";
validateSopsFiles = false;

View file

@ -13,7 +13,7 @@ in
comment = "Sway compositor managed by UWSM";
binPath = "/run/current-system/sw/bin/sway";
};
niri = {
niri = lib.mkIf (config.swarselmodules ? niri) {
prettyName = "Niri";
comment = "Niri compositor managed by UWSM";
binPath = "/run/current-system/sw/bin/niri-session";

View file

@ -82,7 +82,8 @@ let
if netSubmod.config.cidrv6 == null then
null
else
lib.net.cidr.hostCidr hostSubmod.config.id netSubmod.config.cidrv6;
# if we use the /32 wan address as local address directly, do not use the network address in ipv6
lib.net.cidr.hostCidr (if hostSubmod.config.id == 0 then 1 else hostSubmod.config.id) netSubmod.config.cidrv6;
};
};
})
@ -114,13 +115,31 @@ in
services = mkOption {
type = types.attrsOf (
types.submodule {
types.submodule (serviceSubmod: {
options = {
domain = mkOption {
type = types.str;
};
subDomain = mkOption {
readOnly = true;
type = types.str;
default = lib.swarselsystems.getSubDomain serviceSubmod.config.domain;
};
baseDomain = mkOption {
readOnly = true;
type = types.str;
default = lib.swarselsystems.getBaseDomain serviceSubmod.config.domain;
};
proxyAddress4 = mkOption {
type = types.nullOr types.str;
default = null;
};
proxyAddress6 = mkOption {
type = types.nullOr types.str;
default = null;
};
};
}
})
);
};
@ -163,6 +182,12 @@ in
defaultGateway6 = mkOption {
type = types.nullOr types.net.ipv6;
};
wanAddress4 = mkOption {
type = types.nullOr types.net.ipv4;
};
wanAddress6 = mkOption {
type = types.nullOr types.net.ipv6;
};
};
}
);
@ -172,6 +197,10 @@ in
main = mkOption {
type = types.str;
};
externalDns = mkOption {
type = types.listOf types.str;
description = "List of external dns nameservers";
};
};
};
};

View file

@ -24,7 +24,8 @@ in
github-nixpkgs-review-token = { owner = mainUser; };
}) // (lib.optionalAttrs modules.emacs {
emacs-radicale-pw = { owner = mainUser; };
}) // (lib.optionalAttrs modules.optional.work {
github-forge-token = { owner = mainUser; };
}) // (lib.optionalAttrs (modules ? optional-work) {
harica-root-ca = { sopsFile = certsSopsFile; path = "${homeDir}/.aws/certs/harica-root.pem"; owner = mainUser; };
}) // (lib.optionalAttrs modules.anki {
anki-user = { owner = mainUser; };

View file

@ -12,7 +12,6 @@
inputs.nix-index-database.homeModules.nix-index
inputs.sops-nix.homeManagerModules.sops
inputs.spicetify-nix.homeManagerModules.default
# inputs.swarsel-modules.homeModules.default
inputs.swarsel-nix.homeModules.default
{
imports = [

View file

@ -72,6 +72,7 @@ in
hideMounts = true;
directories =
[
"/root/.dotfiles"
"/etc/nix"
"/etc/NetworkManager/system-connections"
"/var/lib/nixos"

View file

@ -11,6 +11,10 @@
description = "Node Name.";
type = lib.types.str;
};
lockFromBootstrapping = lib.mkOption {
description = "Whether this host should be marked to not be bootstrapped again using swarsel-bootstrap.";
type = lib.types.bool;
};
};
};
}

View file

@ -34,6 +34,11 @@ let
"nginx"
"virtualHosts"
]
[
"swarselsystems"
"server"
"dns"
]
];
attrsForEachOption =

View file

@ -1,5 +1,7 @@
{ self, lib, pkgs, config, outputs, inputs, minimal, ... }:
{ self, lib, pkgs, config, outputs, inputs, minimal, globals, ... }:
let
inherit (config.swarselsystems) mainUser;
inherit (config.repo.secrets.common) atticPublicKey;
settings = if minimal then { } else {
environment.etc."nixos/configuration.nix".source = pkgs.writeText "configuration.nix" ''
assert builtins.trace "This location is not used. The config is found in ${config.swarselsystems.flakePath}!" false;
@ -36,7 +38,8 @@ let
channel.enable = false;
registry = rec {
nixpkgs.flake = inputs.nixpkgs;
swarsel.flake = inputs.swarsel;
# swarsel.flake = inputs.swarsel;
swarsel.flake = self;
n = nixpkgs;
s = swarsel;
};
@ -56,8 +59,8 @@ in
config = lib.mkIf config.swarselmodules.general
(lib.recursiveUpdate
{
sops.secrets.github-api-token = lib.mkIf (!minimal) {
sopsFile = "${config.swarselsystems.flakePath}/secrets/general/secrets.yaml";
sops.secrets = lib.mkIf (!minimal) {
github-api-token = { owner = mainUser; };
};
nix =
@ -74,7 +77,17 @@ in
"cgroups"
"pipe-operators"
];
trusted-users = [ "@wheel" "${config.swarselsystems.mainUser}" ];
substituters = [
"https://${globals.services.attic.domain}/${mainUser}"
];
trusted-public-keys = [
atticPublicKey
];
trusted-users = [
"@wheel"
"${config.swarselsystems.mainUser}"
(lib.mkIf config.swarselmodules.server.ssh-builder "builder")
];
};
# extraOptions = ''
# plugin-files = ${pkgs.dev.nix-plugins}/lib/nix/plugins

View file

@ -1,11 +1,8 @@
{ self, pkgs, config, lib, globals, minimal, ... }:
let
sopsFile = self + /secrets/general/secrets.yaml;
in
{ pkgs, config, lib, globals, minimal, ... }:
{
options.swarselmodules.users = lib.mkEnableOption "user config";
config = lib.mkIf config.swarselmodules.users {
sops.secrets.main-user-hashed-pw = lib.mkIf (!config.swarselsystems.isPublic) { inherit sopsFile; neededForUsers = true; };
sops.secrets.main-user-hashed-pw = lib.mkIf (!config.swarselsystems.isPublic) { neededForUsers = true; };
users = {
mutableUsers = lib.mkIf (!minimal) false;

View file

@ -1,7 +1,6 @@
{ lib, config, ... }:
_:
{
options.swarselmodules.optional.amdcpu = lib.mkEnableOption "optional amd cpu settings";
config = lib.mkIf config.swarselmodules.optional.amdcpu {
config = {
hardware = {
cpu.amd.updateMicrocode = true;
};

View file

@ -1,7 +1,6 @@
{ lib, config, ... }:
_:
{
options.swarselmodules.optional.amdgpu = lib.mkEnableOption "optional amd gpu settings";
config = lib.mkIf config.swarselmodules.optional.amdgpu {
config = {
hardware = {
amdgpu = {
opencl.enable = true;

View file

@ -1,7 +1,13 @@
{ lib, config, ... }:
{ self, config, ... }:
{
options.swarselmodules.optional.framework = lib.mkEnableOption "optional framework machine settings";
config = lib.mkIf config.swarselmodules.optional.framework {
config = {
home-manager.users."${config.swarselsystems.mainUser}" = {
imports = [
"${self}/modules/home/optional/framework.nix"
];
};
services = {
fwupd = {
enable = true;

View file

@ -1,7 +1,13 @@
{ pkgs, lib, config, ... }:
{ self, pkgs, config, ... }:
{
options.swarselmodules.optional.gaming = lib.mkEnableOption "optional gaming settings";
config = lib.mkIf config.swarselmodules.optional.gaming {
config = {
home-manager.users."${config.swarselsystems.mainUser}" = {
imports = [
"${self}/modules/home/optional/gaming.nix"
];
};
programs.steam = {
enable = true;
package = pkgs.steam;

View file

@ -1,6 +1,5 @@
{ lib, config, ... }:
{
options.swarselmodules.optional.hibernation = lib.mkEnableOption "optional amd gpu settings";
options.swarselsystems = {
hibernation = {
offset = lib.mkOption {
@ -13,7 +12,7 @@
};
};
};
config = lib.mkIf config.swarselmodules.optional.hibernation {
config = {
boot = {
kernelParams = [
"resume_offset=${builtins.toString config.swarselsystems.hibernation.offset}"

View file

@ -1,11 +1,9 @@
{ lib, config, ... }:
_:
{
options.swarselmodules.optional.microvmGuest = lib.mkEnableOption "optional microvmGuest settings";
# imports = [
# inputs.microvm.nixosModules.microvm
# "${self}/profiles/nixos"
# "${self}/modules/nixos"
# ];
config = lib.mkIf config.swarselmodules.optional.microvmGuest
config =
{ };
}

View file

@ -1,10 +1,7 @@
{ lib, config, ... }:
{ config, lib, ... }:
{
options = {
swarselmodules.optional.microvmHost = lib.mkEnableOption "optional microvmHost settings";
};
# imports = [
# inputs.microvm.nixosModules.host
# inputs.microvm.nixosModules.host
# ];
config = lib.mkIf (config.guests != { }) {

View file

@ -1,8 +1,11 @@
{ lib, config, pkgs, ... }:
{ inputs, lib, config, pkgs, ... }:
let
moduleName = "niri";
in
{
imports = [
inputs.niri-flake.nixosModules.niri
];
options.swarselmodules.${moduleName} = lib.mkEnableOption "${moduleName} settings";
config = lib.mkIf config.swarselmodules.${moduleName}
{

View file

@ -1,7 +1,6 @@
{ lib, config, pkgs, ... }:
{ pkgs, ... }:
{
options.swarselmodules.optional.nswitch-rcm = lib.mkEnableOption "optional nswitch-rcm settings";
config = lib.mkIf config.swarselmodules.optional.nswitch-rcm {
config = {
services.nswitch-rcm = {
enable = true;
package = pkgs.fetchurl {

View file

@ -0,0 +1,50 @@
{ lib, config, globals, ... }:
{
networking = {
useDHCP = lib.mkForce false;
useNetworkd = true;
dhcpcd.enable = false;
renameInterfacesByMac = lib.mapAttrs (_: v: v.mac) (
config.repo.secrets.local.networking.networks or { }
);
};
boot.initrd.systemd.network = {
enable = true;
networks."10-${config.swarselsystems.server.localNetwork}" = config.systemd.network.networks."10-${config.swarselsystems.server.localNetwork}";
};
systemd = {
network = {
enable = true;
wait-online.enable = false;
networks =
let
netConfig = config.repo.secrets.local.networking;
in
{
"10-${config.swarselsystems.server.localNetwork}" = {
address = [
"${globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.cidrv4}"
"${globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.cidrv6}"
];
routes = [
{
Gateway = netConfig.defaultGateway6;
GatewayOnLink = true;
}
{
Gateway = netConfig.defaultGateway4;
GatewayOnLink = true;
}
];
networkConfig = {
IPv6PrivacyExtensions = true;
IPv6AcceptRA = false;
};
matchConfig.MACAddress = netConfig.networks.${config.swarselsystems.server.localNetwork}.mac;
linkConfig.RequiredForOnline = "routable";
};
};
};
};
}

View file

@ -0,0 +1,11 @@
{ self, config, ... }:
{
config = {
home-manager.users."${config.swarselsystems.mainUser}" = {
imports = [
"${self}/modules/home/optional/work.nix"
];
};
};
}

View file

@ -1,7 +1,6 @@
{ lib, config, pkgs, ... }:
{
options.swarselmodules.optional.virtualbox = lib.mkEnableOption "optional VBox settings";
config = lib.mkIf config.swarselmodules.optional.virtualbox {
config = {
# specialisation = {
# VBox.configuration = {
virtualisation.virtualbox = {

View file

@ -1,8 +1,7 @@
{ lib, config, ... }:
_:
{
options.swarselmodules.optional.vmware = lib.mkEnableOption "optional vmware settings";
config = lib.mkIf config.swarselmodules.optional.vmware {
config = {
virtualisation.vmware.host.enable = true;
virtualisation.vmware.guest.enable = true;
};

View file

@ -1,4 +1,4 @@
{ self, lib, pkgs, config, configName, ... }:
{ self, lib, pkgs, config, ... }:
let
inherit (config.swarselsystems) mainUser homeDir;
iwd = config.networking.networkmanager.wifi.backend == "iwd";
@ -6,18 +6,24 @@ let
sopsFile = self + /secrets/work/secrets.yaml;
in
{
options.swarselmodules.optional.work = lib.mkEnableOption "optional work settings";
options.swarselsystems = {
hostName = lib.mkOption {
type = lib.types.str;
default = configName;
default = config.node.name;
};
fqdn = lib.mkOption {
type = lib.types.str;
default = "";
};
};
config = lib.mkIf config.swarselmodules.optional.work {
config = {
home-manager.users."${config.swarselsystems.mainUser}" = {
imports = [
"${self}/modules/home/optional/work.nix"
];
};
sops =
let
secretNames = [

View file

@ -1,11 +1,7 @@
{ self, lib, config, globals, ... }:
{ self, lib, config, globals, dns, confLib, ... }:
let
inherit (config.swarselsystems) sopsFile;
servicePort = 27701;
serviceName = "ankisync";
serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
serviceAddress = globals.networks.home.hosts.${config.node.name}.ipv4;
inherit (confLib.gen { name = "ankisync"; port = 27701; }) servicePort serviceName serviceDomain serviceAddress serviceProxy proxyAddress4 proxyAddress6;
ankiUser = globals.user.name;
in
@ -13,6 +9,10 @@ in
options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselmodules.server.${serviceName} {
nodes.stoicclub.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = {
"${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
};
networking.firewall.allowedTCPPorts = [ servicePort ];
sops.secrets.anki-pw = { inherit sopsFile; owner = "root"; };
@ -23,7 +23,10 @@ in
info = "https://${serviceDomain}";
};
globals.services.${serviceName}.domain = serviceDomain;
globals.services.${serviceName} = {
domain = serviceDomain;
inherit proxyAddress4 proxyAddress6;
};
services.anki-sync-server = {
enable = true;
@ -38,7 +41,7 @@ in
];
};
nodes.moonside.services.nginx = {
nodes.${serviceProxy}.services.nginx = {
upstreams = {
${serviceName} = {
servers = {

View file

@ -0,0 +1,129 @@
{ lib, config, globals, dns, confLib, ... }:
let
inherit (confLib.gen { name = "attic"; port = 8091; }) serviceName serviceDir servicePort serviceAddress serviceDomain serviceProxy proxyAddress4 proxyAddress6;
inherit (config.swarselsystems) mainUser isPublic sopsFile;
serviceDB = "atticd";
in
{
options = {
swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
};
config = lib.mkIf config.swarselmodules.server.${serviceName} {
nodes.stoicclub.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = {
"${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
};
globals.services.${serviceName} = {
domain = serviceDomain;
inherit proxyAddress4 proxyAddress6;
};
sops = lib.mkIf (!isPublic) {
secrets = {
attic-server-token = { inherit sopsFile; };
attic-garage-access-key = { inherit sopsFile; };
attic-garage-secret-key = { inherit sopsFile; };
};
templates = {
"attic.env" = {
content = ''
ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64=${config.sops.placeholder.attic-server-token}
AWS_ACCESS_KEY_ID=${config.sops.placeholder.attic-garage-access-key}
AWS_SECRET_ACCESS_KEY=${config.sops.placeholder.attic-garage-secret-key}
'';
};
};
};
services.atticd = {
enable = true;
environmentFile = config.sops.templates."attic.env".path;
settings = {
listen = "[::]:${builtins.toString servicePort}";
api-endpoint = "https://${serviceDomain}/";
allowed-hosts = [
serviceDomain
];
require-proof-of-possession = false;
compression = {
type = "zstd";
level = 3;
};
database.url = "postgresql:///atticd?host=/run/postgresql";
storage =
if config.swarselmodules.server.garage then {
type = "s3";
region = mainUser;
bucket = serviceName;
# attic must be patched to never serve pre-signed s3 urls directly
# otherwise it will redirect clients to this localhost endpoint
endpoint = "http://127.0.0.1:3900";
} else {
type = "local";
path = serviceDir;
# attic must be patched to never serve pre-signed s3 urls directly
# otherwise it will redirect clients to this localhost endpoint
};
garbage-collection = {
interval = "1 day";
default-retention-period = "3 months";
};
chunking = {
nar-size-threshold = if config.swarselmodules.server.garage then 0 else 64 * 1024; # 64 KiB
min-size = 16 * 1024; # 16 KiB
avg-size = 64 * 1024; # 64 KiB
max-size = 256 * 1024; # 256 KiBize = 262144;
};
};
};
services.postgresql = {
enable = true;
enableTCPIP = true;
ensureDatabases = [ serviceDB ];
ensureUsers = [
{
name = serviceDB;
ensureDBOwnership = true;
}
];
};
systemd.services.atticd = lib.mkIf config.swarselmodules.server.garage {
requires = [ "garage.service" ];
after = [ "garage.service" ];
};
nodes.${serviceProxy}.services.nginx = {
upstreams = {
${serviceName} = {
servers = {
"${serviceAddress}:${builtins.toString servicePort}" = { };
};
};
};
virtualHosts = {
"${serviceDomain}" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
oauth2.enable = false;
locations = {
"/" = {
proxyPass = "http://${serviceName}";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
};
}

View file

@ -1,16 +1,21 @@
{ lib, config, globals, ... }:
{ lib, config, globals, dns, confLib, ... }:
let
servicePort = 8888;
serviceName = "atuin";
serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
serviceAddress = globals.networks.home.hosts.${config.node.name}.ipv4;
inherit (confLib.gen { name = "atuin"; port = 8888; }) servicePort serviceName serviceDomain serviceAddress serviceProxy proxyAddress4 proxyAddress6;
in
{
options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselmodules.server.${serviceName} {
nodes.stoicclub.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = {
"${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
};
topology.self.services.${serviceName}.info = "https://${serviceDomain}";
globals.services.${serviceName}.domain = serviceDomain;
globals.services.${serviceName} = {
domain = serviceDomain;
inherit proxyAddress4 proxyAddress6;
};
services.${serviceName} = {
enable = true;
@ -20,7 +25,7 @@ in
openRegistration = false;
};
nodes.moonside.services.nginx = {
nodes.${serviceProxy}.services.nginx = {
upstreams = {
${serviceName} = {
servers = {

View file

@ -0,0 +1,67 @@
{ self, lib, config, ... }:
{
options.swarselmodules.server.bastion = lib.mkEnableOption "enable bastion on server";
config = lib.mkIf config.swarselmodules.server.bastion {
users = {
groups = {
jump = { };
};
users = {
"jump" = {
isNormalUser = true;
useDefaultShell = true;
group = lib.mkForce "jump";
createHome = lib.mkForce true;
openssh.authorizedKeys.keyFiles = [
(self + /secrets/keys/ssh/yubikey.pub)
(self + /secrets/keys/ssh/magicant.pub)
(self + /secrets/keys/ssh/builder.pub)
];
};
};
};
services.openssh = {
enable = true;
startWhenNeeded = lib.mkForce false;
authorizedKeysInHomedir = false;
extraConfig = ''
Match User jump
PermitTTY no
X11Forwarding no
PermitTunnel no
GatewayPorts no
AllowAgentForwarding no
'';
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = lib.mkDefault "no";
AllowUsers = [
"jump"
];
};
hostKeys = lib.mkIf (!config.swarselmodules.server.ssh) [
{
path = "/etc/ssh/ssh_host_ed25519_key";
type = "ed25519";
}
];
};
home-manager.users.jump.config = {
home.stateVersion = lib.mkDefault "23.05";
programs.ssh = {
enable = true;
enableDefaultConfig = false;
matchBlocks = {
"*" = {
forwardAgent = false;
};
} // config.repo.secrets.local.ssh.hosts;
};
};
};
}

View file

@ -1,5 +1,6 @@
{ self, lib, config, pkgs, ... }:
{ self, lib, config, pkgs, dns, globals, confLib, ... }:
let
inherit (confLib.gen { name = "croc"; }) serviceName serviceDomain proxyAddress4 proxyAddress6;
servicePorts = [
9009
9010
@ -7,8 +8,6 @@ let
9012
9013
];
serviceName = "croc";
serviceDomain = config.repo.secrets.common.services.domains.${serviceName};
inherit (config.swarselsystems) sopsFile;
@ -18,6 +17,10 @@ in
options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server";
config = lib.mkIf config.swarselmodules.server.${serviceName} {
nodes.stoicclub.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = {
"${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
};
sops = {
secrets = {
croc-password = { inherit sopsFile; };
@ -39,7 +42,10 @@ in
icon = "${self}/files/topology-images/${serviceName}.png";
};
globals.services.${serviceName}.domain = serviceDomain;
globals.services.${serviceName} = {
domain = serviceDomain;
inherit proxyAddress4 proxyAddress6;
};
services.${serviceName} = {
enable = true;

View file

@ -1,10 +1,15 @@
{ self, pkgs, lib, config, globals, minimal, ... }:
let
localIp = globals.networks.home.hosts.${config.node.name}.ipv4;
subnetMask = globals.networks.home.subnetMask4;
localIp = globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.ipv4;
subnetMask = globals.networks.${config.swarselsystems.server.netConfigName}.subnetMask4;
gatewayIp = globals.hosts.${config.node.name}.defaultGateway4;
hostKeyPath = "/etc/secrets/initrd/ssh_host_ed25519_key";
hostKeyPathBase = "/etc/secrets/initrd/ssh_host_ed25519_key";
hostKeyPath =
if config.swarselsystems.isImpermanence then
"/persist/${hostKeyPathBase}"
else
"${hostKeyPathBase}";
in
{
options.swarselmodules.server.diskEncryption = lib.mkEnableOption "enable disk encryption config";
@ -14,35 +19,40 @@ in
};
config = lib.mkIf (config.swarselmodules.server.diskEncryption && config.swarselsystems.isCrypted) {
system.activationScripts."createPersistentStorageDirs" = lib.mkIf config.swarselsystems.isImpermanence {
deps = [ "ensureInitrdHostkey" ];
};
system.activationScripts.ensureInitrdHostkey = lib.mkIf (config.swarselprofiles.server || minimal) {
text = ''
[[ -e ${hostKeyPath} ]] || ${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" -f ${hostKeyPath}
'';
deps = [ "users" ];
deps = [
"etc"
];
};
environment.persistence."/persist" = lib.mkIf (config.swarselsystems.isImpermanence && (config.swarselprofiles.server || minimal)) {
files = [ hostKeyPath ];
files = [ hostKeyPathBase ];
};
boot = lib.mkIf (config.swarselprofiles.server || minimal) {
kernelParams = lib.mkIf (!config.swarselsystems.isLaptop) [
boot = lib.mkIf (!config.swarselsystems.isClient) {
kernelParams = lib.mkIf (!config.swarselsystems.isCloud) [
"ip=${localIp}::${gatewayIp}:${subnetMask}:${config.networking.hostName}::none"
];
initrd = {
availableKernelModules = config.swarselsystems.networkKernelModules;
network = {
enable = true;
udhcpc.enable = lib.mkIf config.swarselsystems.isLaptop true;
flushBeforeStage2 = true;
ssh = {
enable = true;
port = 2222; # avoid hostkey changed nag
authorizedKeyFiles = [
(self + /secrets/keys/ssh/yubikey.pub)
(self + /secrets/keys/ssh/magicant.pub)
authorizedKeys = [
''command="/bin/systemctl default" ${builtins.readFile "${self}/secrets/keys/ssh/yubikey.pub"}''
''command="/bin/systemctl default" ${builtins.readFile "${self}/secrets/keys/ssh/magicant.pub"}''
];
hostKeys = [ hostKeyPath ];
hostKeys = [ hostKeyPathBase ];
};
# postCommands = ''
# echo 'cryptsetup-askpass || echo "Unlock was successful; exiting SSH session" && exit 1' >> /root/.profile
@ -52,23 +62,24 @@ in
initrdBin = with pkgs; [
cryptsetup
];
services = {
unlock-luks = {
wantedBy = [ "initrd.target" ];
after = [ "network.target" ];
before = [ "systemd-cryptsetup@cryptroot.service" ];
path = [ "/bin" ];
# NOTE: the below does put the text into /root/.profile, but the command will not be run
# services = {
# unlock-luks = {
# wantedBy = [ "initrd.target" ];
# after = [ "network.target" ];
# before = [ "systemd-cryptsetup@cryptroot.service" ];
# path = [ "/bin" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
# serviceConfig = {
# Type = "oneshot";
# RemainAfterExit = true;
# };
script = ''
echo "systemctl default" >> /root/.profile
'';
};
};
# script = ''
# echo "systemctl default" >> /root/.profile
# '';
# };
# };
};
};
};

Some files were not shown because too many files have changed in this diff Show more