Compare commits

...

181 Commits

Author SHA1 Message Date
383c7bb15e [Gluetun] Switches to Wireguard config 2026-02-24 16:40:02 -08:00
a4bb91e68e [Wallabag] Adds wallabag 2026-02-24 16:40:02 -08:00
13f301c4fb [Obelisk] Adds Reflex FRP binary caches to the system 2026-02-12 15:53:26 -08:00
114a1ae125 [notes] Update Syncthing config for Proxima 2026-02-06 09:47:12 -08:00
9a4ab98506 [Jellyfin] Update to 10.11.6 2026-02-03 15:42:41 -08:00
bf0d4a11d2 [nix] Fixes deprecated function usage. 2026-02-02 17:18:04 -08:00
0950758532 [3d printing] Fix FreeCAD launcher 2026-01-27 23:20:31 -08:00
31907ff47b [Haskell] Adds support to the LSP. [neovim] Merges and checks in lazyvim.json 2026-01-26 12:44:23 -08:00
a985e8a0da [Browser,Firefox,Librewolf] Switch back to Firefox as default browser for better sync and features 2026-01-22 10:02:31 -08:00
8add79d14c [flake] Update 2026-01-09 16:19:43 -08:00
93523c54f2 [altair] Cleans up hardware config 2026-01-09 16:15:41 -08:00
c07dfe4259 [neovim] Check in extras config. 2026-01-06 15:29:51 -08:00
978b7ac2b7 [flake] update to 25.11 2026-01-02 12:37:18 -08:00
d1ccaa1c57 [hyprland] Adds a keybind for saving screenshots to files 2026-01-02 12:36:06 -08:00
1c098a032b [neovim] Switch to tab-completion so that I don't get confused when switching editors 2025-12-30 11:10:30 -08:00
b951779a92 [audio] Adds script to inhibit sleep while media is playing. 2025-12-30 11:05:10 -08:00
889d0b1057 [nvim] Adds a commented section about images in markdown docs, though it won't work in Foot tty. 2025-12-20 12:17:00 -08:00
64cac2b167 [printing] Adds Brother printer 2025-12-14 17:26:25 -08:00
2f278b5ecb [nvim] Adds link to do documentation for RenderMarkdown plugin 2025-12-12 12:25:51 -08:00
a0448def04 [desktop] Adds inkscape and groups some similar apps 2025-12-08 16:15:27 -08:00
edb0f18989 [nvim] Updates a few plugins to new versions/repositories 2025-12-08 16:06:55 -08:00
cfde735570 [nvim] Removes copilot 2025-11-21 12:18:06 -08:00
9bbb4aa2dc [astronomy] Added to Altair, removed from Vega 2025-11-21 12:18:06 -08:00
9818771f7c [dm-companion] Fixes deployment script? 2025-11-21 12:09:29 -08:00
f7af96c497 [scrutiny] Switches to UUIDs, removes missing device. 2025-11-21 12:09:29 -08:00
499b0f4334 [astronomy] Adds Stellarium, KStars and Celestia to Vega 2025-10-21 11:58:35 -07:00
879ad11d96 [flake] update 2025-10-19 20:18:27 -07:00
640eaec8a1 [3d printing] Adds Orynt 2025-10-16 20:10:02 -07:00
898e1bdde0 [3d printing] Adds openscad 2025-10-15 17:42:32 -07:00
a6d4c40beb [notes, syncthing] Adds proxima to syncing. 2025-10-14 15:32:00 -07:00
a13e8cea19 [docker dev] Remove rootless mode because some apps (Bambu Studio) do not work in rootless mode 2025-10-07 16:59:44 -07:00
3b8e38e702 [immich] Adds but disabled Immich because it's crashing on start-up 2025-09-25 17:23:01 -07:00
05c001081e [Containers] Adds GPU support for docker 2025-09-22 20:17:01 -07:00
3e2e3aca21 [Flake] Update 2025-09-19 14:50:05 -07:00
1837a545a4 [3d printing] Adds freecad 2025-09-19 14:32:14 -07:00
5c7649d3df [3d printing] Adds slicers, blender 2025-09-16 20:59:34 -07:00
3bb9ebf875 [desktop] Removes QuteBrowser and adds Chromium 2025-09-16 20:59:34 -07:00
ee3b7c2c53 [wow.blazestar.net] Adds static site 2025-09-15 17:08:03 -07:00
746e31dca2 [nextcloud] Move back to a stable version after some bugs 2025-09-15 17:08:03 -07:00
9a59e60044 [nextcloud] Remove unused env vars 2025-09-15 17:08:03 -07:00
646221721e [Tandoor] Adds tandoor service 2025-09-15 17:08:03 -07:00
554b2863f3 [notes] Fixes alias. [discord] Adds skeleton for PTT hotkey passthrough 2025-09-10 12:05:13 -07:00
5829dc294e [Flake] Updates dependencies 2025-09-02 15:18:59 -07:00
0645912626 [hyprctl] Tweaks for Cyberpunk 2025-09-01 17:49:50 -07:00
430a041724 Adds Nexus-Mods app. 2025-09-01 17:48:04 -07:00
80512c29ea [notes] Adds alias for editing notes 2025-08-21 10:32:21 -07:00
392d6fe537 [discord] Attempts to fix the keybinding issue 2025-08-21 10:31:05 -07:00
6d1e715d9c [neovim] Add link-openining to Obsidian 2025-08-18 11:22:44 -07:00
94b8065dba [gaming] Update warcraft logs client 2025-08-15 22:09:02 -07:00
ea902faf43 [neovim] Cleans up some Snacks config 2025-08-03 11:10:49 -07:00
3d3fa1ed68 [eww] Remove launcher I never use. 2025-08-03 10:36:52 -07:00
cd4367e252 [gaming] Updates Raider.io launcher, still doesn't run properly. 2025-08-03 10:36:52 -07:00
cf4d54ebfd [Webkooks] Switches the NPM deploy to rsync the directory instead of link it because docker will follow the link and then not update. 2025-07-31 17:09:56 -07:00
3b46856b66 [Uptime Kuma] Adds Uptime Kuma to blazestar.net 2025-07-31 16:05:15 -07:00
1d1702bd9b [webhook] Updates the NPM install hooks to do a new directory on each deploy. Clean will come later 2025-07-31 15:34:45 -07:00
8a566715db [habits] Removes Beaver Habits because it seems underdeveloped 2025-07-25 13:43:27 -07:00
19d8c5c097 [habits] Adds beaver habits. [oidc] Sets up OIDC auth forwarding, it works, but not sure which header. 2025-07-25 12:22:33 -07:00
b3c6e951ee [mcp] Removes specific kernel packages for ZFS, preferring the default which should be compatible. 2025-07-18 18:11:05 -07:00
44ac6ce262 [shell] Adds fuser util 2025-07-18 18:10:26 -07:00
1c2cd59f1f [web-containers] Adds an explicit service in case we want to have two services. 2025-07-18 17:54:41 -07:00
ca4d4d714c Enables android dev on altair 2025-07-14 15:29:56 -07:00
8791432964 [goatcounter] Fixes instance for blazestar.net 2025-07-14 15:14:13 -07:00
638f34c2d3 [goatcounter] Adds instance for blazestar.net 2025-07-10 15:35:57 -07:00
743ce58b14 [graphics] Modularizes graphics config. Applies it to vega. 2025-07-01 16:13:08 -07:00
0a1d7a24e7 [dm-companion] Fixes deployment script to apply migrations. 2025-06-28 20:21:41 -07:00
81cb09176c [nvim] Use snacks as the primary picker, no relying on extras 2025-06-27 20:31:26 -07:00
7f04c3aa4c [nvim] Remove less from treesitter installed grammars 2025-06-27 20:01:11 -07:00
bded723261 [nix] Updates again because signal isn't building properly on the last version 2025-06-27 18:16:06 -07:00
0776b9d7e5 [eww] Use the correct network interface for Vega 2025-06-27 17:54:53 -07:00
0ac07e4256 Ensure some grammars are installed for treesitter 2025-06-26 17:46:20 -07:00
cedf51580e [dm-companion] Serves index for all unrecognized files, sets some cache directives 2025-06-26 16:32:39 -07:00
1dc7d7b355 [matrix] Got Blazestar.net working, but federation and cross-server joining isn't quite right. 2025-06-25 15:49:25 -07:00
b1510c3670 [containers] Disables some containers, adds some docker config. 2025-06-24 18:32:15 -07:00
f4dd4583db [nix] Modularized the container backend so I can easily switch it with an option 2025-06-24 17:31:30 -07:00
c74e40e69e [nix,flake] Moves some container files around. Also updates the flake lock. [synapse] Gets the federation working 2025-06-24 16:57:38 -07:00
514746686f [matrix] Moves secrets into sops 2025-06-24 14:29:08 -07:00
286701ba83 [blazestar.net] Sets up auto-deploy of an npm-based app. 2025-06-24 14:28:59 -07:00
1bfec397b5 [goatcounter] Adds back the rewrite for count.js 2025-06-22 10:37:49 -07:00
84d05be93b [goatcounter] Removes the special rewrite rules. Leaves them as comments for reference 2025-06-17 16:00:53 -07:00
03b3fe16b1 [goatcounter] Adds goatcounter.terakoda.com 2025-06-17 15:34:18 -07:00
cda32ea550 [dm-companion] Sets up auto-deploy and moves it to terakoda.com 2025-06-15 11:00:50 -07:00
32e10284d0 [desktop] Fixes XDG mime types for default browser 2025-06-11 15:16:46 -07:00
b9c439f5a9 [nvim] Some extra todo states 2025-06-11 15:12:28 -07:00
449662db8c [desktop] Adds gimp 2025-06-11 10:36:42 -07:00
6601377ece [terakoda.com] Moves www2 to the main site. 2025-06-09 16:04:11 -07:00
d432ef8014 [webhook] Switches match rule to just use an IP whitelist. 2025-06-09 16:04:11 -07:00
9acaae9277 [homemanager] Fixes env vars 2025-06-09 15:47:16 -07:00
f46c5948e5 [flake] Update 2025-06-09 10:15:09 -07:00
1d94f2574c [desktop] Set Librewolf as the default browser. 2025-06-08 20:57:13 -07:00
0a64c5cd4b [hypridle] Tweaks timings 2025-06-06 22:07:14 -07:00
2f44b67e9e [nvim] Remove augment plugin 2025-06-04 21:30:17 -07:00
f8378354fb [webhook] Adds webhook for redeploying npm projects 2025-06-04 17:35:31 -07:00
104cd2fd2e [arr] Adds bazarr. 2025-06-03 23:47:43 -07:00
075613c5a5 [ghost] Removes ghost demo. 2025-06-03 15:15:50 -07:00
dd8ec9035e [ghost] Adds ghost demo. 2025-06-03 15:15:28 -07:00
e5861f8e6b [dm-companion] Routes the API through the same host as the frontend 2025-06-03 15:15:28 -07:00
1ae798e30c [swaylock] Increase pixelation to 20 2025-05-30 16:31:16 -07:00
fec3b3a1e2 [oauth-proxy] Making some progress on this. It's not working, but it's now redirecting and getting 'invalid status code' 2025-05-30 10:25:00 -07:00
9411f87dbc [timetagger,traefik] Adds timetagger back, and attempts to put it behind an oauth proxy, but the traefik config isn't quite right. 2025-05-29 17:05:53 -07:00
07123a0fc2 [lock,idle] Fixes the swaylock script to work for multiple monitors and fixes it's invocation 2025-05-29 12:36:03 -07:00
5299c6d72c [shell] Adds mprocs 2025-05-29 10:26:58 -07:00
aa6402cf7c [idle;lock] Switches to swaylock 2025-05-28 12:23:14 -07:00
efab3866c2 [vega] Removes lock because it isn't working. [shell] Fixes aliases 2025-05-28 11:32:36 -07:00
b56d904c4e [vega] Switches back to stable. 2025-05-27 10:23:46 -07:00
fbf475f179 [nvim] Updates obsidian options: better file names 2025-05-27 10:23:10 -07:00
30ad37c30f [shell] Adds lots of little utilities 2025-05-26 20:37:34 -07:00
2253423fc4 [XCompose] Adds greek letters 2025-05-23 10:36:50 -07:00
bfa912f513 [vega] Attempting to fix some audio popping. 2025-05-22 17:36:12 -07:00
7e7ffa6fa7 [nvim,vscode] VSCode/Copilot config 2025-05-22 17:35:46 -07:00
447fe20041 [vega] Moves to unstable to fix issues building hy3 2025-05-21 15:47:13 -07:00
a219966688 [mcp] Updates to 25.05 and adds FreshRSS. Removes Focalboard and Bookstack 2025-05-20 20:21:51 -07:00
f2875caabb [Rofi] Fixes rendering and updates styles 2025-05-20 17:50:59 -07:00
d5bc7c3143 [Hypr] Sets up hypridle. [Nvim] Sets up nix formatting 2025-05-19 15:52:29 -07:00
a5ceae0912 [Rofi] Adds focus-holding in Hyprland 2025-05-19 12:04:34 -07:00
af07210253 [altair] Adds VSCode 2025-05-17 10:38:31 -07:00
f5fd69ab28 Adds more VScode extensions 2025-05-12 19:43:56 -07:00
8796f36a68 [docker] sets the docker socket variable 2025-05-12 17:27:09 -07:00
4caddc6959 [nvim] Re-enables Augment Code 2025-05-12 17:26:52 -07:00
9263d2752f [vscode] Sets up VScode with some extensions on Vega. 2025-05-12 17:26:31 -07:00
23d71b3a09 [nix] Allow unfree for shells. [docker] Correctly export DOCKER_HOST. [nvim] Disable augment and turn on vtsls 2025-05-11 11:21:36 -07:00
945d3aa002 [nvim] Adds augment plugin. 2025-05-10 10:38:25 -07:00
f76969136e [nvim] Maybe finally fixes snacks smart picker 2025-05-09 18:20:44 -07:00
4dc66c25f6 [vega] Adds Zoom app 2025-05-09 18:20:29 -07:00
5e2c997cdc [linux-desktop] Adds a few more apps and reorganizes the config 2025-05-09 18:20:14 -07:00
b1ae2d56fb [markdown] Adds marksman languages server and telescope picker for obsidian 2025-05-09 11:02:11 -07:00
d814aa9465 [shell] Add dysk as alternative to df 2025-05-09 10:31:37 -07:00
bedce7a93c [neovim] Snacks smart-picker config 2025-05-09 10:31:27 -07:00
e2e32fb6cd [hyprland] Re-configure swayidle as a service 2025-05-09 10:31:00 -07:00
aa2cec9f70 [nvim] Improves markdown checkbox experience 2025-05-06 11:25:28 -07:00
2c3ab47daa [vega] Adds slack for business communication 2025-05-05 16:22:05 -07:00
4c9d2e90c3 [neovim] Sets up surround, emoji auto-complete, indentation 2025-05-05 14:29:29 -07:00
8d4febc16f [hyprland] Adds some gaming window rules 2025-05-05 13:14:11 -07:00
69bfb463fe [hyprland] Run eww only once. 2025-05-05 13:07:21 -07:00
73f2bcb362 [Altair] Switches to unstable 2025-05-05 13:05:23 -07:00
0914c02547 [nix] Cleans up warnings about options and reduces duplication 2025-05-05 10:33:00 -07:00
29317386a9 [gaming] Adds protonplus 2025-05-03 16:52:27 -07:00
177e91c658 [hyprland] Moves env to uswm/env as recommended in whe wiki 2025-05-03 16:52:27 -07:00
2643d3801f [development] More TS dev fixes, adds direnv. Fixes some markdown rendering. 2025-05-01 12:19:54 -07:00
8884bd51fd [container-dev] Switch to rootless docker. [nvim] Update snacks options. [hyprland] Use clipboard fixes globally 2025-04-30 14:29:31 -07:00
55bd116fde [wayland] Adds clipboard fix for wine 2025-04-30 10:42:39 -07:00
99da063b14 [eww] Fixes some errors due to missing functions or null values 2025-04-29 17:31:12 -07:00
0a7e176c1e [dev] Sets up podman as a system package instead of homemanager. 2025-04-29 17:31:12 -07:00
db8d2a3a23 [eww] Show only root partition on vega 2025-04-29 17:31:12 -07:00
828750087d [eww] Fixes networking. [swayosd] Removes instances started by hyprland 2025-04-29 17:31:12 -07:00
1153e9086a [eww] Fixes some stuff with the vertical statusbar 2025-04-29 17:31:12 -07:00
e405610baf [mcp] Adds back the user changes I accidentally clobbered. 2025-04-29 13:10:38 -07:00
35a3ec8f7c [vega] Enables running app-images as binaries 2025-04-29 11:45:52 -07:00
39b2c4301c [mcp] Some user setup on the way to automated deployments 2025-04-28 19:31:55 -07:00
3da928a7a8 [mcp] Adds gitea runners 2025-04-28 19:30:27 -07:00
6fd171ae12 [development] Adds more development utils. 2025-04-28 19:28:55 -07:00
58665f6fcb [nvim] Change suggestion keymaps: C-space to suggest, C-enter to accept. 2025-04-27 10:06:40 -07:00
a912dc5b54 [nvim] Cleans up plugins, adds transparency. 2025-04-26 09:40:19 -07:00
36e847d35a [hyprlock] Adds hyprlock config 2025-04-25 15:32:41 -07:00
28e9c221ad [nix] Adds GC 2025-04-25 15:24:33 -07:00
59ae2bd981 [vega;hyprland] Set up only one-monitor workspaces 2025-04-25 15:18:58 -07:00
5b8cc6eb8d [eww] Filters out empty workspaces, again. 2025-04-25 15:16:45 -07:00
8da2bc8cfe [Offen] Sets up offen. 2025-04-25 15:13:40 -07:00
83ca3abf20 [podman] Remove hostname option so that DNS resolves correctly. 2025-04-25 15:13:40 -07:00
4105a6ff38 [gaming] Adds raider.io client 2025-04-24 22:51:27 -07:00
a2f9956824 [vega] Update config; make gui config generic. [nvim] Use Snacks smart finder instead of fzf and avoid race condition 2025-04-24 13:54:05 -07:00
3198414be4 [wpaperd] Update deprecated settings 2025-04-24 11:29:27 -07:00
3a20c72206 [Term] Switches to foot as a terminal 2025-04-24 11:25:43 -07:00
771c3618bc [hyprland] Uses mainline packages, updates config as necessary 2025-04-24 10:57:50 -07:00
5645867776 [hyprland] Adds window resizing 2025-04-24 10:15:42 -07:00
7761067283 [gaming] Adds warcraft logs app. 2025-04-24 10:15:42 -07:00
0367ecd919 [blazestar.net;havenisms.com] Moves them to the new static-site setup 2025-04-23 17:09:05 -07:00
4a49cd3dfe [terakoda.com] Adds page 2025-04-23 17:09:05 -07:00
f59ed4e280 [git] Set default branch to main 2025-04-23 15:58:39 -07:00
e3a0548ca4 [wpaperd] Adds wallpaper rotation 2025-04-23 15:57:59 -07:00
53e29f3911 [eww] Adds workspaces to the vertical statusbar for vega. 2025-04-22 16:19:20 -07:00
c88845ea2a [Focalboard] Sets up Focalboard with storage, database and secrets. [OpenProject] Removes the container 2025-04-21 16:45:27 -07:00
089541916a [vega] Downgrade to 24.11. Switch to mkNixos. 2025-04-21 11:56:55 -07:00
0dbcb541b3 [eww] Remove uninstalled steam game. [nix] adds some comments. 2025-04-20 17:11:44 -07:00
c2a5e0a709 [nix] Messing around with how to override desktop files 2025-04-17 20:03:18 -07:00
828aaa5d40 [gaming] Add launch options for wowup 2025-04-17 13:02:23 -07:00
1afddefdbf [sway] Adds sway as an option, with minimal config 2025-04-17 13:02:23 -07:00
8533f0c9cc [sway] Switches to sway over hyprland 2025-04-17 13:02:23 -07:00
b2b99f12cc [flake] Move MCP back to 24.11 for stability. Probably move the rest soon too. 2025-04-10 16:11:52 -07:00
b0852ad15a [discord] Fix some ozone/wayland stuff 2025-04-09 18:03:02 -07:00
0b013f215e [email] Removes email server. 2025-04-08 16:34:41 -07:00
a468e87d49 [email] WIP 2025-04-08 16:32:19 -07:00
122 changed files with 3842 additions and 2503 deletions

516
flake.lock generated
View File

@@ -1,76 +1,5 @@
{
"nodes": {
"aquamarine": {
"inputs": {
"hyprutils": [
"hyprland",
"hyprutils"
],
"hyprwayland-scanner": [
"hyprland",
"hyprwayland-scanner"
],
"nixpkgs": [
"hyprland",
"nixpkgs"
],
"systems": [
"hyprland",
"systems"
]
},
"locked": {
"lastModified": 1743265529,
"narHash": "sha256-QbjP15/2N+VJl0b5jxrrTc+VOt39aU4XrDvtP0Lz5ik=",
"owner": "hyprwm",
"repo": "aquamarine",
"rev": "1d2dbd72c2bbaceab031c592d4810f744741d203",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "aquamarine",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"hyprland",
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
@@ -78,385 +7,41 @@
]
},
"locked": {
"lastModified": 1743788974,
"narHash": "sha256-2LeVyQZI2wTkSzMLvnN/kJjXVWp4HCVUoq17Bv8TNTk=",
"lastModified": 1767910483,
"narHash": "sha256-MOU5YdVu4DVwuT5ztXgQpPuRRBjSjUGIdUzOQr9iQOY=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "0f5908daf890c3d7e7052bef1d6deb0f2710aaa1",
"rev": "82fb7dedaad83e5e279127a38ef410bcfac6d77c",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "master",
"ref": "release-25.11",
"repo": "home-manager",
"type": "github"
}
},
"hy3": {
"inputs": {
"hyprland": [
"hyprland"
]
},
"locked": {
"lastModified": 1743128724,
"narHash": "sha256-CUlxc2u1Y8gpeAl7NKrZxxpeZjyU2DBxOYb8b0haM2M=",
"owner": "outfoxxed",
"repo": "hy3",
"rev": "4014433d1c3d1bf36c6684cff14c23d538337070",
"type": "github"
},
"original": {
"owner": "outfoxxed",
"repo": "hy3",
"type": "github"
}
},
"hyprcursor": {
"inputs": {
"hyprlang": [
"hyprland",
"hyprlang"
],
"nixpkgs": [
"hyprland",
"nixpkgs"
],
"systems": [
"hyprland",
"systems"
]
},
"locked": {
"lastModified": 1742215578,
"narHash": "sha256-zfs71PXVVPEe56WEyNi2TJQPs0wabU4WAlq0XV7GcdE=",
"owner": "hyprwm",
"repo": "hyprcursor",
"rev": "2fd36421c21aa87e2fe3bee11067540ae612f719",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprcursor",
"type": "github"
}
},
"hyprgraphics": {
"inputs": {
"hyprutils": [
"hyprland",
"hyprutils"
],
"nixpkgs": [
"hyprland",
"nixpkgs"
],
"systems": [
"hyprland",
"systems"
]
},
"locked": {
"lastModified": 1739049071,
"narHash": "sha256-3+7TpXMrbsUXSwgr5VAKAnmkzMb6JO+Rvc9XRb5NMg4=",
"owner": "hyprwm",
"repo": "hyprgraphics",
"rev": "175c6b29b6ff82100539e7c4363a35a02c74dd73",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprgraphics",
"type": "github"
}
},
"hyprland": {
"inputs": {
"aquamarine": "aquamarine",
"hyprcursor": "hyprcursor",
"hyprgraphics": "hyprgraphics",
"hyprland-protocols": "hyprland-protocols",
"hyprland-qtutils": "hyprland-qtutils",
"hyprlang": "hyprlang",
"hyprutils": "hyprutils",
"hyprwayland-scanner": "hyprwayland-scanner",
"nixpkgs": [
"nixpkgs"
],
"pre-commit-hooks": "pre-commit-hooks",
"systems": "systems",
"xdph": "xdph"
},
"locked": {
"lastModified": 1743809433,
"narHash": "sha256-tCOlE2zMXfd+KNG5ETr2VxhbniDMD7jBbD0JQhYBrlc=",
"owner": "hyprwm",
"repo": "Hyprland",
"rev": "8ba20fcae124591718bddadd94c5e8c381d02097",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "Hyprland",
"type": "github"
}
},
"hyprland-protocols": {
"inputs": {
"nixpkgs": [
"hyprland",
"nixpkgs"
],
"systems": [
"hyprland",
"systems"
]
},
"locked": {
"lastModified": 1743549251,
"narHash": "sha256-yf+AXt0RkAkCyF6iSnJt6EJAnNG/l6qv70CVzhRP6Bg=",
"owner": "hyprwm",
"repo": "hyprland-protocols",
"rev": "4ab17ccac08456cb5e00e8bd323de2efd30612be",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprland-protocols",
"type": "github"
}
},
"hyprland-qt-support": {
"inputs": {
"hyprlang": [
"hyprland",
"hyprland-qtutils",
"hyprlang"
],
"nixpkgs": [
"hyprland",
"hyprland-qtutils",
"nixpkgs"
],
"systems": [
"hyprland",
"hyprland-qtutils",
"systems"
]
},
"locked": {
"lastModified": 1737634706,
"narHash": "sha256-nGCibkfsXz7ARx5R+SnisRtMq21IQIhazp6viBU8I/A=",
"owner": "hyprwm",
"repo": "hyprland-qt-support",
"rev": "8810df502cdee755993cb803eba7b23f189db795",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprland-qt-support",
"type": "github"
}
},
"hyprland-qtutils": {
"inputs": {
"hyprland-qt-support": "hyprland-qt-support",
"hyprlang": [
"hyprland",
"hyprlang"
],
"hyprutils": [
"hyprland",
"hyprland-qtutils",
"hyprlang",
"hyprutils"
],
"nixpkgs": [
"hyprland",
"nixpkgs"
],
"systems": [
"hyprland",
"systems"
]
},
"locked": {
"lastModified": 1739048983,
"narHash": "sha256-REhTcXq4qs3B3cCDtLlYDz0GZvmsBSh947Ub6pQWGTQ=",
"owner": "hyprwm",
"repo": "hyprland-qtutils",
"rev": "3504a293c8f8db4127cb0f7cfc1a318ffb4316f8",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprland-qtutils",
"type": "github"
}
},
"hyprlang": {
"inputs": {
"hyprutils": [
"hyprland",
"hyprutils"
],
"nixpkgs": [
"hyprland",
"nixpkgs"
],
"systems": [
"hyprland",
"systems"
]
},
"locked": {
"lastModified": 1741191527,
"narHash": "sha256-kM+11Nch47Xwfgtw2EpRitJuORy4miwoMuRi5tyMBDY=",
"owner": "hyprwm",
"repo": "hyprlang",
"rev": "72df3861f1197e41b078faa3e38eedd60e00018d",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprlang",
"type": "github"
}
},
"hyprutils": {
"inputs": {
"nixpkgs": [
"hyprland",
"nixpkgs"
],
"systems": [
"hyprland",
"systems"
]
},
"locked": {
"lastModified": 1742984269,
"narHash": "sha256-uz9FaCIbga/gQ5ZG1Hb4HVVjTWT1qjjCAFlCXiaefxg=",
"owner": "hyprwm",
"repo": "hyprutils",
"rev": "7248194a2ce0106ae647b70d0526a96dc9d6ad60",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprutils",
"type": "github"
}
},
"hyprwayland-scanner": {
"inputs": {
"nixpkgs": [
"hyprland",
"nixpkgs"
],
"systems": [
"hyprland",
"systems"
]
},
"locked": {
"lastModified": 1739870480,
"narHash": "sha256-SiDN5BGxa/1hAsqhgJsS03C3t2QrLgBT8u+ENJ0Qzwc=",
"owner": "hyprwm",
"repo": "hyprwayland-scanner",
"rev": "206367a08dc5ac4ba7ad31bdca391d098082e64b",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprwayland-scanner",
"type": "github"
}
},
"nix-darwin": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1743496612,
"narHash": "sha256-emPWa5lmKbnyuj8c1mSJUkzJNT+iJoU9GMcXwjp2oVM=",
"owner": "LnL7",
"repo": "nix-darwin",
"rev": "73d59580d01e9b9f957ba749f336a272869c42dd",
"type": "github"
},
"original": {
"owner": "LnL7",
"ref": "master",
"repo": "nix-darwin",
"type": "github"
}
},
"nix-filter": {
"locked": {
"lastModified": 1693833173,
"narHash": "sha256-hlMABKrGbEiJD5dwUSfnw1CQ3bG7KKwDV+Nx3bEZd7U=",
"owner": "numtide",
"repo": "nix-filter",
"rev": "ac030bd9ba98e318e1f4c4328d60766ade8ebe8b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "nix-filter",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1743583204,
"narHash": "sha256-F7n4+KOIfWrwoQjXrL2wD9RhFYLs2/GGe/MQY1sSdlE=",
"lastModified": 1767799921,
"narHash": "sha256-r4GVX+FToWVE2My8VVZH4V0pTIpnu2ZE8/Z4uxGEMBE=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "2c8d3f48d33929642c1c12cd243df4cc7d2ce434",
"rev": "d351d0653aeb7877273920cd3e823994e7579b0b",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"hyprland",
"nixpkgs"
]
},
"locked": {
"lastModified": 1742649964,
"narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"home-manager": "home-manager",
"hy3": "hy3",
"hyprland": "hyprland",
"nix-darwin": "nix-darwin",
"nixpkgs": "nixpkgs",
"sops-nix": "sops-nix",
"split-monitor-workspaces": "split-monitor-workspaces"
"sops-nix": "sops-nix"
}
},
"sops-nix": {
@@ -466,11 +51,11 @@
]
},
"locked": {
"lastModified": 1743756170,
"narHash": "sha256-2b11EYa08oqDmF3zEBLkG1AoNn9rB1k39ew/T/mSvbU=",
"lastModified": 1767826491,
"narHash": "sha256-WSBENPotD2MIhZwolL6GC9npqgaS5fkM7j07V2i/Ur8=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "cff8437c5fe8c68fc3a840a21bf1f4dc801da40d",
"rev": "ea3adcb6d2a000d9a69d0e23cad1f2cacb3a9fbe",
"type": "github"
},
"original": {
@@ -478,83 +63,6 @@
"repo": "sops-nix",
"type": "github"
}
},
"split-monitor-workspaces": {
"inputs": {
"hyprland": [
"hyprland"
],
"nix-filter": "nix-filter"
},
"locked": {
"lastModified": 1743247927,
"narHash": "sha256-za6nKSilGOUpTDLho1LK8elyImLNNIUGixDLW/n6f84=",
"owner": "Duckonaut",
"repo": "split-monitor-workspaces",
"rev": "a8e39ff10dfb5ff451416a791a30388a8517e038",
"type": "github"
},
"original": {
"owner": "Duckonaut",
"repo": "split-monitor-workspaces",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1689347949,
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
"owner": "nix-systems",
"repo": "default-linux",
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default-linux",
"type": "github"
}
},
"xdph": {
"inputs": {
"hyprland-protocols": [
"hyprland",
"hyprland-protocols"
],
"hyprlang": [
"hyprland",
"hyprlang"
],
"hyprutils": [
"hyprland",
"hyprutils"
],
"hyprwayland-scanner": [
"hyprland",
"hyprwayland-scanner"
],
"nixpkgs": [
"hyprland",
"nixpkgs"
],
"systems": [
"hyprland",
"systems"
]
},
"locked": {
"lastModified": 1741934139,
"narHash": "sha256-ZhTcTH9FoeAtbPfWGrhkH7RjLJZ7GeF18nygLAMR+WE=",
"owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland",
"rev": "150b0b6f52bb422a1b232a53698606fe0320dde0",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland",
"type": "github"
}
}
},
"root": "root",

View File

@@ -2,27 +2,9 @@
description = "System Configuration";
inputs = {
nixpkgs = {
url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-25.11";
home-manager = {
url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs";
};
hyprland = {
url = "github:hyprwm/Hyprland";
inputs.nixpkgs.follows = "nixpkgs";
};
hy3 = {
url = "github:outfoxxed/hy3";
inputs.hyprland.follows = "hyprland";
};
split-monitor-workspaces = {
url = "github:Duckonaut/split-monitor-workspaces";
inputs.hyprland.follows = "hyprland";
};
nix-darwin = {
url = "github:LnL7/nix-darwin/master";
url = "github:nix-community/home-manager?ref=release-25.11";
inputs.nixpkgs.follows = "nixpkgs";
};
sops-nix = {
@@ -32,31 +14,54 @@
};
outputs =
{ self, nixpkgs, ... }@inputs:
{
nixosConfigurations = {
altair = (import ./system/hosts/altair) {
inherit inputs;
inherit self;
inherit nixpkgs;
};
mcp = (import ./system/hosts/mcp) {
inherit inputs;
inherit self;
inherit nixpkgs;
};
vega = (import ./system/hosts/vega) {
inherit inputs;
inherit self;
inherit nixpkgs;
};
};
darwinConfigurations = {
# Removed. See 133a3f82073f03e62cb3e7902c85fb3fc6292fe2 for when the
# last one was removed.
};
features = {
development = (import ./home-manager/features/development/development.nix);
self,
nixpkgs,
...
}@inputs:
let
local = import ./lib;
mkNixosConfig =
{
path,
system ? "x86_64-linux",
nixpkgs ? inputs.nixpkgs,
home-manager ? inputs.home-manager,
}:
nixpkgs.lib.nixosSystem {
inherit system;
modules = [
home-manager.nixosModules.home-manager
{
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = {
inherit inputs local;
};
};
}
path
];
specialArgs = {
inherit inputs local;
};
};
in
{
nixosConfigurations = {
altair = mkNixosConfig {
path = ./system/hosts/altair;
};
vega = mkNixosConfig {
path = ./system/hosts/vega;
};
mcp = mkNixosConfig {
path = ./system/hosts/mcp;
};
};
features = {
development = import ./home-manager/features/development/development.nix;
};
};
}

View File

@@ -0,0 +1,18 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
discord
];
xdg.desktopEntries = {
discord = {
name = "Discord";
# Custom options to reduce flickering under wayland.
exec = "env ELECTRON_OZONE_PLATFORM_HINT= discord --enable-features=UseOzonePlatform --ozone-platform=wayland --disable-gpu";
};
};
wayland.windowManager.hyprland.settings.bind = [
# Pass Mouse4 through to discord
# ", mouse:275, pass, class:^discord$"
];
}

View File

@@ -0,0 +1,64 @@
{
pkgs,
...
}:
let
freecad-wrapped = pkgs.symlinkJoin {
name = "freecad-wrapped";
paths = [ pkgs.freecad ];
buildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram $out/bin/freecad \
--prefix MESA_LOADER_DRIVER_OVERRIDE : zink \
--prefix __EGL_VENDOR_LIBRARY_FILENAMES : ${pkgs.mesa}/share/glvnd/egl_vendor.d/50_mesa.json
'';
};
bambu-studio-wrapped = pkgs.symlinkJoin {
name = "bambu-studio-wrapped";
paths = [ pkgs.bambu-studio ];
buildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram $out/bin/bambu-studio \
--prefix MESA_LOADER_DRIVER_OVERRIDE : zink \
--prefix __EGL_VENDOR_LIBRARY_FILENAMES : ${pkgs.mesa}/share/glvnd/egl_vendor.d/50_mesa.json
'';
};
in
{
home.packages = with pkgs; [
bambu-studio-wrapped
LycheeSlicer
orca-slicer
blender
freecad-wrapped
openscad
];
xdg.desktopEntries.orynt3d =
let
orynt3d-appimage = pkgs.fetchurl {
name = "orynt3d-appimage";
url = "https://files.orynt3d.com/client/Orynt3D-0.15.3.AppImage";
sha256 = "0j10myj06ff4frsd4yv7z3lb3qgw3ha70hc5hdc9idbryica801y";
};
in
{
name = "Orynt3D";
exec = "env __EGL_VENDOR_LIBRARY_FILENAMES=/run/opengl-driver/share/glvnd/egl_vendor.d/10_nvidia.json ${pkgs.appimage-run}/bin/appimage-run ${orynt3d-appimage}";
terminal = false;
type = "Application";
# icon = "";
comment = "3D model viewer and organizer";
categories = [
"Science"
"Development"
];
};
# Options to get Bambu Studio to run:
# __GLX_VENDOR_LIBRARY_NAME=mesa __EGL_VENDOR_LIBRARY_FILENAMES=/nix/store/js9cfbjvlsls14nddk39fw74vyvlhz4l-mesa-25.0.7/share/glvnd/egl_vendor.d/50_mesa.json MESA_LOADER_DRIVER_OVERRIDE=zink GALLIUM_DRIVER=zink WEBKIT_DISABLE_DMABUF_RENDERER=1 bambu-studio
}

View File

@@ -0,0 +1,8 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
stellarium
kstars
celestia
];
}

View File

@@ -1,7 +1,41 @@
{ pkgs, ... }:
with pkgs;
let
# A script that runs as long as media is playing.
isMediaPlaying = writeShellApplication {
name = "isMediaPlaying";
runtimeInputs = [
playerctl
];
text = ''
set -e
while [ "$(playerctl status)" = "Playing" ]; do
echo -n "."
sleep 1
done
'';
};
# A script that prevents the system from going to sleep while media is playing
mediaCaffeine = writeShellApplication {
name = "media-caffeine";
runtimeInputs = [
isMediaPlaying
systemd
];
text = ''
set -e
systemd-inhibit --what=sleep --why="Media is playing" --mode=block isMediaPlaying
'';
};
in
{
home.packages = with pkgs; [
pulseaudio # for pactl and other tools
pavucontrol # GUI volume control with lots of options
mediaCaffeine
];
}

View File

@@ -0,0 +1,11 @@
{ pkgs, ... }:
{
imports = [
../apps/element.nix
../apps/discord.nix
];
home.packages = with pkgs; [
signal-desktop
];
}

View File

@@ -1,7 +1,64 @@
include "%L"
<Multi_key> <m> <u> : "μ"
<Multi_key> <p> <i> : "π"
<Multi_key> <minus> <comma> : "¬"
<Multi_key> <asciicircum> <asciicircum> : "∧"
<Multi_key> <v> <v> : ""
# GREEK CAPITAL LETTERS
<Multi_key> <G> <A> : "Α" U0391 # GREEK CAPITAL LETTER ALPHA
<Multi_key> <G> <B> : "Β" U0392 # GREEK CAPITAL LETTER BETA
<Multi_key> <G> <G> : "Γ" U0393 # GREEK CAPITAL LETTER GAMMA
<Multi_key> <G> <D> : "Δ" U0394 # GREEK CAPITAL LETTER DELTA
<Multi_key> <G> <E> : "Ε" U0395 # GREEK CAPITAL LETTER EPSILON
<Multi_key> <G> <Z> : "Ζ" U0396 # GREEK CAPITAL LETTER ZETA
<Multi_key> <G> <H> : "Η" U0397 # GREEK CAPITAL LETTER ETA
<Multi_key> <G> <I> : "Ι" U0399 # GREEK CAPITAL LETTER IOTA
<Multi_key> <G> <K> : "Κ" U039A # GREEK CAPITAL LETTER KAPPA
<Multi_key> <G> <L> : "Λ" U039B # GREEK CAPITAL LETTER LAMDA
<Multi_key> <G> <M> : "Μ" U039C # GREEK CAPITAL LETTER MU
<Multi_key> <G> <N> : "Ν" U039D # GREEK CAPITAL LETTER NU
<Multi_key> <G> <P> : "Π" U03A0 # GREEK CAPITAL LETTER PI
<Multi_key> <G> <R> : "Ρ" U03A1 # GREEK CAPITAL LETTER RHO
<Multi_key> <G> <S> : "Σ" U03A3 # GREEK CAPITAL LETTER SIGMA
<Multi_key> <G> <T> : "Τ" U03A4 # GREEK CAPITAL LETTER TAU
<Multi_key> <G> <U> : "Υ" U03A5 # GREEK CAPITAL LETTER UPSILON
<Multi_key> <G> <F> : "Φ" U03A6 # GREEK CAPITAL LETTER PHI
<Multi_key> <G> <X> : "Χ" U03A7 # GREEK CAPITAL LETTER CHI
<Multi_key> <G> <O> : "Ω" U03A9 # GREEK CAPITAL LETTER OMEGA
# DOUBLES (additional stroke <Q>)
<Multi_key> <G> <Q> <T> : "Θ" U0398 # GREEK CAPITAL LETTER THETA
<Multi_key> <G> <Q> <O> : "Ο" U039F # GREEK CAPITAL LETTER OMICRON
<Multi_key> <G> <Q> <X> : "Ξ" U039E # GREEK CAPITAL LETTER XI
<Multi_key> <G> <Q> <P> : "Ψ" U03A8 # GREEK CAPITAL LETTER PSI
# greek small letters
<Multi_key> <g> <a> : "α" U03B1 # GREEK SMALL LETTER ALPHA
<Multi_key> <g> <b> : "β" U03B2 # GREEK SMALL LETTER BETA
<Multi_key> <g> <g> : "γ" U03B3 # GREEK SMALL LETTER GAMMA
<Multi_key> <g> <d> : "δ" U03B4 # GREEK SMALL LETTER DELTA
<Multi_key> <g> <e> : "ε" U03B5 # GREEK SMALL LETTER EPSILON
<Multi_key> <g> <z> : "ζ" U03B6 # GREEK SMALL LETTER ZETA
<Multi_key> <g> <h> : "η" U03B7 # GREEK SMALL LETTER ETA
<Multi_key> <g> <i> : "ι" U03B9 # GREEK SMALL LETTER IOTA
<Multi_key> <g> <k> : "κ" U03BA # GREEK SMALL LETTER KAPPA
<Multi_key> <g> <l> : "λ" U03BB # GREEK SMALL LETTER LAMDA
<Multi_key> <g> <m> : "μ" U03BC # GREEK SMALL LETTER MU
<Multi_key> <g> <n> : "ν" U03BD # GREEK SMALL LETTER NU
<Multi_key> <g> <p> : "π" U03C0 # GREEK SMALL LETTER PI
<Multi_key> <g> <r> : "ρ" U03C1 # GREEK SMALL LETTER RHO
<Multi_key> <g> <s> : "σ" U03C3 # GREEK SMALL LETTER SIGMA
<Multi_key> <g> <t> : "τ" U03C4 # GREEK SMALL LETTER TAU
<Multi_key> <g> <u> : "υ" U03C5 # GREEK SMALL LETTER UPSILON
<Multi_key> <g> <f> : "φ" U03C6 # GREEK SMALL LETTER PHI
<Multi_key> <g> <x> : "χ" U03C7 # GREEK SMALL LETTER CHI
<Multi_key> <g> <o> : "ω" U03C9 # GREEK SMALL LETTER OMEGA
# doubles (additional stroke <q>)
<Multi_key> <g> <q> <t> : "θ" U03B8 # GREEK SMALL LETTER THETA
<Multi_key> <g> <q> <o> : "ο" U03BF # GREEK SMALL LETTER OMICRON
<Multi_key> <g> <q> <p> : "ψ" U03C8 # GREEK SMALL LETTER PSI
<Multi_key> <g> <q> <s> : "ς" U03C2 # GREEK SMALL LETTER FINAL SIGMA
<Multi_key> <g> <q> <x> : "ξ" U03BE # GREEK SMALL LETTER X

View File

@@ -10,10 +10,17 @@
# Base languages that should always be available
./nix.nix
./lua.nix
./sh.nix
];
home.packages = with pkgs; [
# Dev helpers
direnv
hyperfine # Benchmarking tool
];
programs.direnv = {
enable = true;
enableBashIntegration = true;
enableZshIntegration = true;
nix-direnv.enable = true;
};
}

View File

@@ -0,0 +1,6 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
docker-compose
];
}

View File

@@ -0,0 +1,7 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
markdownlint-cli2 # linter
marksman # language server
];
}

View File

@@ -6,6 +6,7 @@
nixfmt-rfc-style # Formatter
nil # Language Server
statix # Lints and suggestions for Nix
];
home.shellAliases = {
@@ -14,4 +15,3 @@
rebuild-boot = "sudo nixos-rebuild boot --flake ~/system-config --show-trace --print-build-logs --verbose";
};
}

View File

@@ -0,0 +1,6 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
shfmt # Formatter
];
}

View File

@@ -0,0 +1,9 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
vtsls # Language Server
eslint # Linter
nodePackages.prettier # Formatter
tailwindcss-language-server # Language server for tailwind CSS
];
}

View File

@@ -0,0 +1,20 @@
{ pkgs, ... }:
{
programs.vscode = {
enable = true;
extensions = with pkgs.vscode-extensions; [
asvetliakov.vscode-neovim # Use embedded neovim editor
enkia.tokyo-night # Color theme
eamodio.gitlens # Show git info inline
mechatroner.rainbow-csv # Make it easier to read CSV files
aaron-bond.better-comments # Provides some highlighting in comments
# Typescript
esbenp.prettier-vscode # Auto-formatting
# AI Agents
github.copilot
];
};
}

View File

@@ -33,6 +33,16 @@ $color-standout-dark: darker($color-standout);
font-family: 'Noto Sans Nerd Font', sans-serif;
}
window.vertical-statusbar {
background-color: $color-background;
// background-image: linear-gradient(160deg, rgba(255,00,00,0.5), $color-background);
color: $color-foreground;
padding: 16px;
font-size: 14px;
border-right: 3px solid $color-border;
font-family: 'Noto Sans Nerd Font', sans-serif;
}
.system-monitor {
padding-top: 8px;
padding-right: 8px;

View File

@@ -3,5 +3,4 @@
(include "./primary-statusbar.yuck")
(include "./secondary-statusbar.yuck")
(include "./system-monitor.yuck")
(include "./launcher.yuck")
(include "./vertical-statusbar.yuck")

View File

@@ -1,82 +0,0 @@
(defwindow launcher
:monitor '[ "<primary>", "DP-2", 0 ]'
:geometry (geometry
:x "100px"
:y "100px"
:anchor "top left"
)
:stacking "bottom"
:exclusive false
:focusable false
(box
:class "launcher-window stand-alone"
:orientation "v"
:spacing 4
:visible { arraylength(jq(workspaces-json-dp2, "map(select(.active and (.has_windows | not)))")) > 0 }
(box
:orientation "v"
:halign "start"
:spacing 4
:space-evenly false
(label
:text "Apps"
:halign "start"
)
(box
:orientation "h"
:halign "start"
:spacing 4
:space-evenly false
(button
:onclick "firefox"
(image
:class "launcher-icon"
:icon "firefox"
:icon-size "dialog"
)
)
)
)
(box
:orientation "v"
:halign "start"
:spacing 4
:space-evenly false
(label
:text "Games"
:halign "start"
)
(box
:orientation "h"
:halign "start"
:spacing 4
:space-evenly false
(button
;; :onclick "env LUTRIS_SKIP_INIT=1 lutris lutris:rungameid/1"
:onclick "/home/drew/.local/bin/wow.sh >/tmp/wow.log 2>&1"
(image
:class "launcher-icon"
:image-width 48
:path "/home/drew/.local/share/icons/hicolor/128x128/apps/lutris_battlenet.png"
)
)
(button
:onclick "steam steam://rungameid/1091500"
(image
:class "launcher-icon"
:icon "steam_icon_1091500"
:icon-size "dialog"
)
)
;; (button
;; :onclick "steam steam://rungameid/1145350"
;; (image
;; :class "launcher-icon"
;; :icon "steam_icon_1145350"
;; :icon-size "dialog"
;; )
;;)
)
)
)
)

View File

@@ -30,7 +30,7 @@
)
(defwindow primary-statusbar
:monitor '[ "<primary>", "DP-2", 0 ]'
:monitor '[ "<primary>", "DP-2", 1 ]'
:geometry (geometry
:x "0%"
:y "0%"

View File

@@ -47,7 +47,7 @@
)
(defwindow secondary-statusbar
:monitor '[ "<secondary>", "DP-1" ]'
:monitor '[ "<secondary>", "DP-1", "0" ]'
:geometry (geometry
:x "0px"
:y "0px"

View File

@@ -30,7 +30,7 @@
:spacing 8
(system-monitor-perf)
(system-monitor-disks)
(system-monitor-net)
(system-monitor-net :interface "wlo1")
)
(box
:orientation "h"
@@ -145,13 +145,13 @@
:name "Disks"
(system-monitor-gauge
:name "Root"
:text-value {EWW_DISK['/'].free / powi(2, 30)}
:text-value {EWW_DISK['/'].free / 1000000000}
:gauge-pct {EWW_DISK['/'].used_perc}
:units " GB"
)
(system-monitor-gauge
:name "Home"
:text-value {EWW_DISK['/home'].free / powi(2, 30)}
:text-value {EWW_DISK['/home'].free / 1000000000}
:gauge-pct {EWW_DISK['/home'].used_perc}
:units " GB"
)
@@ -164,7 +164,7 @@
`iwgetid -r`
)
(defwidget system-monitor-net []
(defwidget system-monitor-net [ interface ]
(system-monitor-group
:name "Network"
:orientation "v"
@@ -174,12 +174,12 @@
)
(system-monitor-sparkgraph
:name "Down"
:value {EWW_NET["wlo1"]["NET_DOWN"] / 1000000}
:value {EWW_NET[interface]["NET_DOWN"] / 1000000}
:units " MB/s"
)
(system-monitor-sparkgraph
:name "Up"
:value {EWW_NET["wlo1"]["NET_UP"] / 1000000}
:value {EWW_NET[interface]["NET_UP"] / 1000000}
:units " MB/s"
)
)

View File

@@ -8,14 +8,35 @@
)
)
(deflisten workspaces-json-hdmi-a-1
:initial "[]"
`~/.config/eww/scripts/workspaces.sh HDMI-A-1`
)
(defwidget workspaces-vega []
(workspaces :workspaces-json workspaces-json-hdmi-a-1)
)
(defwidget disks-vega []
(system-monitor-group
:name "Disks"
(system-monitor-gauge
:name "Root"
:text-value {EWW_DISK['/'].free / 1000000000}
:gauge-pct {EWW_DISK['/'].used_perc}
:units " GB"
)
)
)
(defwidget vertical-statusbar []
(box
:class "statusbar"
:orientation "v"
:halign "center"
:halign "fill"
:spacing 8
:space-evenly false
(clock-large)
(workspaces-vega)
(vertical-statusbar-systray)
(system-monitor-group
:name "Performance"
@@ -23,8 +44,8 @@
(system-monitor-perf-cpu)
(system-monitor-perf-gpu)
)
(system-monitor-disks)
(system-monitor-net)
(disks-vega)
(system-monitor-net :interface "wlp5s0")
(system-monitor-audio)
)
)

View File

@@ -1,5 +1,13 @@
{ ... }:
{ pkgs, ... }:
{
home.packages = with pkgs; [
# For Noto Sans NF
# 25.05
nerd-fonts.noto
# 24.11
# (nerdfonts.override { fonts = [ "NotoSans" ]; })
];
programs.eww = {
enable = true;
configDir = ./config;

View File

@@ -1,4 +1,40 @@
{ pkgs, ... }:
{ pkgs, local, ... }:
let
# TODO: This is an attempt to patch the desktop file by actually using the old
# one so I don't have to put in all the options like below. This will generate
# the correct file, however, xdg.dataFile."applications/wowup-cf.desktop"
# doesn't seem to actually overrwite it, even with force = true.
# patched-desktop =
# pkgs.runCommand "patched-wowup-cf-desktop"
# {
# desktop = "${pkgs.wowup-cf}/share/applications/wowup-cf.desktop";
# }
# ''
# mkdir -p $out
# substitute "$desktop" "$out/wowup-cf.desktop" \
# --replace-fail 'Exec=wowup-cf' 'Exec=wowup-cf --enable-features=UseOzonePlatform --ozone-platform=wayland --disable-gpu'
# '';
warcraftLogsUploader = pkgs.fetchurl {
name = "warcraftlogs-client";
url = "https://github.com/RPGLogs/Uploaders-warcraftlogs/releases/download/v8.17.47/warcraftlogs-v8.17.47.AppImage";
sha256 = "1aypr3ffy6lq0qj64d48c7n54nfs72404xb2kpxsw5slqh66imw6";
};
warcraftLogsIcon = pkgs.fetchurl {
name = "warcraftlogs-icon";
url = "https://assets.rpglogs.com/img/warcraft/favicon.png";
sha256 = "0hil7rj7a0bmls0h4w3xmfzcp1gm5yfagbziv1967lmy70ri0bc9";
};
raiderioClient = pkgs.fetchurl {
name = "raiderio-client";
url = "https://raider.io/client/download/linux";
sha256 = "0wcw53bgr9dr02x1ci2jlnc5irpiqxqxgs2hpbrsnj67q50nvlm9";
};
raiderioIcon = pkgs.fetchurl {
name = "raiderio-icon";
url = "https://cdn.raiderio.net/images/brand/Mark_2ColorWhite.png";
sha256 = "13311vi04lv6bp7jvnhinbcfah4ghn9h85cl3wzysz3aaxs73988";
};
in
{
home.packages = with pkgs; [
# Gaming
@@ -10,9 +46,74 @@
];
})
protonup-ng
protonplus
protontricks
vulkan-tools # useful for debugging Vulkan issues
# WoW addon updater
wowup-cf
# Nexus Mod Manager
nexusmods-app-unfree
];
# xdg.dataFile."applications/wowup-cf.desktop" = {
# force = true;
# source = "${patched-desktop}/wowup-cf.desktop";
# };
# wowup needs options to work under wayland.
xdg.desktopEntries.wowup-cf = local.electronDesktopEntry {
name = "WowUp";
exec = "wowup-cf --no-sandbox";
terminal = false;
type = "Application";
icon = "wowup-cf";
comment = "World of Warcraft addon updater";
categories = [
"Game"
];
};
xdg.desktopEntries.warcraftLogs = {
name = "WarcraftLogs";
exec = "${pkgs.appimage-run}/bin/appimage-run ${warcraftLogsUploader}";
terminal = false;
type = "Application";
icon = "${warcraftLogsIcon}";
comment = "WarcraftLogs uploader";
categories = [ "Game" ];
};
xdg.desktopEntries.raiderio = {
name = "Raider.io";
exec = "${pkgs.appimage-run}/bin/appimage-run ${raiderioClient}";
terminal = false;
type = "Application";
icon = "${raiderioIcon}";
comment = "Raider.io Client";
categories = [ "Game" ];
};
wayland.windowManager.hyprland.settings.windowrulev2 = [
# Set up full-screen games on monitor 1 (since window 0 is the vertical one.)
"monitor 1,class:^steam_app_\d+$"
"float,class:^steam_app_\d+$"
"monitor 1,fullscreen:1"
"center,class:^steam_app_\d+$"
# Make sure WoW spawns on the right monitor and that Battlenet floats so it renders correctly
"monitor 1,title:^World of Warcraft$"
"fullscreen,title:^World of Warcraft$"
"monitor 1,title:^Battle.net$"
"float,title:^Battle.net$"
# Make Balatro into a regular window.
"monitor 1,title:^Balatro$"
"tile,title:^Balatro$"
# Load Cyberpunk 2077 on the right monitor.
"monitor 1,class:steam_app_1091500"
"fullscreen,class:steam_app_1091500"
];
}

View File

@@ -12,15 +12,17 @@
"l" = "log --oneline";
};
extraConfig = {
core = {
pager = "";
};
pull = {
rebase = true;
};
log = {
date = "iso";
};
init = {
defaultBranch = "main";
};
};
# Enable the delta diff pager.
delta.enable = true;
};
}

View File

@@ -0,0 +1,34 @@
{ ... }:
{
services.hypridle = {
enable = true;
settings = {
general = {
lock_cmd = "pidof swaylock || ~/.config/swaylock/swaylock.sh"; # avoid starting multiple lock instances.
before_sleep_cmd = "loginctl lock-session"; # lock before suspend.
after_sleep_cmd = "hyprctl dispatch dpms on"; # to avoid having to press a key twice to turn on the display.
};
listener = [
{
timeout = 300; # 5min
on-timeout = "brightnessctl -s set 10"; # set monitor backlight to minimum, avoid 0 on OLED monitor.
on-resume = "brightnessctl -r"; # monitor backlight restore.
}
{
timeout = 330; # 5.5 min
on-timeout = "loginctl lock-session"; # lock screen when timeout has passed
}
{
timeout = 600; # 10 min
on-timeout = "hyprctl dispatch dpms off"; # screen off when timeout has passed
on-resume = "hyprctl dispatch dpms on && brightnessctl -r"; # screen on when activity is detected after timeout has fired.
}
{
timeout = 1800; # 30min
on-timeout = "systemctl suspend"; # suspend pc
}
];
};
};
}

View File

@@ -1,10 +1,28 @@
{ pkgs, inputs, ... }:
{ pkgs, ... }:
{
imports = [
./swaylock.nix
./hypr/hypridle.nix
];
home.packages = with pkgs; [
swayosd # volume pop-up
swaynotificationcenter # notifications
hyprpolkitagent # Privilege managent
hyprshot # Screenshot utility
# For clipboard management. See below.
wl-clipboard
xclip
];
wayland.windowManager.hyprland = {
enable = true;
plugins = [
inputs.hy3.packages.${pkgs.system}.hy3
inputs.split-monitor-workspaces.packages.${pkgs.system}.split-monitor-workspaces
# https://github.com/outfoxxed/hy3
pkgs.hyprlandPlugins.hy3
# https://github.com/shezdy/hyprsplit
pkgs.hyprlandPlugins.hyprsplit
];
# Disable systemd because it conflicts with UWSM
@@ -16,34 +34,22 @@
"DP-1, 2560x1440, -1440x-510, 1, transform, 1"
];
"$terminal" = "wezterm";
"$fileManager" = "dolphin";
"$terminal" = "foot";
"$menu" = "rofi -show combi -combi-modes drun,ssh,run -theme ~/.config/rofi/launcher/style.rasi";
"$browser" = "firefox";
"$browser" = "firefox --new-window";
exec-once = [
"nm-applet"
"sleep 2 && hyprpm reload -n"
"swayidle -w before-sleep hyprlock"
"swayosd-server"
"systemctl --user start hyprpolkitagent"
"gsettings set org.gnome.desktop.interface color-scheme \"prefer-dark\""
"gsettings set org.gnome.desktop.interface gtk-theme \"Adwaita-dark\""
];
env = [
"XCURSOR_SIZE,32"
"HYPRCURSOR_SIZE,32"
"HYPRCURSOR_THEME,phinger"
# Nvidia config
"LIBVA_DRIVER_NAME,nvidia"
"__GLX_VENDOR_LIBRARY_NAME,nvidia"
# For window theming
"QT_QPA_PLATFORMTHEME,qt6ct # for Qt apps"
"GTK_THEME,Adwaita-dark"
# Hyprland doesn't paste into Firefox or Wine apps. This program is a workaround.
# See https://github.com/hyprwm/Hyprland/issues/2319
# -t text = Only handle text
# -w xclip -selection clipboard = Watch for events and invoke xclip
"wl-paste -t text -w xclip -selection clipboard"
];
general = {
@@ -57,7 +63,7 @@
"col.inactive_border" = "rgba(595959aa)";
# Set to true enable resizing windows by clicking and dragging on borders and gaps
resize_on_border = false;
resize_on_border = true;
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
allow_tearing = false;
@@ -235,12 +241,9 @@
};
};
split-monitor-workspaces = {
# Keep the focus when reloading.
keep_focused = true;
# Allocate persistent workspaces. If this is off there are some bugs
# when trying to move to a new workspace if it doesn't already exist.
enable_persistent_workspaces = true;
hyprsplit = {
num_workspaces = 10;
persistent_workspaces = true;
};
};
@@ -283,8 +286,8 @@
"$mainMod, T, exec, $terminal"
"$mainMod, B, exec, $browser"
"$mainMod, D, exec, $menu"
"$mainMod, E, exec, $fileManager"
"$mainMod + SHIFT, S, exec, hyprshot -m region --clipboard-only"
"$mainMod + CTRL + SHIFT, S, exec, hyprshot -m region -o ~/Pictures"
"$mainMod, C, exec, swaync-client -t"
"$mainMod + L_CONTROL, Q, exec, /home/drew/.config/rofi/powermenu/powermenu.sh"
@@ -294,6 +297,10 @@
"$mainMod, F, togglefloating,"
"$mainMod + SHIFT, F, fullscreen, 1"
"$mainMod + CTRL, left, resizeactive, -20 0"
"$mainMod + CTRL, right, resizeactive, 20 0"
"$mainMod + CTRL, down, resizeactive, 0 20"
"$mainMod + CTRL, up, resizeactive, 0 -20"
# Monitors
"$mainMod, R, focusmonitor, next"
@@ -305,42 +312,46 @@
"$mainMod, G, hy3:makegroup, opposite, ephemeral"
"$mainMod, W, hy3:makegroup, tab, ephemeral"
"$mainMod + SHIFT, W, hy3:changegroup, toggletab"
"$mainMod, A, hy3:changefocus, raise"
"$mainMod, Z, hy3:changefocus, lower"
"$mainMod, O, hy3:changegroup, opposite"
"$mainMod, left, hy3:movefocus, l"
"$mainMod, right, hy3:movefocus, r"
"$mainMod, up, hy3:movefocus, u"
"$mainMod, down, hy3:movefocus, d"
"$mainMod, A, hy3:changefocus, raise"
"$mainMod, Z, hy3:changefocus, lower"
"$mainMod, r, focusmonitor, l"
"$mainMod, s, focusmonitor, r"
"$mainMod + SHIFT, left, hy3:movewindow, l"
"$mainMod + SHIFT, right, hy3:movewindow, r"
"$mainMod + SHIFT, up, hy3:movewindow, u"
"$mainMod + SHIFT, down, hy3:movewindow, d"
# Switch workspaces with mainMod + [0-9]
"$mainMod, 1, split-workspace, 1"
"$mainMod, 2, split-workspace, 2"
"$mainMod, 3, split-workspace, 3"
"$mainMod, 4, split-workspace, 4"
"$mainMod, 5, split-workspace, 5"
"$mainMod, 6, split-workspace, 6"
"$mainMod, 7, split-workspace, 7"
"$mainMod, 8, split-workspace, 8"
"$mainMod, 9, split-workspace, 9"
"$mainMod, 0, split-workspace, 10"
"$mainMod, 1, split:workspace, 1"
"$mainMod, 2, split:workspace, 2"
"$mainMod, 3, split:workspace, 3"
"$mainMod, 4, split:workspace, 4"
"$mainMod, 5, split:workspace, 5"
"$mainMod, 6, split:workspace, 6"
"$mainMod, 7, split:workspace, 7"
"$mainMod, 8, split:workspace, 8"
"$mainMod, 9, split:workspace, 9"
"$mainMod, 0, split:workspace, 10"
# Move active window to a workspace with mainMod + SHIFT + [0-9]
"$mainMod SHIFT, 1, split-movetoworkspace, 1, follow"
"$mainMod SHIFT, 2, split-movetoworkspace, 2, follow"
"$mainMod SHIFT, 3, split-movetoworkspace, 3, follow"
"$mainMod SHIFT, 4, split-movetoworkspace, 4, follow"
"$mainMod SHIFT, 5, split-movetoworkspace, 5, follow"
"$mainMod SHIFT, 6, split-movetoworkspace, 6, follow"
"$mainMod SHIFT, 7, split-movetoworkspace, 7, follow"
"$mainMod SHIFT, 8, split-movetoworkspace, 8, follow"
"$mainMod SHIFT, 9, split-movetoworkspace, 9, follow"
"$mainMod SHIFT, 0, split-movetoworkspace, 10, follow"
# Note: using hy3:movetoworkspace instead of split:movetoworkspace.
# The plugins are compatible.
"$mainMod SHIFT, 1, hy3:movetoworkspace, 1, follow"
"$mainMod SHIFT, 2, hy3:movetoworkspace, 2, follow"
"$mainMod SHIFT, 3, hy3:movetoworkspace, 3, follow"
"$mainMod SHIFT, 4, hy3:movetoworkspace, 4, follow"
"$mainMod SHIFT, 5, hy3:movetoworkspace, 5, follow"
"$mainMod SHIFT, 6, hy3:movetoworkspace, 6, follow"
"$mainMod SHIFT, 7, hy3:movetoworkspace, 7, follow"
"$mainMod SHIFT, 8, hy3:movetoworkspace, 8, follow"
"$mainMod SHIFT, 9, hy3:movetoworkspace, 9, follow"
"$mainMod SHIFT, 0, hy3:movetoworkspace, 10, follow"
# These don't take monitor numbers, but rather differences. It's next/prev but
# it'll always just move it to the other monitor
"$mainMod SHIFT, r, split-changemonitor, prev"
"$mainMod SHIFT, r, movewindow, mon:+1"
];
# m = mouse bindings
@@ -388,31 +399,101 @@
"opaque,class:(),title:()"
"noshadow,class:(),title:()"
"noblur,class:(),title:()"
# Set up full-screen games on monitor 1
"monitor 1,class:^steam_app_\d+$"
"float,class:^steam_app_\d+$"
"monitor 1,fullscreen:1"
"center,class:^steam_app_\d+$"
"monitor 1,title:^World of Warcraft$"
"monitor 1,title:^Battle.net$"
"float,title:^Battle.net$"
];
# See https://wiki.hyprland.org/Configuring/Workspace-Rules/ for workspace rules
workspace = [
"11, defaultName:1"
"12, defaultName:2"
"13, defaultName:3"
"14, defaultName:4"
"15, defaultName:5"
"16, defaultName:6"
"17, defaultName:7"
"18, defaultName:8"
"19, defaultName:9"
"20, defaultName:10"
"1, defaultName:L1"
"2, defaultName:L2"
"3, defaultName:L3"
"4, defaultName:L4"
"5, defaultName:L5"
"6, defaultName:L6"
"7, defaultName:L7"
"8, defaultName:L8"
"9, defaultName:L9"
"10, defaultName:L10"
"11, defaultName:R1"
"12, defaultName:R2"
"13, defaultName:R3"
"14, defaultName:R4"
"15, defaultName:R5"
"16, defaultName:R6"
"17, defaultName:R7"
"18, defaultName:R8"
"19, defaultName:R9"
"20, defaultName:R10"
];
};
};
programs.hyprlock = {
enable = false;
settings = {
general = {
disable_loading_bar = true;
hide_cursor = true;
};
background = {
monitor = "";
color = "rgb(000000)";
};
# Time
label = {
monitor = "";
text = ''
cmd[update:1000] echo "$(date '+%F %T')"
'';
font_size = 96;
font_family = "NotoSans Nerd Font";
color = "rgb(990000)";
position = "0, 0";
halign = "center";
valign = "center";
};
input-field = {
monitor = "";
size = "300, 40";
fade_on_empty = true;
outline_thickness = 2;
outer_color = "rgb(cc2222) rgb(661111)";
inner_color = "rgb(221111)";
font_color = "rgb(cc2222)";
dots_size = 0.2;
dots_spacing = 0.1;
placeholder_text = "";
fail_color = "rgb(cc3333)";
capslock_color = "rgb(cccc33)";
halign = "center";
valign = "center";
position = "0, -300px";
};
};
};
# UWSM sessions should not use Hyprland's variables but instead use UWSM's variable management.
# See https://wiki.hyprland.org/Configuring/Environment-variables/
home.file.".config/uwsm/env".text = ''
export XCURSOR_SIZE="32"
export HYPRCURSOR_SIZE="32"
export HYPRCURSOR_THEME="phinger"
# Nvidia config
export LIBVA_DRIVER_NAME="nvidia"
export __GLX_VENDOR_LIBRARY_NAME="nvidia"
# For window theming
export QT_QPA_PLATFORMTHEME="qt6ct # for Qt apps"
export GTK_THEME="Adwaita-dark"
# Tell electron apps they should use OZone for Wayland
export ELECTRON_OZONE_PLATFORM_HINT="auto"
'';
}

View File

@@ -0,0 +1,7 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
gimp3
inkscape
];
}

View File

@@ -1,43 +1,58 @@
{ pkgs, ... }:
{
imports = [
./hyprland.nix
./audio.nix
./nix.nix
./hyprland.nix
./rofi/rofi.nix
./sway.nix
../apps/element.nix
../apps/discord.nix
./terminal.nix
];
home.packages = with pkgs; [
home = {
packages = with pkgs; [
# Desktop Applications
gimp3
# Common utilities
feh
networkmanagerapplet # network control
hyprlock # lock screen
swayidle # lock on idle
swayosd # volume pop-up
swaynotificationcenter # notifications
hyprpolkitagent # Privilege managent
gnome-keyring # Secret management
glib # for Gnome/GTK settings
gsettings-desktop-schemas # So that we can access gnome settings
xdg-desktop-portal-hyprland
xdg-desktop-portal-gtk # GTK backend for XDG components like pickers
grim # Screenshot provider
hyprshot # Screenshot utility
nwg-look # GTK settings editor
playerctl # for universal play/pause etc
wirelesstools
waypaper # Wallpaper switcher
phinger-cursors # Mouse cursors
];
# Hint for electron apps to use wayland
home.sessionVariables.NIXOS_OZONE_WL = "1";
pointerCursor = {
enable = true;
gtk.enable = true;
name = "phinger-cursors";
size = 16;
package = pkgs.phinger-cursors;
};
# Micelaneious config files
home.file = {
# Hint for electron apps to use wayland
sessionVariables.NIXOS_OZONE_WL = "1";
# Miscelaneous config files
file = {
".XCompose".source = ./config/XCompose;
};
};
programs = {
# browsers
firefox.enable = true;
librewolf.enable = true;
chromium.enable = true;
};
# GTK settings
gtk = {
@@ -68,4 +83,18 @@
platformTheme.name = "adwaita";
style.name = "adwaita-dark";
};
# Default apps
xdg.mimeApps = {
enable = true;
defaultApplications = {
"text/html" = [ "firefox.desktop" ];
"default-web-browser" = [ "firefox.desktop" ];
"x-scheme-handler/http" = [ "firefox.desktop" ];
"x-scheme-handler/https" = [ "firefox.desktop" ];
"x-scheme-handler/about" = [ "firefox.desktop" ];
"x-scheme-handler/unknown" = [ "firefox.desktop" ];
};
};
home.sessionVariables.DEFAULT_BROWSER = "${pkgs.firefox}/bin/firefox";
}

View File

@@ -0,0 +1,18 @@
{
"extras": [
"lazyvim.plugins.extras.coding.mini-comment",
"lazyvim.plugins.extras.coding.mini-surround",
"lazyvim.plugins.extras.editor.snacks_picker",
"lazyvim.plugins.extras.lang.astro",
"lazyvim.plugins.extras.lang.haskell",
"lazyvim.plugins.extras.lang.json",
"lazyvim.plugins.extras.lang.markdown",
"lazyvim.plugins.extras.lang.nix",
"lazyvim.plugins.extras.lang.rust",
"lazyvim.plugins.extras.lang.tailwind",
"lazyvim.plugins.extras.lang.toml",
"lazyvim.plugins.extras.lang.typescript"
],
"install_version": 8,
"version": 8
}

View File

@@ -10,8 +10,8 @@
vim.api.nvim_create_autocmd("FileType", {
pattern = { "markdown" },
callback = function()
vim.bo.shiftwidth = 4
vim.bo.tabstop = 4
vim.bo.softtabstop = 4
vim.o.shiftwidth = 2
vim.o.tabstop = 2
vim.o.softtabstop = 2
end,
})

View File

@@ -18,6 +18,10 @@ require("lazy").setup({
spec = {
-- add LazyVim and import its plugins
{ "LazyVim/LazyVim", import = "lazyvim.plugins" },
-- Integrate ESlint for fixes and prettier for formatting
-- See: https://www.lazyvim.org/configuration/recipes
{ import = "lazyvim.plugins.extras.linting.eslint" },
{ import = "lazyvim.plugins.extras.formatting.prettier" },
-- import/override with your plugins
{ import = "plugins" },
},

View File

@@ -4,3 +4,6 @@
-- Creates a shortcut for adding the directory of the current buffer when specifying a file
vim.cmd("cnoreabbrev %. %:h<Tab>")
-- Set snacks as the preferred picker.
vim.g.lazyvim_picker = "snacks"

View File

@@ -0,0 +1,37 @@
return {
"saghen/blink.cmp",
dependencies = {
"moyiz/blink-emoji.nvim",
},
opts = {
sources = {
default = { "lsp", "buffer", "snippets", "path", "emoji" },
providers = {
-- https://github.com/moyiz/blink-emoji.nvim
emoji = {
module = "blink-emoji",
name = "Emoji",
score_offset = 15, -- Tune by preference
opts = { insert = true }, -- Insert emoji (default) or complete its name
should_show_items = function()
return vim.tbl_contains(
-- Enable emoji completion only for git commits and markdown.
-- By default, enabled for all file-types.
{ "gitcommit", "markdown" },
vim.o.filetype
)
end,
},
},
},
keymap = {
preset = "default",
["<C-space>"] = {
function(cmp)
cmp.show()
end,
},
["<Tab>"] = { "select_and_accept", "snippet_forward", "fallback" },
},
},
}

View File

@@ -0,0 +1,8 @@
return {
"stevearc/conform.nvim",
opts = {
formatters_by_ft = {
nix = { "nixfmt" },
},
},
}

View File

@@ -1,9 +0,0 @@
return {
"zbirenbaum/copilot.lua",
opts = {
filetypes = {
markdown = false,
help = false,
},
},
}

View File

@@ -1,5 +1,5 @@
return {
-- Maeson installs it's own binaries that are incompatible with NixOS.
{ "williamboman/mason.nvim", enabled = false },
{ "williamboman/mason-lspconfig.nvim", enabled = false },
{ "mason-org/mason.nvim", enabled = false },
{ "mason-org/mason-lspconfig.nvim", enabled = false },
}

View File

@@ -1,11 +0,0 @@
return {
-- https://www.lazyvim.org/extras/editor/fzf
"ibhagwan/fzf-lua",
keys = {
{
"<leader><space>",
"<cmd>FzfLua buffers sort_mru=true sort_lastused=true<cr>",
desc = "Switch Buffer",
},
},
}

View File

@@ -3,8 +3,17 @@ return {
"neovim/nvim-lspconfig",
opts = {
servers = {
-- Lua
lua_ls = {},
-- Nix
nil_ls = {},
-- Typescript
vtsls = {},
-- Haskell
hls = {},
},
codelens = {
enable = true,
},
},
},

View File

@@ -0,0 +1,45 @@
-- https://github.com/MeanderingProgrammer/render-markdown.nvim?tab=readme-ov-file#setup
return {
"MeanderingProgrammer/render-markdown.nvim",
opts = {
checkbox = {
enabled = true,
render_modes = true,
unchecked = {
icon = "󰄱 ",
highlight = "RenderMarkdownUnchecked",
scope_highlight = nil,
},
checked = {
-- Replaces '[x]' of 'task_list_marker_checked'.
icon = "󰱒 ",
-- Highlight for the checked icon.
highlight = "RenderMarkdownChecked",
-- Highlight for item associated with checked checkbox.
scope_highlight = nil,
},
-- Define custom checkbox states, more involved, not part of the markdown grammar.
-- As a result this requires neovim >= 0.10.0 since it relies on 'inline' extmarks.
-- The key is for healthcheck and to allow users to change its values, value type below.
-- | raw | matched against the raw text of a 'shortcut_link' |
-- | rendered | replaces the 'raw' value when rendering |
-- | highlight | highlight for the 'rendered' icon |
-- | scope_highlight | optional highlight for item associated with custom checkbox |
-- stylua: ignore
custom = {
partial = {
raw = '[/]',
rendered = '',
highlight = 'RenderMarkdownTodo',
scope_highlight = nil
},
deferred = {
raw = '[>]',
rendered = '',
highlight = 'RenderMarkdownWarn',
scope_highlight = nil
},
},
},
},
}

View File

@@ -1,10 +1,38 @@
return {
{
"echasnovski/mini.surround",
"nvim-mini/mini.surround",
enable = true,
keys = function(_, keys)
-- Populate the keys based on the user's options
local opts = LazyVim.opts("mini.surround")
local mappings = {
{ opts.mappings.add, desc = "Add Surrounding", mode = { "n", "v" } },
{ opts.mappings.delete, desc = "Delete Surrounding" },
{ opts.mappings.find, desc = "Find Right Surrounding" },
{ opts.mappings.find_left, desc = "Find Left Surrounding" },
{ opts.mappings.highlight, desc = "Highlight Surrounding" },
{ opts.mappings.replace, desc = "Replace Surrounding" },
{ opts.mappings.update_n_lines, desc = "Update `MiniSurround.config.n_lines`" },
}
mappings = vim.tbl_filter(function(m)
return m[1] and #m[1] > 0
end, mappings)
return vim.list_extend(mappings, keys)
end,
opts = {
mappings = {
add = "gsa", -- Add surrounding in Normal and Visual modes
delete = "gsd", -- Delete surrounding
find = "gsf", -- Find surrounding (to the right)
find_left = "gsF", -- Find surrounding (to the left)
highlight = "gsh", -- Highlight surrounding
replace = "gsr", -- Replace surrounding
update_n_lines = "gsn", -- Update `n_lines`
},
},
},
{
"echasnovski/mini.comment",
"nvim-mini/mini.comment",
enable = true,
},
}

View File

@@ -1,20 +1,7 @@
return {
"epwalsh/obsidian.nvim",
"obsidian-nvim/obsidian.nvim",
version = "*", -- recommended, use latest release instead of latest commit
lazy = true,
ft = "markdown",
-- Replace the above line with this if you only want to load obsidian.nvim for markdown files in your vault:
-- event = {
-- -- If you want to use the home shortcut '~' here you need to call 'vim.fn.expand'.
-- -- E.g. "BufReadPre " .. vim.fn.expand "~" .. "/my-vault/*.md"
-- -- refer to `:h file-pattern` for more examples
-- "BufReadPre path/to/my-vault/*.md",
-- "BufNewFile path/to/my-vault/*.md",
-- },
dependencies = {
-- Required.
"nvim-lua/plenary.nvim",
},
opts = {
workspaces = {
{
@@ -22,18 +9,65 @@ return {
path = "~/Documents/Notes",
},
},
-- Can I enable this somehow? I'm using blink.cmp but this is triggering
-- it to look for nvim-cmp directly.
-- completion = {
-- nvim_cmp = true,
-- min_chars = 2,
-- },
daily_notes = {
-- Optional, if you keep daily notes in a separate directory.
folder = "Daily Notes",
-- Optional, if you want to change the date format for the ID of daily notes.
date_format = "%Y-%m-%d",
-- Optional, if you want to automatically insert a template from your template directory like ''
template = nil,
template = "Daily Note",
},
templates = {
folder = "Templates",
date_format = "%Y-%m-%d",
time_format = "%H:%M",
},
ui = {
-- Disable the UI features and let render-markdown.nvim handle it.
enable = false,
-- Even with UI disabled, this determines the order of checkbox states for the smart action.
checkboxes = {
[" "] = { char = "", hl_group = "ObsidianTodo" },
["x"] = { char = "", hl_group = "ObsidianDone" },
["/"] = { char = "", hl_group = "ObsidianTodo" },
[">"] = { char = "»", hl_group = "ObsidianRightArrow" },
["~"] = { char = "»", hl_group = "ObsidianTilde" },
["!"] = { char = "", hl_group = "ObsidianDone" },
},
},
-- Put the note ID in the wiki links
wiki_link_func = "prepend_note_id",
preferred_link_style = "wiki",
-- Customize how note IDs are generated given an optional title.
---@param title string|?
---@return string
note_id_func = function(title)
if title ~= nil then
-- If title is given, transform it into valid file name by removing most special characters
-- Note that parens are not supported because they interfere with markdown links.
return title:gsub("[^A-Za-z0-9-_]", ""):lower()
else
-- If title is nil, just put the date and four random characters
for _ = 1, 4 do
return os.date("%Y-%m-%d ") .. string.char(math.random(65, 90))
end
end
end,
follow_url_func = function(url)
vim.ui.open(url) -- Use the built-in open, need Neovim 0.10.0+
end,
},
}

View File

@@ -0,0 +1,65 @@
return {
"folke/snacks.nvim",
opts = function(_, opts)
vim.tbl_deep_extend("force", opts, {
picker = {
smart = {
-- Remove the "recent" picker so we don't get things from other directories.
multi = { "buffers", "files" },
matcher = {
-- sort even when the search string is empty
sort_empty = true,
-- Enable frecensy for matchers. This puts more common files near the top
frecency = false,
-- Make sure files in the current directory are prioritized
cwd_bonus = true,
-- Give more weight to files that are more recent
history_bonus = true,
-- Give more weight to places where the filename is part of the match
filename_bonus = true,
},
},
sources = {
explorer = {
layout = { layout = { position = "right" } },
},
},
-- This only supports the Kitty graphics protocol.
-- See
-- https://github.com/folke/snacks.nvim/blob/main/docs/image.md
-- https://github.com/obsidian-nvim/obsidian.nvim/wiki/Images
-- image = {
-- resolve = function(path, src)
-- if require("obsidian.api").path_is_note(path) then
-- return require("obsidian.api").resolve_image_path(src)
-- end
-- end,
-- },
},
})
Snacks.toggle({
name = "Color Column",
get = function()
return vim.o.colorcolumn == "80"
end,
set = function(state)
if state then
vim.o.colorcolumn = "80"
vim.cmd([[highlight ColorColumn guibg=#202020]])
else
vim.o.colorcolumn = ""
vim.cmd([[highlight ColorColumn guibg=None]])
end
end,
}):map("<leader>ut", { desc = "Toggle Color Column" })
end,
keys = {
{
"<leader><space>",
function()
Snacks.picker.smart()
end,
desc = "Smart Find Files",
},
},
}

View File

@@ -1,14 +0,0 @@
return {
"nvim-telescope/telescope.nvim",
enabled = false,
keys = {
-- Switch the default keybind to switch buffers instead of find files
{
"<leader><space>",
"<cmd>Telescope buffers sort_mru=true sort_lastused=true<cr>",
desc = "Open Files",
},
-- Disable the <leader><comma> since it's so hard to type and redundant with the above.
{ "<leader><comma>", false },
},
}

View File

@@ -0,0 +1,10 @@
return {
"folke/tokyonight.nvim",
opts = {
transparent = true,
styles = {
sidebars = "transparent",
-- floats = "transparent",
},
},
}

View File

@@ -0,0 +1,23 @@
return {
"nvim-treesitter/nvim-treesitter",
opts = {
ensure_installed = {
"astro",
"bash",
"html",
"css",
"javascript",
"json",
"lua",
"markdown",
"markdown_inline",
"python",
"query",
"regex",
"tsx",
"typescript",
"vim",
"yaml",
},
},
}

View File

@@ -9,6 +9,7 @@
extraPackages = with pkgs; [
gcc # For treesitter complation
tree-sitter # For treesitter binaries
ripgrep # Search support
wayclip # Clipboard support
fd # finder for telescope
@@ -17,6 +18,7 @@
wget # LazyVim dep?
sqlite # For Snacks
imagemagick # For image conversion/display
vscode-langservers-extracted # For language servers (it wants this version of eslint for some reason)
];
};

View File

@@ -1,10 +0,0 @@
{ pkgs, ... }:
{
# Enable flakes and nix-commnands.
nix.settings.experimental-features = ["flakes" "nix-command"];
# Allow unfree code
nixpkgs.config = {
allowUnfree = true;
};
}

View File

@@ -1,5 +1,13 @@
{ lib, ... }:
{ lib, pkgs, ... }:
{
home.packages = with pkgs; [
obsidian
];
home.shellAliases = {
"notes" = "(cd ~/Documents/Notes && nvim)";
};
services.syncthing = {
enable = true;
tray = {
@@ -17,6 +25,7 @@
"altair"
"mcp"
"vega"
"proxima"
];
};
};
@@ -48,6 +57,14 @@
];
compression = "always";
};
proxima = {
id = "NWZL6LY-ULJQMZE-EWY3MQU-XPDAFQB-LTIBZV7-GPKIABJ-WBJE36F-SK6LVAY";
name = "Proxima";
addresses = [
"relay://syncthing.blazestar.net:22067"
];
compression = "always";
};
};
options = {
localAnnounceEnabled = false;

View File

@@ -7,7 +7,7 @@
**/
* {
background: #15161EFF;
background: #15161ECC;
background-alt: #1A1B26FF;
foreground: #C0CAF5FF;
selected: #33467CFF;

View File

@@ -1,3 +1,3 @@
configuration {
ssh-command: "wezterm ssh {host}";
ssh-command: "foot ssh {host}";
}

View File

@@ -15,4 +15,4 @@
/* Import color-scheme from `colors` directory */
@import "~/.config/rofi/colors/onedark.rasi"
@import "~/.config/rofi/colors/tokyonight.rasi"

View File

@@ -32,8 +32,8 @@ window {
enabled: true;
margin: 0px;
padding: 0px;
border: 0px solid;
border-radius: 0px;
border: 2px solid;
border-radius: 5px;
border-color: @selected;
background-color: @background;
cursor: "default";

View File

@@ -15,4 +15,4 @@
/* Import color-scheme from `colors` directory */
@import "~/.config/rofi/colors/onedark.rasi"
@import "~/.config/rofi/colors/tokyonight.rasi"

View File

@@ -11,7 +11,7 @@ dir="${HOME}/.config/rofi/powermenu"
# CMDs
uptime="$(uptime | awk -F ' ' '{print $2}' | sed -e 's/,//g')"
host=`hostname`
host=$(hostname)
# Options
shutdown='󰐥'
@@ -76,7 +76,9 @@ run_cmd() {
qdbus org.kde.ksmserver /KSMServer logout 0 0 0
elif [[ "$DESKTOP_SESSION" == 'plasma' ]]; then
qdbus org.kde.ksmserver /KSMServer logout 0 0 0
elif command -v hyprctl &>/dev/null; then
elif [[ "$DESKTOP_SESSION" == 'hyprland-uwsm' ]]; then
hyprctl dispatch exit
elif [[ "$DESKTOP_SESSION" == 'hyprland' ]]; then
hyprctl dispatch exit
fi
fi
@@ -95,13 +97,16 @@ case ${chosen} in
run_cmd --reboot
;;
$lock)
if [[ -x '/usr/bin/betterlockscreen' ]]; then
betterlockscreen -l
elif [[ -x '/usr/bin/i3lock' ]]; then
i3lock
elif command -v hyprlock &>/dev/null; then
hyprlock
fi
loginctl lock-session
# if [[ -x '/usr/bin/betterlockscreen' ]]; then
# betterlockscreen -l
# elif [[ -x '/usr/bin/i3lock' ]]; then
# i3lock
# elif command -v hyprlock &>/dev/null; then
# hyprlock
# elif command -v swaylock &>/dev/null; then
# swaylock
# fi
;;
$suspend)
run_cmd --suspend

View File

@@ -35,8 +35,8 @@ window {
enabled: true;
margin: 0px;
padding: 0px;
border: 0px solid;
border-radius: 0px;
border: 2px solid;
border-radius: 5px;
border-color: @selected;
cursor: "default";
background-color: @background;

View File

@@ -8,4 +8,10 @@
source = ./config;
recursive = true;
};
wayland.windowManager.hyprland.settings.windowrulev2 = [
# Forces the Rofi window to hold focus so that it gets input even if
# something else opens or the mouse is outside the window.
"stayfocused, class:Rofi"
];
}

View File

@@ -2,6 +2,10 @@
{ pkgs, ... }:
{
imports = [
./uutils.nix
];
# These are all the sort of shell commands that we want available whereever
# there is shell. These include just a lot of useful utilities for managing
# a system or working with other shell commands. Packages more specific to
@@ -11,35 +15,53 @@
htop
btop
neofetch
killall
psmisc # fuser, killal, pstree
# Files
# Archives
zip
xz
unzip
p7zip
unrar-wrapper
# File manipulation
file
tree
ranger
ueberzugpp # for image previews
yazi # File manager
w3m # terminal browser for image previews
dysk # better disk info
ripgrep # better grep
fd # Better find
bat # cat with wings
eza # Modern replacement for ls
dust # More intuitive du
dua # Interactive disk usage analyzer
# Networking
dnsutils
inetutils
socat
httpie
xh
# devices
usbutils
# Other
jq
mprocs # Manage multiple long-running processes
];
home.shellAliases = {
"p?" = "ps ax | grep";
"p?" = "ps ax | rg";
# Dysk is basically just better.
"df" = "echo 'Do you mean: dysk?'";
"grep" = "echo 'Do you mean: rg?'";
"find" = "echo 'Do you mean: fd'";
"cat" = "bat";
"ls" = "eza";
"http" = "echo 'Do you mean: xh'";
"du" = "echo 'Do you mean: dust or dua?'";
"ranger" = "echo 'Do you mean: yazi'";
};
programs.zsh = {
@@ -48,7 +70,7 @@
PATH=$PATH:$HOME/.local/bin
GITHUB_USERNAME=periodic
'';
initExtra = ''
initContent = ''
# Make ^U work like it does in Bash
bindkey "^U" backward-kill-line
@@ -94,6 +116,12 @@
];
};
programs.zoxide = {
# TODO: Learn all the capabilities of zoxide and use them.
enable = true;
enableZshIntegration = true;
};
programs.starship = {
enable = true;
settings = {

View File

@@ -0,0 +1,154 @@
{
config,
lib,
...
}:
{
imports = [
./swaync.nix
./swaylock.nix
];
services.swayosd = {
enable = true;
topMargin = 0.7;
};
# Enable sway config generation for home.pointerCursor
home.pointerCursor.sway.enable = true;
wayland.windowManager.sway = {
enable = true;
extraOptions = [
# Required for NVIDIA GPUs
"--unsupported-gpu"
];
checkConfig = true;
systemd = {
enable = true;
xdgAutostart = true;
};
config = {
# Workspace assignments
# Example:
# {
# "1: web" = [{ class = "^Firefox$"; }];
# "0: extra" = [{ class = "^Firefox$"; window_role = "About"; }];
# }
assigns = { };
colors = {
background = "#333333";
focused = {
background = "#285577";
border = "#4c7899";
childBorder = "#285577";
indicator = "#2e9ef4";
text = "#ffffff";
};
focusedInactive = {
background = "#5f676a";
border = "#333333";
childBorder = "#5f676a";
indicator = "#484e50";
text = "#ffffff";
};
placeholder = {
background = "#0c0c0c";
border = "#000000";
childBorder = "#0c0c0c";
indicator = "#000000";
text = "#ffffff";
};
unfocused = {
background = "#222222";
border = "#333333";
childBorder = "#222222";
indicator = "#292d2e";
text = "#888888";
};
urgent = {
background = "#900000";
border = "#2f343a";
childBorder = "#900000";
indicator = "#900000";
text = "#ffffff";
};
};
modifier = "Mod4"; # Super key
keybindings =
let
modifier = config.wayland.windowManager.sway.config.modifier;
terminal = "foot";
browser = "firefox";
menu = "rofi -show drun";
in
lib.mkOptionDefault {
"${modifier}+t" = "exec ${terminal}";
"${modifier}+b" = "exec ${browser}";
"${modifier}+d" = "exec ${menu}";
"${modifier}+Shift+s" = "exec hyprshot -m region --clipboard-only";
"${modifier}+c" = "exec swaync-client -t";
"${modifier}+Control+q" = "exec /home/drew/.config/rofi/powermenu/powermenu.sh";
"${modifier}+x" = "exec /home/drew/.config/rofi/powermenu/powermenu.sh";
"${modifier}+f" = "floating toggle";
"${modifier}+Shift+f" = "fullscreen toggle";
"${modifier}+r" = "focus output right"; # sway does not have `focusmonitor next`
"${modifier}+Control+r" = "move workspace to output left";
"${modifier}+Control+s" = "move workspace to output right";
"${modifier}+q" = "kill";
"${modifier}+Left" = "focus left";
"${modifier}+Right" = "focus right";
"${modifier}+Up" = "focus up";
"${modifier}+Down" = "focus down";
"${modifier}+Shift+Left" = "move left";
"${modifier}+Shift+Right" = "move right";
"${modifier}+Shift+Up" = "move up";
"${modifier}+Shift+Down" = "move down";
# Workspace switching
"${modifier}+1" = "workspace number 1";
"${modifier}+2" = "workspace number 2";
"${modifier}+3" = "workspace number 3";
"${modifier}+4" = "workspace number 4";
"${modifier}+5" = "workspace number 5";
"${modifier}+6" = "workspace number 6";
"${modifier}+7" = "workspace number 7";
"${modifier}+8" = "workspace number 8";
"${modifier}+9" = "workspace number 9";
"${modifier}+0" = "workspace number 10";
"${modifier}+Shift+1" = "move container to workspace number 1; workspace number 1";
"${modifier}+Shift+2" = "move container to workspace number 2; workspace number 2";
"${modifier}+Shift+3" = "move container to workspace number 3; workspace number 3";
"${modifier}+Shift+4" = "move container to workspace number 4; workspace number 4";
"${modifier}+Shift+5" = "move container to workspace number 5; workspace number 5";
"${modifier}+Shift+6" = "move container to workspace number 6; workspace number 6";
"${modifier}+Shift+7" = "move container to workspace number 7; workspace number 7";
"${modifier}+Shift+8" = "move container to workspace number 8; workspace number 8";
"${modifier}+Shift+9" = "move container to workspace number 9; workspace number 9";
"${modifier}+Shift+0" = "move container to workspace number 10; workspace number 10";
"${modifier}+Shift+r" = "move container to output left"; # approximating hyprland\u2019s split-changemonitor
"${modifier}+button1" = "move";
"${modifier}+button2" = "resize";
"XF86AudioRaiseVolume" = "exec swayosd-client --output-volume raise";
"XF86AudioLowerVolume" = "exec swayosd-client --output-volume lower";
"XF86AudioMute" = "exec swayosd-client --output-volume mute-toggle";
"XF86AudioMicMute" = "exec swayosd-client --input-volume mute-toggle";
"XF86AudioNext" = "exec playerctl next";
"XF86AudioPause" = "exec playerctl play-pause";
"XF86AudioPlay" = "exec playerctl play-pause";
"XF86AudioPrev" = "exec playerctl previous";
};
};
};
}

View File

@@ -0,0 +1,37 @@
{ pkgs, ... }:
{
programs.swaylock = {
enable = true;
package = pkgs.swaylock-effects;
settings = {
clock = true;
indicator = true;
effect-pixelate = 20;
};
};
home.file.".config/swaylock/swaylock.sh" = {
executable = true;
# A script that will take the wallpaper folder for each monitor (see
# wallpaper.nix) and use a random image as the background on each monitor.
text = ''
#!/usr/bin/env sh
wallpaper_dir="$HOME/Pictures/Wallpaper"
cmd="swaylock"
for monitor in $(hyprctl monitors | awk '/^Monitor/ { print $2 }'); do
dir="$wallpaper_dir/$monitor"
if [ -d "$dir" ]; then
image=$(find "$dir" -type f | shuf -n 1)
if [ -n "$image" ]; then
cmd="$cmd --image \"$monitor:$image\""
fi
fi
done
# Eval to handle the quoted image paths correctly
eval $cmd
'';
};
}

View File

@@ -0,0 +1,98 @@
{ ... }:
{
services.swaync = {
enable = true;
settings = {
"positionX" = "right";
"positionY" = "top";
"layer" = "overlay";
"control-center-layer" = "top";
"layer-shell" = true;
"cssPriority" = "application";
"control-center-margin-top" = 0;
"control-center-margin-bottom" = 0;
"control-center-margin-right" = 0;
"control-center-margin-left" = 0;
"notification-2fa-action" = true;
"notification-inline-replies" = false;
"notification-icon-size" = 64;
"notification-body-image-height" = 100;
"notification-body-image-width" = 200;
"timeout" = 10;
"timeout-low" = 5;
"timeout-critical" = 0;
"fit-to-screen" = true;
"relative-timestamps" = true;
"control-center-width" = 500;
"control-center-height" = 600;
"notification-window-width" = 500;
"keyboard-shortcuts" = true;
"image-visibility" = "when-available";
"transition-time" = 200;
"hide-on-clear" = false;
"hide-on-action" = true;
"script-fail-notify" = true;
"scripts" = {
"example-script" = {
"exec" = "echo 'Do something...'";
"urgency" = "Normal";
};
"example-action-script" = {
"exec" = "echo 'Do something actionable!'";
"urgency" = "Normal";
"run-on" = "action";
};
};
"notification-visibility" = {
"example-name" = {
"state" = "muted";
"urgency" = "Low";
"app-name" = "Spotify";
};
};
"widgets" = [
"inhibitors"
"title"
"dnd"
"notifications"
];
"widget-config" = {
"inhibitors" = {
"text" = "Inhibitors";
"button-text" = "Clear All";
"clear-all-button" = true;
};
"title" = {
"text" = "Notifications";
"clear-all-button" = true;
"button-text" = "Clear All";
};
"dnd" = {
"text" = "Do Not Disturb";
};
"label" = {
"max-lines" = 5;
"text" = "Label Text";
};
"mpris" = {
"image-size" = 96;
"image-radius" = 12;
};
"buttons-grid" = {
"actions" = [
{
"label" = "";
"type" = "toggle";
"active" = true;
"command" =
"sh -c '[[ $SWAYNC_TOGGLE_STATE == true ]] && nmcli radio wifi on || nmcli radio wifi off'";
"update_command" = "sh -c '[[ $(nmcli radio wifi) == \"enabled\" ]] && echo true || echo false'";
}
];
};
};
};
};
}

View File

@@ -4,9 +4,16 @@
home.packages = with pkgs; [
# Font
# 24.11
# inconsolata-nerdfont
# fira-code-nerdfont
# 25.05
nerd-fonts.inconsolata
nerd-fonts.fira-code
nerd-fonts.jetbrains-mono
libsixel # For working with images in terminals
ueberzugpp # for image previews
];
# Allow Home Manager to set fonts.
@@ -37,6 +44,45 @@
};
home.shellAliases = {
"imgcat" = "wezterm imgcat";
"imgcat" = "img2sixel";
};
programs.foot = {
enable = true;
settings = {
main = {
font = "FiraCode Nerd Font:size=12";
selection-target = "primary";
pad = "8x8";
};
scrollback = {
lines = 5000;
};
colors = {
alpha = 0.9;
# Tokionight Night theme
# From https://codeberg.org/dnkl/foot/src/branch/master/themes/tokyonight-night
background = "1a1b26";
foreground = "c0caf5";
regular0 = "15161E";
regular1 = "f7768e";
regular2 = "9ece6a";
regular3 = "e0af68";
regular4 = "7aa2f7";
regular5 = "bb9af7";
regular6 = "7dcfff";
regular7 = "a9b1d6";
bright0 = "414868";
bright1 = "f7768e";
bright2 = "9ece6a";
bright3 = "e0af68";
bright4 = "7aa2f7";
bright5 = "bb9af7";
bright6 = "7dcfff";
bright7 = "c0caf5";
};
};
};
}

View File

@@ -0,0 +1,7 @@
{ pkgs, lib, ... }:
{
home.packages = with pkgs; [
# Use uutils core-utils with no prefix so they override the GNU coreutils
(lib.hiPrio uutils-coreutils-noprefix)
];
}

View File

@@ -5,11 +5,24 @@ monitors:
"wpaperd"
];
programs.wpaperd = {
services.wpaperd = {
enable = true;
settings = builtins.listToAttrs (map (mon: {
settings =
builtins.listToAttrs (
map (mon: {
name = mon;
value = { path = "~/Pictures/Wallpaper/${mon}"; };
}) monitors);
value = {
# Each monitor gets a folder under wallpaper that containes the current images.
path = "~/Pictures/Wallpaper/${mon}";
};
}) monitors
)
// {
default = {
duration = "1h";
mode = "center";
sorting = "random";
};
};
};
}

3
lib/default.nix Normal file
View File

@@ -0,0 +1,3 @@
{
inherit (import ./electron.nix) electronDesktopEntry;
}

9
lib/electron.nix Normal file
View File

@@ -0,0 +1,9 @@
{
# Adds extra arguments to avoid flickering under wayland.
electronDesktopEntry =
desktop:
desktop
// {
exec = "${desktop.exec} --enable-features=UseOzonePlatform --ozone-platform=wayland --disable-gpu";
};
}

View File

@@ -1,14 +1,33 @@
gitea_db_password: ENC[AES256_GCM,data:G2YqiDk0msBRjUJkoPxWmayQ9dI=,iv:FsojIJIi61K7rD2VULDgIx6uSYX3iDiA6W744HlgHl0=,tag:BlmsM7LZHnBCKtfuqlhoKA==,type:str]
gitea:
db_password: ENC[AES256_GCM,data:12FYMsc8HdTMdPegoPLCidaHMMU=,iv:Uat0g7Nvota1yvj6InIAo7Dzv3cBtVVzlRa1d09gx1s=,tag:sFavpAHW0k/Fv1uzPVuGcA==,type:str]
registration_token: ENC[AES256_GCM,data:zYfFATOuqACrGUyt6xPhiisz293uomKc6BLPKz8I+MFFBrBdzT9FqA==,iv:gyp2WsUHMMrNBmssWGPLSJmZqlAtopc6HeAtX9+oCXs=,tag:mLEPTapn7OM3bm5c9TKB0A==,type:str]
bookstack_app_key: ENC[AES256_GCM,data:N79JVlQSoVCXOsIHCxd19HFm6LkrYyXQu/xWenEdUlQWqwZEi3PuHXG7fQgvzQY4KI7S,iv:cd2l2eOv+wAJ5sih3YhHgQTdy1qrvaIsoHcywOnHuYM=,tag:5QvCHlQX8wUz3tI2NXl+8A==,type:str]
bookstack_db: ENC[AES256_GCM,data:m8fGgAfmJu1rEaxmTVH4FfBhyiU=,iv:OnBT/6sp9zmcJ1+kBmdmvaE630hifxBpvKnu3XrVXcE=,tag:SSVQcYkAymlbFOnf0MB6KA==,type:str]
mariadb_root_password: ENC[AES256_GCM,data:p965ZhFQqqX+Ub1yhgklVYlBH6A=,iv:qC5WwTvZGvlbAkYiv35xHizMYAnP0V0Vw79EkvL32wQ=,tag:gOJQvHeOC9turFKOMQ9DNg==,type:str]
openproject:
secret-key-base: ENC[AES256_GCM,data:luTuUtxL/SGx6O10y9cRiAzJHw==,iv:8qVJm+obsHr9eV0h+jdpsreeFGxEM+UFZHHiIUUPs6w=,tag:+zpjhKoIiNNSSYxe1QkQ7Q==,type:str]
focalboard:
database: ENC[AES256_GCM,data:GDxYdkVV+tl3qHxWMMoetmMnLnY=,iv:JujgNPyUEHCmD/yW3UKCTj9GTk9a7EkvUiyFLF4sF8A=,tag:46YZ7AthpiiaX69aN9a3Bg==,type:str]
offen:
secret: ENC[AES256_GCM,data:sH2siPc/QH1O2M7ZlJwqhqlHRIeLIG9r,iv:eD29ALx2ji0rm1t9j6RulTZT3f6VLK7dxpPOze3qDKA=,tag:zqJTgT2UeA/ecBS4VremUw==,type:str]
smtp-token: ENC[AES256_GCM,data:ZTfe65g3JykPvG2l0AN8UQ==,iv:GTruGo/vcP+imfJyqB3NX9ic8dz5jvTEh6SF+OeqMDM=,tag:kgwd59pG/WUt8OAaVzi39Q==,type:str]
traefik:
oauth2-client-secret: ENC[AES256_GCM,data:p7/6OsN2ytBj8mQiK0YL7J6NYLtMHOXIIs/6+bIDpsU=,iv:k6jLZifJEFLYKSFMkyn/kA7iBE+EFB8O/3/3fyTh1SY=,tag:6s49O2+tdlZoXyAGEamuMQ==,type:str]
oauth2-plugin-secret: ENC[AES256_GCM,data:sArqwKHAdW35o5kD7DGfXSYCXFUXqvKQdoVnXutsNLw=,iv:qWf597QS3BqkVQkeAb99HbpDB0kUhdD+qKdpUPZEB0o=,tag:vXnb93npaklItWkMZ+/M9Q==,type:str]
protonvpn:
private_key: ENC[AES256_GCM,data:41pfbR1klj1F24v3HlCCA4ofW2sCEnyE5TH8iX4Ug8D+kmwstTaj5RG2Zz8=,iv:P6XyQnDVoOmdkP8ilBR9DyfqPZA6GsQ6VUwY/tSGhx4=,tag:Bzgdv29lbk/gYlADPZMGVA==,type:str]
deploy-key:
mcp: ENC[AES256_GCM,data:eQcX8xdz5qZ6nU8ISOvZo+ZtP4Z/ePd+/ZZReX1BKvTUqGQPPFxConbLMwFzvzpD6xAUbA1MLkcR/bT98QbNx6LJYlhbofuDUg2DI79RB0fcrAcj/wUV0YPhmgofUdYYDaimH5A2PSvtmKfB3CtKKuA5HNeLymoXeLEpFzbckkGhzPee/CHiUmxayogp6za6btsDJsiT8hdHbrzyD2S6fhMJrzX+PlRzT32M/6eaFuFWE8EUO1gbkRlNfKPXw/EM2GXWJfR4qXfN2YKIKigqrtlAAoxnrUbp5EBrn/hGHS2ZYZXeRUFr3avFjcI0bLX423PWRHAylfQCPxgYVEtbcRv11CAFmq4rfFl0ZdvnAKbTLNmWcrQNijBATZPaAdQzgKPDHs8pwPUFR9Tcg8pZNbzw0mK9kPolniAOL2PBKUHv6LP/uEkB1E6Pxc7yms0kGpeJyo7hrFVOiVAckCey+SI9dpbJMSB3md070I1xk6Ik7PywrWh2QDeUtOU1U28UkYgnJ/9MJelWsNlUX9SR,iv:oCNeanaV/7UZ3dhmq4ZmJUZ5hb61AnHpHCfskM2Jsm8=,tag:F2uJKN5beM/rfiBMSyUP7w==,type:str]
matrix:
syncv3:
db-password: ENC[AES256_GCM,data:N/IO0k/2BZpmaDTbKZmSgZNzmdk=,iv:p0jGjJ9mTCh5FPM/Oe1vxusYvlyg14UeggE5ynpDVL8=,tag:tZbddwxJf6wSH6L1QRUQVg==,type:str]
secret: ENC[AES256_GCM,data:KZjYxjUxGgkY1I5jGF7XMEhkHK+khDaQzxugoKxpLsROmVs722tFfbUAxhp71llam55gy9+eUWGxIPlmvOySlw==,iv:OoThGcT08Z11kpnAMQ7w59wj5JheNFGEk1jfFENsmy0=,tag:8EeKT7dh2/a52Amf6LsL1w==,type:str]
blazestar-registration-token: ENC[AES256_GCM,data:TB3bR+E4H4c2l9pRcEOAZr35+vBVaJUcuCs9K0Pjd0aW+M35x5LgZ8+F99Y=,iv:e28sie6LSI5UX41BPb+yN+3n+Yw9Ssfsqe4zppwbPkU=,tag:cQPgZcRFbYSiZnmPVtZxHg==,type:str]
tandoor:
secret_key: ENC[AES256_GCM,data:nl7S2fS1wENrT5k2iZfLEAGc99lCUktgwR5L5KklF69BNVKQkW1rUgb3aIv50VpXZa+3OxV/vdPmG9NhKMy96I5+Dno=,iv:FFyGQBARz0B5zrONZELzUMsOIn8TWrDNTKGsAHPlS7w=,tag:/c4MnDfLXQpBZDqVxZ0DTg==,type:str]
immich:
database: ENC[AES256_GCM,data:1fjOQsLZcq/T+r+AkzomWwCQWw==,iv:c4pn2rC+3xkxLJ7uAdhnTE6zVTRQkfuKK3tjUyDhfAw=,tag:kvk7DOv6X/+RDxfPxVak7w==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1yvdzvuvu5wqztcx6ll2xk6x547uuyqy735tjjdd7zftkz53jsf9qf5ahue
enc: |
@@ -28,8 +47,7 @@ sops:
by9aNFY4dXNxaWxnTXFTQS9reHhuQWMKh5rZ93nFtBV9EpFVRp+E+GXZ6xzVy2Jw
vFh4deGcAb60q4odSaeWfk1Dr7L9Ua69oK9omjbCNUt+P7Kwlfca7Q==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-04-03T19:04:17Z"
mac: ENC[AES256_GCM,data:DEUuXrCl3OXJ9NbfLoxHIND5+m7enHNDbuLE2jS8nvZCpKm83YoXwp0RhIFA725wJnBej26HLkovCi7V/4s5NrrfT9sPHGNBMSHB0AAcwu3Dmo6G2PBKvAWZTxXmiIXGx8vSvWNbLrp3vTV8jjTpfbuMvOiuxayKfn6esKI9T2o=,iv:zUfbL753Uvzg6WW4kwI8swmpWHIQ/IpCyYSsLptVDG4=,tag:XZy8jNZYYcqspd6zptH3pQ==,type:str]
pgp: []
lastmodified: "2026-02-25T00:28:13Z"
mac: ENC[AES256_GCM,data:hDmqObrtfoVkQqz8JPkqlyXMbiuyBophjdZNLvTFrZw3pAVNCuzsH4zxFBOaxJttkzLc65DWDHDeEIBY5YZam1GLFFXUQ5E3Dxno7hnyzOoM2ipgDTOacI0gbKJAWgGUF3LNDdqVoREA9LC91LoNUJoNmzpTSFtuLb7ORuwCrH4=,iv:8+W3n1Cr6woEiPU9ECaMYM64HNmFHr2AIw6UohCJi00=,tag:7drkZiPAUHaEx5PagXA9JQ==,type:str]
unencrypted_suffix: _unencrypted
version: 3.9.4
version: 3.11.0

View File

@@ -0,0 +1,5 @@
{ ... }:
{
programs.adb.enable = true;
users.users.drew.extraGroups = [ "adbusers" ];
}

22
system/features/audio.nix Normal file
View File

@@ -0,0 +1,22 @@
{ ... }:
{
# RealtimeKit hands out realtime scheduling priority to user processes on
# demand, e.g. audio
security.rtkit.enable = true;
# Enable sound with pipewire.
services.pulseaudio = {
enable = false;
daemon.config = {
exit-idle-time = -1;
};
};
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
# If you want to use JACK applications, uncomment this
#jack.enable = true;
};
}

View File

@@ -0,0 +1,26 @@
{ ... }:
{
virtualisation = {
docker = {
enable = true;
# rootless = {
# enable = true;
# setSocketVariable = true;
# };
};
# Do not use Podman in Wayland/Hyperland. It will crash the session. Very annoying.
# podman.enable = true;
};
hardware.nvidia-container-toolkit.enable = true;
home-manager.users.drew =
{ ... }:
{
# Add the path to the docker socket to the environment.
programs.zsh.envExtra = ''
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
'';
};
}

View File

@@ -0,0 +1,12 @@
{ pkgs, ... }:
{
services.flatpak.enable = true;
systemd.services.flatpak-repo = {
wantedBy = [ "multi-user.target" ];
path = [ pkgs.flatpak ];
script = ''
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
'';
};
}

8
system/features/gc.nix Normal file
View File

@@ -0,0 +1,8 @@
{ ... }: {
# Automatic
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
}

View File

@@ -0,0 +1,50 @@
{ config, lib, ... }:
{
options =
with lib;
with types;
{
graphics = {
enable = mkEnableOption "graphics support";
driverChannel = mkOption {
type = str;
# Default to production because I often want new features, but I don't want bleeding edge.
default = "production";
description = "Driver channel to use (in order of oldest to newest): stable, beta, latest";
};
};
};
config = lib.mkIf config.graphics.enable {
# Graphics settings
hardware.graphics = {
enable = true;
enable32Bit = true;
};
services.xserver.videoDrivers = [ "nvidia" ];
hardware.nvidia = {
package = config.boot.kernelPackages.nvidiaPackages."${config.graphics.driverChannel}";
modesetting.enable = true;
# Nvidia power management. Experimental, and can cause sleep/suspend to fail.
# Enable this if you have graphical corruption issues or application crashes after waking
# up from sleep. This fixes it by saving the entire VRAM memory to /tmp/ instead
# of just the bare essentials.
powerManagement.enable = true;
# Fine-grained power management for PRIME. Turns off GPU when not in use.
# Experimental and only works on modern Nvidia GPUs (Turing or newer).
# Requires offload to be enabled.
# powerManagement.finegrained = false;
# Use the open-source driver?
open = false;
# Enable the nvidia-settings menu?
nvidiaSettings = true;
};
};
}

37
system/features/gui.nix Normal file
View File

@@ -0,0 +1,37 @@
{ ... }: {
# Enable the X11 windowing system and a display manager
services.xserver = {
enable = true;
displayManager.gdm = {
enable = true;
wayland = true;
};
# displayManager.sddm = {
# enable = true;
# wayland.enable = true;
# };
# Configure keymap in X11
xkb = {
layout = "us";
variant = "";
};
};
# services.displayManager.ly.enable = true;
# Enable Hyprland so it shows up in the menu
programs.hyprland = {
enable = true;
withUWSM = true;
xwayland.enable = true;
};
programs.sway = {
enable = true;
xwayland.enable = true;
wrapperFeatures = {
gtk = true;
base = true;
};
};
}

View File

@@ -0,0 +1,21 @@
{ pkgs, ... }:
{
services.printing = {
enable = true;
drivers = [ pkgs.brlaser ];
};
hardware.printers = {
ensurePrinters = [
{
name = "Brother_HL-L2370DW_series";
location = "Home";
deviceUri = "dnssd://Brother%20HL-L2370DW%20series._ipp._tcp.local/?uuid=e3248000-80ce-11db-8000-3c2af4f28c38";
model = "drv:///brlaser.drv/brl2370d.ppd";
ppdOptions = {
PageSize = "Letter";
};
}
];
ensureDefaultPrinter = "Brother_HL-L2370DW_series";
};
}

View File

@@ -0,0 +1,127 @@
{ config, lib, ... }:
{
options =
with lib;
with types;
{
virtualisation.web-containers = {
enable = mkEnableOption "web containers";
containers = mkOption {
type = lazyAttrsOf (submodule {
options =
let
strOpt = mkOption { type = str; };
intOpt = mkOption { type = int; };
boolOpt = mkOption {
type = bool;
default = false;
};
strList = mkOption {
type = listOf str;
default = [ ];
};
attrOpt = mkOption {
type = attrsOf str;
default = { };
};
in
{
image = strOpt;
hostname = strOpt;
port = intOpt;
homepageOpts = attrOpt;
dependsOn = strList;
domain = strOpt;
volumes = strList;
environment = attrOpt;
environmentFiles = strList;
public = boolOpt;
user = mkOption {
type = nullOr str;
default = null;
};
extraOptions = strList;
oauthProxy = boolOpt;
extraLabels = attrOpt;
};
});
default = { };
description = "";
};
};
};
config = {
virtualisation.oci-containers.containers = lib.mkIf config.virtualisation.web-containers.enable (
let
hostRule = host: domain: "Host(`${host}.${domain}`)";
localNet = "192.168.0.0/16";
dockerNet = "10.88.0.0/16";
localNetRule = "(ClientIP(`${localNet}`) || ClientIP(`${dockerNet}`))";
localHostRule = host: domain: "${localNetRule} && ${hostRule host domain}";
mkContainer =
key:
{
image,
hostname,
port,
homepageOpts,
dependsOn,
domain,
volumes,
environment,
environmentFiles,
public,
user,
extraOptions,
oauthProxy,
extraLabels,
}:
let
fqn = "${hostname}.${domain}";
serviceName = builtins.replaceStrings [ "." ] [ "-" ] fqn;
routerRule = if public then hostRule hostname domain else localHostRule hostname domain;
homepageLabels =
if homepageOpts == { } then
{ }
else
{
"homepage.group" = "${homepageOpts.group}";
"homepage.name" = "${homepageOpts.name}";
"homepage.icon" = "${homepageOpts.icon}";
"homepage.href" = "https://${fqn}";
"homepage.description" = "${homepageOpts.description}";
};
oauthLabels =
if oauthProxy then
{ "traefik.http.routers.${serviceName}.middlewares" = "oidc-auth@file"; }
else
{ };
in
{
inherit
image
dependsOn
volumes
environment
environmentFiles
user
extraOptions
;
autoStart = true;
labels = {
"traefik.enable" = "true";
"traefik.http.routers.${serviceName}.rule" = "${routerRule}";
"traefik.http.routers.${serviceName}.service" = "${serviceName}";
"traefik.http.routers.${serviceName}.entrypoints" = "web,websecure";
"traefik.http.services.${serviceName}.loadbalancer.server.port" = "${toString port}";
}
// oauthLabels
// homepageLabels
// extraLabels;
};
in
builtins.mapAttrs mkContainer config.virtualisation.web-containers.containers
);
};
}

View File

@@ -4,15 +4,10 @@
{
pkgs,
inputs,
...
}:
{
imports = [
./qmk.nix
];
networking.hostName = "altair"; # Define your hostname.
# Configure network proxy if necessary
@@ -42,15 +37,9 @@
LC_TIME = "en_US.UTF-8";
};
# Enable the X11 windowing system.
# You can disable this if you're only using the Wayland session.
services.xserver.enable = true;
services.displayManager.sddm = {
enable = true;
theme = "sddm-astronaut-theme";
};
# Enable Ozone Wayland support in chromium and electron apps.
# https://nixos.wiki/wiki/Wayland
environment.sessionVariables.NIXOS_OZONE_WL = "1";
# Unlock the default keyring on login to hyprland
security.pam.services.hyprland.enableGnomeKeyring = true;
@@ -63,21 +52,6 @@
'';
};
# Enable Hyprland so it shows up in the menu
programs.hyprland = {
enable = true;
withUWSM = true;
package = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.hyprland;
portalPackage =
inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.xdg-desktop-portal-hyprland;
};
# Configure keymap in X11
services.xserver.xkb = {
layout = "us";
variant = "";
};
# Enable CUPS to print documents.
services.printing = {
enable = true;
@@ -96,7 +70,7 @@
services.gnome.gnome-keyring.enable = true;
# Enable sound with pipewire.
services.pulseaudio.enable = false;
hardware.pulseaudio.enable = false;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
@@ -114,16 +88,10 @@
# Enable touchpad support (enabled default in most desktopManager).
# services.xserver.libinput.enable = true;
# Allow unfree packages
nixpkgs.config = {
allowUnfree = true;
};
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
vim
sddm-astronaut
];
# Some programs need SUID wrappers, can be configured further or are

View File

@@ -1,13 +1,20 @@
{ nixpkgs, inputs, ... }:
nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
{ ... }:
{
imports = [
./configuration.nix
./hardware-configuration.nix
./qmk.nix
../../authorized-keys.nix
inputs.home-manager.nixosModules.home-manager
{
../../features/audio.nix
../../features/gc.nix
../../features/gui.nix
../../features/container-dev.nix
../../features/android-dev.nix
../../features/flatpak.nix
];
nixpkgs.config.allowUnfree = true;
home-manager.users.drew =
{ ... }:
{
@@ -15,14 +22,4 @@ nixpkgs.lib.nixosSystem {
./drew.nix
];
};
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = {
inherit inputs;
};
}
];
specialArgs = {
inherit inputs;
};
}

View File

@@ -1,4 +1,4 @@
{ pkgs, ... }:
{ ... }:
let
monitors = [
"DP-1"
@@ -8,17 +8,31 @@ in
{
imports =
map (x: ../../../home-manager + x) [
"/features/astronomy.nix"
"/features/chat.nix"
"/features/development/development.nix"
"/features/development/docker.nix"
"/features/development/haskell.nix"
"/features/development/markdown.nix"
"/features/development/typescript.nix"
"/features/development/vscode.nix"
"/features/eww"
"/features/gaming.nix"
"/features/image-editing.nix"
"/features/linux-desktop.nix"
"/features/notes.nix"
"/features/eww"
"/features/3d-printing.nix"
]
++ [
(import ../../../home-manager/features/wallpaper.nix monitors)
];
# This config file is needed for nix shell to allow unfree programs. I'm not
# sure why this isn't a home-manager option.
home.file.".config/nixpkgs/config.nix".text = ''
{ allowUnfree = true; }
'';
home.stateVersion = "24.11";
home.username = "drew";
@@ -29,17 +43,16 @@ in
userEmail = "drew.haven@gmail.com";
};
home.packages = with pkgs; [
# Applications
discord
signal-desktop
obsidian
firefox
];
wayland.windowManager.hyprland.settings = {
exec-once = [
# Set up eww here because it's based on the monitor configuration
# Eww is idempotent, so it's fine to just run it on every reload to make sure things are open
wayland.windowManager.hyprland.settings.execr-once = [
"eww open-many primary-statusbar secondary-statusbar launcher"
"sleep 2 && eww open-many primary-statusbar secondary-statusbar"
# Set DP-2 as the primary monitor, otherwise it defaults to DP-1 because it's first in the list.
"xrandr --output DP-2 --primary"
];
windowrulev2 = [
# Rofi doesn't center properly when I have the two asymetric monitors, so we need hyprland to manage it.
"center, class:Rofi"
];
};
}

View File

@@ -13,10 +13,14 @@
(modulesPath + "/installer/scan/not-detected.nix")
];
# Bootloader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot = {
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
boot.initrd.availableKernelModules = [
initrd = {
availableKernelModules = [
"xhci_pci"
"ahci"
"nvme"
@@ -24,16 +28,19 @@
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
kernelModules = [ ];
};
kernelModules = [ "kvm-intel" ];
extraModulePackages = [ ];
};
fileSystems."/" = {
fileSystems = {
"/" = {
device = "/dev/disk/by-uuid/343c0ac5-3973-49b3-964a-6ad90c36b89c";
fsType = "ext4";
};
fileSystems."/boot" = {
"/boot" = {
device = "/dev/disk/by-uuid/5F99-043D";
fsType = "vfat";
options = [
@@ -42,10 +49,11 @@
];
};
fileSystems."/home" = {
"/home" = {
device = "/dev/disk/by-uuid/28f4fb41-9414-4504-a767-c2e8bf5eb2c8";
fsType = "ext4";
};
};
swapDevices = [ ];
@@ -58,17 +66,26 @@
# networking.interfaces.wlo1.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
# Graphics settings
hardware.graphics = {
enable = true;
enable32Bit = true;
};
services.xserver.videoDrivers = [ "nvidia" ];
hardware.nvidia = {
hardware = {
cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
graphics = {
enable = true;
enable32Bit = true;
};
nvidia = {
# Other options include:
# stable - Current stable
# production - Same as stable
# latest - Bleeding edge
# beta - latest beta
#
# See https://nixos.wiki/wiki/Nvidia
#
# Current versions can be found in https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/os-specific/linux/nvidia-x11/default.nix
#
package = config.boot.kernelPackages.nvidiaPackages.beta;
modesetting.enable = true;
@@ -90,6 +107,7 @@
# Enable the nvidia-settings menu?
nvidiaSettings = true;
};
};
# Add a udev rule to prevent the mouse from waking the system. Note that it
# has two entries depending on whether it's plugged in or not.

View File

@@ -1,4 +1,4 @@
{ config, pkgs, ... }:
{ pkgs, ... }:
{
imports = [
./vars.nix
@@ -16,9 +16,6 @@
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# Set the kernel to be compatible with ZFS
boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages;
networking.hostName = "mcp"; # Define your hostname.
networking.hostId = "5e292f2d"; # Define a host ID for ZFS with `head -c 8 /etc/machine-id`
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
@@ -62,6 +59,7 @@
"networkmanager"
"wheel"
"docker-registry"
"docker"
];
shell = pkgs.zsh;
# Enable linger so that systemd services run for this user are started and
@@ -96,7 +94,8 @@
port = 5000;
openFirewall = true;
# Bind to the podman network so Traefik can route to it.
# Note that it may fail to start if this network has not been created yet.
# Note that it may fail to start if this network has not been created yet,
# so this has to be manually restarted when the system boots.
listenAddress = "10.88.0.1";
};
@@ -107,8 +106,10 @@
enabledCollectors = [ "systemd" ];
port = 9002;
# Open the firewall, but only listen on the internal address
# TODO: Add some form authentication
openFirewall = true;
# Bind to the podman network so Traefik can route to it.
# Note that it may fail to start if this network has not been created yet,
# so this has to be manually restarted when the system boots.
listenAddress = "10.88.0.1";
};
};

View File

@@ -1,29 +1,100 @@
# Started from https://nixos.wiki/wiki/Podman
{ config, pkgs, ... }:
{
config,
pkgs,
lib,
...
}:
{
# Additional configuration
imports = [
./containers/bookstack.nix
./containers/email.nix
./containers/havenisms.com
./containers/blazestar.net
# Docker containers
./containers/dm-companion.nix
./containers/freshrss.nix
./containers/gitea.nix
./containers/goatcounter.nix
./containers/grafana.nix
./containers/jobhunt.nix
# ./containers/jobhunt.nix
./containers/mariadb.nix
./containers/media-system.nix
./containers/nextcloud.nix
./containers/openproject.nix
./containers/prometheus.nix
# ./containers/offen.nix
./containers/pocket-id.nix
./containers/prometheus.nix
./containers/public-homepage.nix
./containers/searxng.nix
./containers/shared-postgres.nix
./containers/synapse.nix
# ./containers/timetagger.nix
./containers/traefik.nix
./containers/users.nix
# NixOS Containers
./static-site-hooks.nix
];
options.local = with lib; {
container-backend = mkOption {
type = with types; uniq str;
default = "docker";
example = "docker";
description = "Which backend to use for containers: docker or podman";
};
container-socket = mkOption {
type = with types; uniq str;
default = "/var/run/docker.sock";
example = "/var/run/docker.sock";
description = "Path to the container management deamon's socket.";
};
};
config = {
# local = {
# container-backend = "docker";
# container-socket = "/var/run/docker.sock";
# };
local = {
container-backend = "podman";
container-socket = "/var/run/podman/podman.sock";
};
# Enable common container config files in /etc/containers
virtualisation.containers.enable = true;
virtualisation = {
podman = {
containers.enable = true;
oci-containers.backend = config.local.container-backend;
docker = lib.mkIf (config.local.container-backend == "docker") {
enable = true;
# Enable rootless so that I can run containers as other users for security.
rootless = {
enable = true;
# Set this to make the default DOCKER_HOST be the rootless version for normal users.
setSocketVariable = true;
daemon = {
settings = {
default-address-pools = [
{
base = "10.88.0.0/16";
size = 24;
}
];
};
};
};
daemon = {
settings = {
default-address-pools = [
{
base = "10.88.0.0/16";
size = 24;
}
];
};
};
};
podman = lib.mkIf (config.local.container-backend == "podman") {
enable = true;
# Create a `docker` alias for podman, to use it as a drop-in replacement
@@ -39,258 +110,17 @@
# Useful other development tools
environment.systemPackages = with pkgs; [
dive # look into docker image layers
podman-tui # status of containers in the terminal
docker-compose # start group of containers for dev
#podman-compose # start group of containers for dev
];
users.groups = {
git = { };
timetagger = { };
};
users.users = {
gitea = {
uid = 2001;
isSystemUser = true;
description = "System User for Gitea";
extraGroups = [ "git" ];
group = "git";
};
timetagger = {
uid = 2002;
isSystemUser = true;
description = "System User for TimeTagger";
group = "timetagger";
};
};
virtualisation.oci-containers.backend = "podman";
virtualisation.oci-containers.containers =
let
inherit (import ./containers/lib.nix config)
hostRuleHavenisms
localHostRuleHavenisms
havenisms;
havenisms
;
in
{
jellyfin = {
image = "lscr.io/linuxserver/jellyfin";
autoStart = true;
extraOptions = [
"--device=/dev/dri:/dev/dri"
"-l=traefik.enable=true"
"-l=traefik.http.routers.jellyfin.rule=${hostRuleHavenisms "jellyfin"}"
"-l=traefik.http.services.jellyfin.loadbalancer.server.port=8096"
"-l=homepage.group=Apps"
"-l=homepage.name=Jellyfin"
"-l=homepage.icon=jellyfin.svg"
"-l=homepage.href=https://jellyfin.${havenisms}"
"-l=homepage.description=Media player"
"-l=homepage.widget.type=jellyfin"
"-l=homepage.widget.key={{HOMEPAGE_FILE_JELLYFIN_KEY}}"
"-l=homepage.widget.url=http://jellyfin:8096"
"-l=homepage.widget.enableBlocks=true"
];
volumes = [
"/tank/media/collection:/data"
"/tank/config/jellyfin:/config"
];
# environment = {
# TZ = vars.timeZone;
# PUID = "994";
# UMASK = "002";
# GUID = "993";
# };
};
deluge = {
image = "linuxserver/deluge:latest";
autoStart = true;
dependsOn = [
"gluetun"
];
extraOptions = [
"--network=container:gluetun"
"-l=homepage.group=Arr"
"-l=homepage.name=Deluge"
"-l=homepage.icon=deluge.svg"
"-l=homepage.href=https://deluge.${havenisms}"
"-l=homepage.description=Torrent client"
"-l=homepage.widget.type=deluge"
"-l=homepage.widget.password={{HOMEPAGE_FILE_DELUGE_PASSWORD}}"
"-l=homepage.widget.url=http://gluetun:8112"
];
volumes = [
"/tank/media:/data"
"/tank/config/deluge:/config"
];
};
qbittorrent = {
image = "linuxserver/qbittorrent:latest";
autoStart = true;
dependsOn = [
"gluetun"
];
extraOptions = [
"--network=container:gluetun"
"-l=homepage.group=Arr"
"-l=homepage.name=qBitTorrent"
"-l=homepage.icon=qbittorrent.svg"
"-l=homepage.href=https://torrents.${havenisms}"
"-l=homepage.description=Torrent client"
"-l=homepage.widget.type=qbittorrent"
"-l=homepage.widget.url=http://torrents.${havenisms}"
];
volumes = [
"/tank/media/Downloads:/downloads"
"/tank/config/qbittorrent:/config"
];
environment = {
PUID = "911";
PGID = "911";
UMASK = "002";
};
};
gluetun = {
image = "qmcgaw/gluetun:latest";
autoStart = true;
extraOptions = [
# add network admin capability.
"--cap-add=NET_ADMIN"
"--device=/dev/net/tun:/dev/net/tun"
"-l=traefik.enable=true"
"-l=traefik.http.routers.torrents.rule=${localHostRuleHavenisms "torrents"}"
"-l=traefik.http.routers.torrents.service=torrents"
"-l=traefik.http.services.torrents.loadbalancer.server.port=8080"
"-l=homepage.group=Infra"
"-l=homepage.name=GlueTun"
"-l=homepage.icon=gluetun.svg"
"-l=homepage.href=https://torrents.${havenisms}"
"-l=homepage.description=VPN killswitch"
"-l=homepage.widget.type=gluetun"
"-l=homepage.widget.url=http://gluetun:8000"
];
ports = [
"127.0.0.1:8083:8000"
];
environmentFiles = [
"/tank/config/gluetun/vpn.env"
];
environment = {
VPN_SERVICE_PROVIDER = "protonvpn";
UMASK = "002";
};
};
prowlarr = {
image = "lscr.io/linuxserver/prowlarr";
autoStart = true;
extraOptions = [
"-l=traefik.enable=true"
"-l=traefik.http.routers.prowlarr.rule=${localHostRuleHavenisms "prowlarr"}"
"-l=traefik.http.services.prowlarr.loadbalancer.server.port=9696"
"-l=homepage.group=Arr"
"-l=homepage.name=Prowlarr"
"-l=homepage.icon=prowlarr.svg"
"-l=homepage.href=https://prowlarr.${havenisms}"
"-l=homepage.description=Torrent indexer"
];
volumes = [
"/tank/config/prowlarr:/config"
];
environment = {
UMASK = "002";
};
};
# Currently broken and doesn't work. :(
# flaresolverr = {
# image = "ghcr.io/flaresolverr/flaresolverr:latest";
# autoStart = true;
# extraOptions = [
# "-l=homepage.group=Infra"
# "-l=homepage.name=FlareSolverr"
# "-l=homepage.icon=flaresolverr.svg"
# "-l=homepage.href=https://flaresolverr.${domain}"
# "-l=homepage.description=Cloudflare bypass"
# ];
# volumes = [
# "/tank/config/flaresolverr:/config"
# ];
# environment = {
# UMASK = "002";
# };
# };
radarr = {
image = "lscr.io/linuxserver/radarr";
autoStart = true;
extraOptions = [
"-l=traefik.enable=true"
"-l=traefik.http.routers.radarr.rule=${localHostRuleHavenisms "radarr"}"
"-l=traefik.http.services.radarr.loadbalancer.server.port=7878"
"-l=homepage.group=Arr"
"-l=homepage.name=Radarr"
"-l=homepage.icon=radarr.svg"
"-l=homepage.href=https://radarr.${havenisms}"
"-l=homepage.description=Movie acquisition"
"-l=homepage.widget.type=radarr"
"-l=homepage.widget.url=http://radarr:7878"
"-l=homepage.widget.key={{HOMEPAGE_FILE_RADARR_KEY}}"
];
volumes = [
"/tank/media:/data"
"/tank/config/radarr:/config"
];
environment = {
UMASK = "002";
};
};
sonarr = {
image = "lscr.io/linuxserver/sonarr";
autoStart = true;
extraOptions = [
"-l=traefik.enable=true"
"-l=traefik.http.routers.sonarr.rule=${localHostRuleHavenisms "sonarr"}"
"-l=traefik.http.services.sonarr.loadbalancer.server.port=8989"
"-l=homepage.group=Arr"
"-l=homepage.name=Sonarr"
"-l=homepage.icon=sonarr.svg"
"-l=homepage.href=https://sonarr.${havenisms}"
"-l=homepage.description=Show acquisition"
"-l=homepage.widget.type=sonarr"
"-l=homepage.widget.url=http://sonarr:8989"
"-l=homepage.widget.key={{HOMEPAGE_FILE_SONARR_KEY}}"
];
volumes = [
"/tank/media:/data"
"/tank/config/sonarr:/config"
];
environment = {
UMASK = "002";
};
};
readarr = {
# The Linuxserver version of this image doesn't have a latest tag. Odd.
image = "lscr.io/linuxserver/readarr:develop";
autoStart = true;
extraOptions = [
"-l=traefik.enable=true"
"-l=traefik.http.routers.readarr.rule=${localHostRuleHavenisms "readarr"}"
"-l=traefik.http.services.readarr.loadbalancer.server.port=8787"
"-l=homepage.group=Arr"
"-l=homepage.name=Readarr"
"-l=homepage.icon=readarr.svg"
"-l=homepage.href=https://readarr.${havenisms}"
"-l=homepage.description=E-book acquisition"
"-l=homepage.widget.type=readarr"
"-l=homepage.widget.url=http://readarr.havenisms.com:8787"
"-l=homepage.widget.key={{HOMEPAGE_FILE_READARR_KEY}}"
];
volumes = [
"/tank/media:/data"
"/tank/config/readarr:/config"
];
environment = {
UMASK = "002";
};
};
homepage = {
image = "ghcr.io/gethomepage/homepage:latest";
autoStart = true;
@@ -305,7 +135,7 @@
"/tank/secrets/jellyfin.key:/app/config/secrets/jellyfin.key"
"/tank/secrets/radarr.key:/app/config/secrets/radarr.key"
"/tank/secrets/sonarr.key:/app/config/secrets/sonarr.key"
"/var/run/podman/podman.sock:/var/run/docker.sock:ro"
"${config.local.container-socket}:/var/run/docker.sock:ro"
];
environment = {
HOMEPAGE_FILE_JELLYFIN_KEY = "/app/config/secrets/jellyfin.key";
@@ -330,10 +160,10 @@
"-l=homepage.widget.type=scrutiny"
"-l=homepage.widget.url=http://scrutiny:8080"
"--cap-add=SYS_RAWIO"
"--device=/dev/sda:/dev/sda"
"--device=/dev/sdb:/dev/sdb"
"--device=/dev/sdc:/dev/sdc"
"--device=/dev/sdd:/dev/sdd"
"--device=/dev/disk/by-id/wwn-0x5000cca26fca1aed:/dev/disk/by-id/wwn-0x5000cca26fca1aed"
"--device=/dev/disk/by-id/wwn-0x5000cca26fef696c:/dev/disk/by-id/wwm-0x5000cca26fef696c"
"--device=/dev/disk/by-id/wwn-0x5000cca270db1d0e:/dev/disk/by-id/wwn-0x5000cca270db1d0e"
# "--device=/dev/sdd:/dev/sdd" Removing this one while the disk is down
];
volumes = [
"/run/udev:/run/udev:ro"
@@ -349,4 +179,5 @@
];
};
};
};
}

View File

@@ -0,0 +1,104 @@
{ config, ... }:
let
inherit (import ../lib.nix config) mkContainer blazestar;
matrixHost = "matrix";
serviceName = "matrix-blazestar-net";
dbPath = "/var/lib/matrix";
port = 8448;
in
{
sops.secrets = {
"matrix/blazestar-registration-token" = {
restartUnits = [ "${config.local.container-backend}-matrix-blazestar-net.service" ];
};
};
sops.templates."matrix-blazestar-net.env".content = ''
TUWUNEL_REGISTRATION_TOKEN=${config.sops.placeholder."matrix/blazestar-registration-token"}
'';
# This isn't using any of my usual helpers because I wanted to set a custom
# serviceName in Traefik that is different from the hostname to avoid
# conflicts with the havenisms.com server.
virtualisation.oci-containers.containers."${serviceName}" = {
# The 1.1.0 version has an issue with the compression being incorrectly tagged.
# See: https://github.com/matrix-construct/tuwunel/issues/79
image = "ghcr.io/matrix-construct/tuwunel:v1.0.0-release-all-x86_64-linux-gnu";
autoStart = true;
volumes = [
"matrix-blazestar-net-db:${dbPath}"
];
environment = {
TUWUNEL_PORT = toString port;
TUWUNEL_ADDRESS = "0.0.0.0"; # It'll bind to localhost by default with Podman
TUWUNEL_SERVER_NAME = "blazestar.net";
TUWUNEL_ALLOW_REGISTRATION = "true";
TUWUNEL_ALLOW_CHECK_FOR_UPDATES = "true";
TUWUNEL_ALLOW_FEDERATION = "true";
TUWUNEL_DATABASE_BACKEND = "rocksdb";
TUWUNEL_DATABASE_PATH = dbPath;
TUWUNEL_WELL_KNOWN = ''
{
client=https://${matrixHost}.blazestar.net,
server=${matrixHost}.blazestar.net:443
}
'';
TUWUNEL_TRUSTED_SERVERS = ''["matrix.org", "chat.havenisms.com"]'';
};
environmentFiles = [
config.sops.templates."matrix-blazestar-net.env".path
];
labels = {
"traefik.enable" = "true";
"traefik.http.routers.${serviceName}.rule" = "Host(`${matrixHost}.${blazestar}`)";
"traefik.http.services.${serviceName}.loadbalancer.server.port" = "${toString port}";
# Redirect well-known requests to this host.
"traefik.http.routers.${matrixHost}-blazestar-net-well-known.rule" =
"Host(`blazestar.net`) && PathPrefix(`/.well-known/matrix`)";
"traefik.http.routers.${matrixHost}-blazestar-net-well-known.service" = serviceName;
};
};
# virtualisation.oci-containers.containers.matrix-blazestar-net =
# mkContainer {
# image = "registry.gitlab.com/famedly/conduit/matrix-conduit:latest";
# hostName = hostname;
# domain = blazestar;
# port = port;
# ports = [
# "8449:6167"
# ];
# volumes = [
# "chat-blazestar-net-db:${dbPath}"
# ];
# environment = {
# CONDUIT_PORT = "6167";
# CONDUIT_SERVER_NAME = "blazestar.net";
# CONDUIT_ALLOW_REGISTRATION = "true";
# CONDUIT_DATABASE_BACKEND = "rocksdb";
# CONDUIT_DATABASE_PATH = dbPath;
# CONDUIT_ALLOW_CHECK_FOR_UPDATES = "true";
# CONDUIT_ALLOW_FEDERATION = "true";
# CONDUIT_MAX_REQUEST_SIZE = "20000000";
# CONDUIT_TRUSTED_SERVERS = "[\"matrix.org\"]";
# CONDUIT_MAX_CONCURRENT_REQUESTS = "100";
# CONDUIT_WELL_KNOWN_CLIENT = "https://${hostname}.blazestar.net";
# CONDUIT_WELL_KNOWN_SERVER = "${hostname}.blazestar.net:443";
# CONDUIT_CONFIG = ""; # Ignore the config file
# };
# extraLabels = {
# "traefik.http.routers.${hostname}-blazestar-net-well-known.rule" =
# "Host(`blazestar.net`) && PathPrefix(`/.well-known`)";
# "traefik.http.routers.${hostname}-blazestar-net-well-known.service" = "${hostname}-blazestar-net";
# };
# };
virtualisation.oci-containers.containers.chat = mkContainer {
image = "vectorim/element-web:latest";
hostName = "chat";
port = 8080;
domain = blazestar;
environment = {
ELEMENT_WEB_PORT = "8080";
};
};
}

View File

@@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./chat.nix
./uptime.nix
];
}

View File

@@ -0,0 +1,15 @@
{ config, ... }:
let
inherit (import ../lib.nix config) blazestar;
in
{
virtualisation.web-containers.containers.uptime = {
image = "louislam/uptime-kuma:1";
hostname = "uptime";
domain = blazestar;
port = 3001;
volumes = [
"uptime-kuma:/app/data"
];
};
}

View File

@@ -1,37 +1,26 @@
{ config, ... }:
let
inherit (import ./lib.nix config) mkContainer mkMariaDbContainer havenisms;
userIds = import ./user-ids.nix;
in {
in
{
imports = [
(mkMariaDbContainer {
name = "bookstack";
uid = userIds.bookstack.uid;
gid = userIds.bookstack.gid;
uid = config.users.users.bookstack.uid;
gid = config.users.groups.bookstack.gid;
directory = "/tank/bookstack/db";
passwordSecret = "bookstack_db";
})
];
users.groups.bookstack = {
gid = userIds.bookstack.gid;
};
users.users.bookstack = {
uid = userIds.bookstack.uid;
isSystemUser = true;
description = "System User for Bookstack";
group = "bookstack";
};
sops.secrets = {
bookstack_app_key = {
restartUnits = [ "podman-bookstack.service" ];
restartUnits = [ "${config.local.container-backend}-bookstack.service" ];
mode = "0400";
owner = config.users.users.bookstack.name;
};
bookstack_db = {
restartUnits = [ "podman-bookstack-mariadb.service" ];
restartUnits = [ "${config.local.container-backend}-bookstack-mariadb.service" ];
mode = "0400";
owner = config.users.users.bookstack.name;
};
@@ -55,8 +44,8 @@ in {
];
environment = {
APP_URL = "https://bookstack.${havenisms}";
PID = toString userIds.bookstack.uid;
GID = toString userIds.bookstack.gid;
PID = toString config.users.users.bookstack.uid;
GID = toString config.users.groups.bookstack.gid;
DB_HOST = "bookstack-mariadb";
DB_USERNAME = "bookstack";
DB_DATABASE = "bookstack";

View File

@@ -0,0 +1,108 @@
{ config, pkgs, ... }:
let
inherit (import ./lib.nix config) mkContainer localHostRule terakoda;
nginxConf = pkgs.writeText "dm-companion-nginx.conf" ''
user nginx;
worker_processes auto;
# error.log is symlinked to /dev/stderr
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# access.log is symlinked to /dev/stdout
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
server {
listen 80;
server_name dm.blazestar.net;
root /usr/share/nginx/html;
# X-Frame-Options is to prevent from clickJacking attack
add_header X-Frame-Options SAMEORIGIN;
# disable content-type sniffing on some browsers.
add_header X-Content-Type-Options nosniff;
# This header enables the Cross-site scripting (XSS) filter
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "no-referrer-when-downgrade";
# Enables response header of "Vary: Accept-Encoding"
# This lets the cache have different entries depending on the encoding, e.g. compression
gzip_vary on;
# Serve static files separately.
location ~ ^/(robots.txt|manifest.json) {
expires modified 1y;
add_header Cache-Control "public";
access_log off;
}
location / {
try_files $uri $uri/ /index.html;
index index.html;
expires -1;
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
}
}
'';
in
{
virtualisation.oci-containers.containers = {
dm-companion-pocketbase =
let
hostName = "dm-pocketbase";
in
mkContainer {
inherit hostName;
image = "docker.havenisms.com/lazy-dm/pocketbase";
domain = terakoda;
port = 8080;
volumes = [
"/tank/web/dm.terakoda.com/pb_data:/pb/pb_data"
"/tank/web/dm.terakoda.com/pb_migrations:/pb/pb_migrations:ro"
];
environment = { };
extraLabels = {
"traefik.http.routers.${hostName}-api.rule" =
"PathPrefix(`/api`) && ${localHostRule "dm" terakoda}";
"traefik.http.routers.${hostName}-api.service" = "${hostName}";
};
};
dm-companion = mkContainer {
image = "nginx:alpine";
hostName = "dm";
domain = terakoda;
port = 80;
dependsOn = [
"dm-companion-pocketbase"
];
volumes = [
"/tank/web/dm.terakoda.com/deployed:/usr/share/nginx/html:ro"
"${nginxConf}:/etc/nginx/nginx.conf:ro"
];
};
};
}

View File

@@ -1,44 +0,0 @@
{ config, ... }:
let
inherit (import ./lib.nix config) blazestar;
in {
virtualisation.oci-containers.containers.docker-mailserver = {
image = "ghcr.io/docker-mailserver/docker-mailserver:latest";
hostname = "mail.${blazestar}";
autoStart = true;
ports = [
"465:465"
"587:587"
"993:993"
];
volumes = [
"/tank/mailserver/mail-data:/var/mail"
"/tank/mailserver/mail-state:/var/mail-state"
"/tank/mailserver/mail-logs:/var/log/mail"
"/tank/mailserver/config:/tmp/docker-mailserver"
"/etc/localtime:/etc/localtime:ro"
];
# environment = {
# See https://docker-mailserver.github.io/docker-mailserver/latest/config/environment/
# docker-mailserver uses 0 and 1 for false and true respectively
# ENABLE_RSPAMD="1";
# ENABLE_CLAMAV="1";
# ENABLE_FAIL2BAN="1";
# LOG_LEVEL="info";
# ENABLE_POP3="0";
# ENABLE_IMAP="1";
# };
environmentFiles = [
./email/mailserver.env
];
extraOptions = [
# add network admin capability for Fail2Ban
"--cap-add=NET_ADMIN"
];
labels = {
"traefik.enable" = "true";
"traefik.tcp.routers.mail.service" = "mailserver";
};
};
}

View File

@@ -1,661 +0,0 @@
# -----------------------------------------------
# --- Mailserver Environment Variables ----------
# -----------------------------------------------
# DOCUMENTATION FOR THESE VARIABLES IS FOUND UNDER
# https://docker-mailserver.github.io/docker-mailserver/latest/config/environment/
# -----------------------------------------------
# --- General Section ---------------------------
# -----------------------------------------------
# empty => uses the `hostname` command to get the mail server's canonical hostname
# => Specify a fully-qualified domainname to serve mail for. This is used for many of the config features so if you can't set your hostname (e.g. you're in a container platform that doesn't let you) specify it in this environment variable.
OVERRIDE_HOSTNAME=
# REMOVED in version v11.0.0! Use LOG_LEVEL instead.
DMS_DEBUG=0
# Set the log level for DMS.
# This is mostly relevant for container startup scripts and change detection event feedback.
#
# Valid values (in order of increasing verbosity) are: `error`, `warn`, `info`, `debug` and `trace`.
# The default log level is `info`.
LOG_LEVEL=info
# critical => Only show critical messages
# error => Only show erroneous output
# **warn** => Show warnings
# info => Normal informational output
# debug => Also show debug messages
SUPERVISOR_LOGLEVEL=
# Support for deployment where these defaults are not compatible (eg: some NAS appliances):
# /var/mail vmail User ID (default: 5000)
DMS_VMAIL_UID=
# /var/mail vmail Group ID (default: 5000)
DMS_VMAIL_GID=
# **empty** => use FILE
# LDAP => use LDAP authentication
# OIDC => use OIDC authentication (not yet implemented)
# FILE => use local files (this is used as the default)
ACCOUNT_PROVISIONER=
# empty => postmaster@domain.com
# => Specify the postmaster address
POSTMASTER_ADDRESS=postmaster@blazestar.net
# Check for updates on container start and then once a day
# If an update is available, a mail is sent to POSTMASTER_ADDRESS
# 0 => Update check disabled
# 1 => Update check enabled
ENABLE_UPDATE_CHECK=1
# Customize the update check interval.
# Number + Suffix. Suffix must be 's' for seconds, 'm' for minutes, 'h' for hours or 'd' for days.
UPDATE_CHECK_INTERVAL=1d
# Set different options for mynetworks option (can be overwrite in postfix-main.cf)
# **WARNING**: Adding the docker network's gateway to the list of trusted hosts, e.g. using the `network` or
# `connected-networks` option, can create an open relay
# https://github.com/docker-mailserver/docker-mailserver/issues/1405#issuecomment-590106498
# The same can happen for rootless podman. To prevent this, set the value to "none" or configure slirp4netns
# https://github.com/docker-mailserver/docker-mailserver/issues/2377
#
# none => Explicitly force authentication
# container => Container IP address only
# host => Add docker container network (ipv4 only)
# network => Add all docker container networks (ipv4 only)
# connected-networks => Add all connected docker networks (ipv4 only)
PERMIT_DOCKER=none
# Set the timezone. If this variable is unset, the container runtime will try to detect the time using
# `/etc/localtime`, which you can alternatively mount into the container. The value of this variable
# must follow the pattern `AREA/ZONE`, i.e. of you want to use Germany's time zone, use `Europe/Berlin`.
# You can lookup all available timezones here: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
TZ=
# In case you network interface differs from 'eth0', e.g. when you are using HostNetworking in Kubernetes,
# you can set NETWORK_INTERFACE to whatever interface you want. This interface will then be used.
# - **empty** => eth0
NETWORK_INTERFACE=
# empty => modern
# modern => Enables TLSv1.2 and modern ciphers only. (default)
# intermediate => Enables TLSv1, TLSv1.1 and TLSv1.2 and broad compatibility ciphers.
TLS_LEVEL=
# Configures the handling of creating mails with forged sender addresses.
#
# **0** => (not recommended) Mail address spoofing allowed. Any logged in user may create email messages with a forged sender address (see also https://en.wikipedia.org/wiki/Email_spoofing).
# 1 => Mail spoofing denied. Each user may only send with their own or their alias addresses. Addresses with extension delimiters(http://www.postfix.org/postconf.5.html#recipient_delimiter) are not able to send messages.
SPOOF_PROTECTION=
# Enables the Sender Rewriting Scheme. SRS is needed if your mail server acts as forwarder. See [postsrsd](https://github.com/roehling/postsrsd/blob/main/README.rst) for further explanation.
# - **0** => Disabled
# - 1 => Enabled
ENABLE_SRS=0
# Enables the OpenDKIM service.
# **1** => Enabled
# 0 => Disabled
ENABLE_OPENDKIM=1
# Enables the OpenDMARC service.
# **1** => Enabled
# 0 => Disabled
ENABLE_OPENDMARC=1
# Enabled `policyd-spf` in Postfix's configuration. You will likely want to set this
# to `0` in case you're using Rspamd (`ENABLE_RSPAMD=1`).
#
# - 0 => Disabled
# - **1** => Enabled
ENABLE_POLICYD_SPF=1
# Enables POP3 service
# - **0** => Disabled
# - 1 => Enabled
ENABLE_POP3=0
# Enables IMAP service
# - 0 => Disabled
# - **1** => Enabled
ENABLE_IMAP=1
# Enables ClamAV, and anti-virus scanner.
# 1 => Enabled
# **0** => Disabled
ENABLE_CLAMAV=0
# Add the value of this ENV as a prefix to the mail subject when spam is detected.
# NOTE: This subject prefix may be redundant (by default spam is delivered to a junk folder).
# It provides value when your junk mail is stored alongside legitimate mail instead of a separate location (like with `SPAMASSASSIN_SPAM_TO_INBOX=1` or `MOVE_SPAM_TO_JUNK=0` or a POP3 only setup, without IMAP).
# NOTE: When not using Docker Compose, other CRI may not support quote-wrapping the value here to preserve any trailing white-space.
SPAM_SUBJECT=
# Enables Rspamd
# **0** => Disabled
# 1 => Enabled
ENABLE_RSPAMD=0
# When `ENABLE_RSPAMD=1`, an internal Redis instance is enabled implicitly.
# This setting provides an opt-out to allow using an external instance instead.
# 0 => Disabled
# 1 => Enabled
ENABLE_RSPAMD_REDIS=
# When enabled,
#
# 1. the "[autolearning][rspamd-autolearn]" feature is turned on;
# 2. the Bayes classifier will be trained when moving mails from or to the Junk folder (with the help of Sieve scripts).
#
# **0** => disabled
# 1 => enabled
RSPAMD_LEARN=0
# This settings controls whether checks should be performed on emails coming
# from authenticated users (i.e. most likely outgoing emails). The default value
# is `0` in order to align better with SpamAssassin. We recommend reading
# through https://rspamd.com/doc/tutorials/scanning_outbound.html though to
# decide for yourself whether you need and want this feature.
#
# Note that DKIM signing of e-mails will still happen.
RSPAMD_CHECK_AUTHENTICATED=0
# Controls whether the Rspamd Greylisting module is enabled.
# This module can further assist in avoiding spam emails by greylisting
# e-mails with a certain spam score.
#
# **0** => disabled
# 1 => enabled
RSPAMD_GREYLISTING=0
# Can be used to enable or disable the Hfilter group module.
#
# - 0 => Disabled
# - **1** => Enabled
RSPAMD_HFILTER=1
# Can be used to control the score when the HFILTER_HOSTNAME_UNKNOWN symbol applies. A higher score is more punishing. Setting it to 15 is equivalent to rejecting the email when the check fails.
#
# Default: 6
RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE=6
# Can be used to enable or disable the (still experimental) neural module.
#
# - **0** => Disabled
# - 1 => Enabled
RSPAMD_NEURAL=0
# Amavis content filter (used for ClamAV & SpamAssassin)
# 0 => Disabled
# 1 => Enabled
ENABLE_AMAVIS=1
# -1/-2/-3 => Only show errors
# **0** => Show warnings
# 1/2 => Show default informational output
# 3/4/5 => log debug information (very verbose)
AMAVIS_LOGLEVEL=0
# This enables DNS block lists in Postscreen.
# Note: Emails will be rejected, if they don't pass the block list checks!
# **0** => DNS block lists are disabled
# 1 => DNS block lists are enabled
ENABLE_DNSBL=0
# If you enable Fail2Ban, don't forget to add the following lines to your `compose.yaml`:
# cap_add:
# - NET_ADMIN
# Otherwise, `nftables` won't be able to ban IPs.
ENABLE_FAIL2BAN=0
# Fail2Ban blocktype
# drop => drop packet (send NO reply)
# reject => reject packet (send ICMP unreachable)
FAIL2BAN_BLOCKTYPE=drop
# 1 => Enables Managesieve on port 4190
# empty => disables Managesieve
ENABLE_MANAGESIEVE=
# **enforce** => Allow other tests to complete. Reject attempts to deliver mail with a 550 SMTP reply, and log the helo/sender/recipient information. Repeat this test the next time the client connects.
# drop => Drop the connection immediately with a 521 SMTP reply. Repeat this test the next time the client connects.
# ignore => Ignore the failure of this test. Allow other tests to complete. Repeat this test the next time the client connects. This option is useful for testing and collecting statistics without blocking mail.
POSTSCREEN_ACTION=enforce
# empty => all daemons start
# 1 => only launch postfix smtp
SMTP_ONLY=
# Please read [the SSL page in the documentation](https://docker-mailserver.github.io/docker-mailserver/latest/config/security/ssl) for more information.
#
# empty => SSL disabled
# letsencrypt => Enables Let's Encrypt certificates
# custom => Enables custom certificates
# manual => Let's you manually specify locations of your SSL certificates for non-standard cases
# self-signed => Enables self-signed certificates
SSL_TYPE=letsencrypt
# These are only supported with `SSL_TYPE=manual`.
# Provide the path to your cert and key files that you've mounted access to within the container.
SSL_CERT_PATH=
SSL_KEY_PATH=
# Optional: A 2nd certificate can be supported as fallback (dual cert support), eg ECDSA with an RSA fallback.
# Useful for additional compatibility with older MTA and MUA (eg pre-2015).
SSL_ALT_CERT_PATH=
SSL_ALT_KEY_PATH=
# Set how many days a virusmail will stay on the server before being deleted
# empty => 7 days
VIRUSMAILS_DELETE_DELAY=
# Configure Postfix `virtual_transport` to deliver mail to a different LMTP client (default is a dovecot socket).
# Provide any valid URI. Examples:
#
# empty => `lmtp:unix:/var/run/dovecot/lmtp` (default, configured in Postfix main.cf)
# `lmtp:unix:private/dovecot-lmtp` (use socket)
# `lmtps:inet:<host>:<port>` (secure lmtp with starttls)
# `lmtp:<kopano-host>:2003` (use kopano as mailstore)
POSTFIX_DAGENT=
# Set the mailbox size limit for all users. If set to zero, the size will be unlimited (default). Size is in bytes.
#
# empty => 0
POSTFIX_MAILBOX_SIZE_LIMIT=
# See https://docker-mailserver.github.io/docker-mailserver/latest/config/account-management/overview/#quotas
# 0 => Dovecot quota is disabled
# 1 => Dovecot quota is enabled
ENABLE_QUOTAS=1
# Set the message size limit for all users. If set to zero, the size will be unlimited (not recommended!). Size is in bytes.
#
# empty => 10240000 (~10 MB)
POSTFIX_MESSAGE_SIZE_LIMIT=
# Mails larger than this limit won't be scanned.
# ClamAV must be enabled (ENABLE_CLAMAV=1) for this.
#
# empty => 25M (25 MB)
CLAMAV_MESSAGE_SIZE_LIMIT=
# Enables regular pflogsumm mail reports.
# This is a new option. The old REPORT options are still supported for backwards compatibility. If this is not set and reports are enabled with the old options, logrotate will be used.
#
# not set => No report
# daily_cron => Daily report for the previous day
# logrotate => Full report based on the mail log when it is rotated
PFLOGSUMM_TRIGGER=
# Recipient address for pflogsumm reports.
#
# not set => Use REPORT_RECIPIENT or POSTMASTER_ADDRESS
# => Specify the recipient address(es)
PFLOGSUMM_RECIPIENT=
# Sender address (`FROM`) for pflogsumm reports if pflogsumm reports are enabled.
#
# not set => Use REPORT_SENDER
# => Specify the sender address
PFLOGSUMM_SENDER=
# Interval for logwatch report.
#
# none => No report is generated
# daily => Send a daily report
# weekly => Send a report every week
LOGWATCH_INTERVAL=weekly
# Recipient address for logwatch reports if they are enabled.
#
# not set => Use REPORT_RECIPIENT or POSTMASTER_ADDRESS
# => Specify the recipient address(es)
LOGWATCH_RECIPIENT=
# Sender address (`FROM`) for logwatch reports if logwatch reports are enabled.
#
# not set => Use REPORT_SENDER
# => Specify the sender address
LOGWATCH_SENDER=
# Defines who receives reports if they are enabled.
# **empty** => ${POSTMASTER_ADDRESS}
# => Specify the recipient address
REPORT_RECIPIENT=
# Defines who sends reports if they are enabled.
# **empty** => mailserver-report@${DOMAINNAME}
# => Specify the sender address
REPORT_SENDER=
# Changes the interval in which log files are rotated
# **weekly** => Rotate log files weekly
# daily => Rotate log files daily
# monthly => Rotate log files monthly
#
# Note: This Variable actually controls logrotate inside the container
# and rotates the log files depending on this setting. The main log output is
# still available in its entirety via `docker logs mail` (Or your
# respective container name). If you want to control logrotation for
# the Docker-generated logfile see:
# https://docs.docker.com/config/containers/logging/configure/
#
# Note: This variable can also determine the interval for Postfix's log summary reports, see [`PFLOGSUMM_TRIGGER`](#pflogsumm_trigger).
LOGROTATE_INTERVAL=weekly
# Defines how many log files are kept by logrorate
LOGROTATE_COUNT=4
# If enabled, employs `reject_unknown_client_hostname` to sender restrictions in Postfix's configuration.
#
# - **0** => Disabled
# - 1 => Enabled
POSTFIX_REJECT_UNKNOWN_CLIENT_HOSTNAME=0
# Choose TCP/IP protocols for postfix to use
# **all** => All possible protocols.
# ipv4 => Use only IPv4 traffic. Most likely you want this behind Docker.
# ipv6 => Use only IPv6 traffic.
#
# Note: More details at http://www.postfix.org/postconf.5.html#inet_protocols
POSTFIX_INET_PROTOCOLS=all
# Enables MTA-STS support for outbound mail.
# More details: https://docker-mailserver.github.io/docker-mailserver/v13.3/config/best-practices/mta-sts/
# - **0** ==> MTA-STS disabled
# - 1 => MTA-STS enabled
ENABLE_MTA_STS=0
# Choose TCP/IP protocols for dovecot to use
# **all** => Listen on all interfaces
# ipv4 => Listen only on IPv4 interfaces. Most likely you want this behind Docker.
# ipv6 => Listen only on IPv6 interfaces.
#
# Note: More information at https://dovecot.org/doc/dovecot-example.conf
DOVECOT_INET_PROTOCOLS=all
# -----------------------------------------------
# --- SpamAssassin Section ----------------------
# -----------------------------------------------
ENABLE_SPAMASSASSIN=0
# KAM is a 3rd party SpamAssassin ruleset, provided by the McGrail Foundation.
# If SpamAssassin is enabled, KAM can be used in addition to the default ruleset.
# - **0** => KAM disabled
# - 1 => KAM enabled
#
# Note: only has an effect if `ENABLE_SPAMASSASSIN=1`
ENABLE_SPAMASSASSIN_KAM=0
# deliver spam messages to the inbox (tagged using SPAM_SUBJECT)
SPAMASSASSIN_SPAM_TO_INBOX=1
# spam messages will be moved in the Junk folder (SPAMASSASSIN_SPAM_TO_INBOX=1 required)
MOVE_SPAM_TO_JUNK=1
# spam messages will be marked as read
MARK_SPAM_AS_READ=0
# add 'spam info' headers at, or above this level
SA_TAG=2.0
# add 'spam detected' headers at, or above this level
SA_TAG2=6.31
# triggers spam evasive actions
SA_KILL=10.0
# -----------------------------------------------
# --- Fetchmail Section -------------------------
# -----------------------------------------------
ENABLE_FETCHMAIL=0
# The interval to fetch mail in seconds
FETCHMAIL_POLL=300
# Use multiple fetchmail instances (1 per poll entry in fetchmail.cf)
# Supports multiple IMAP IDLE connections when a server is used across multiple poll entries
# https://otremba.net/wiki/Fetchmail_(Debian)#Immediate_Download_via_IMAP_IDLE
FETCHMAIL_PARALLEL=0
# Enable or disable `getmail`.
#
# - **0** => Disabled
# - 1 => Enabled
ENABLE_GETMAIL=0
# The number of minutes for the interval. Min: 1; Default: 5.
GETMAIL_POLL=5
# -----------------------------------------------
# --- OAUTH2 Section ----------------------------
# -----------------------------------------------
# empty => OAUTH2 authentication is disabled
# 1 => OAUTH2 authentication is enabled
ENABLE_OAUTH2=1
# Specify the user info endpoint URL of the oauth2 provider
# Example: https://oauth2.example.com/userinfo/
OAUTH2_INTROSPECTION_URL=https://auth.blazestar.net/api/oidc/userinfo
# -----------------------------------------------
# --- LDAP Section ------------------------------
# -----------------------------------------------
# A second container for the ldap service is necessary (i.e. https://hub.docker.com/r/bitnami/openldap/)
# empty => no
# yes => LDAP over TLS enabled for Postfix
LDAP_START_TLS=
# empty => mail.example.com
# Specify the `<dns-name>` / `<ip-address>` where the LDAP server is reachable via a URI like: `ldaps://mail.example.com`.
# Note: You must include the desired URI scheme (`ldap://`, `ldaps://`, `ldapi://`).
LDAP_SERVER_HOST=
# empty => ou=people,dc=domain,dc=com
# => e.g. LDAP_SEARCH_BASE=dc=mydomain,dc=local
LDAP_SEARCH_BASE=
# empty => cn=admin,dc=domain,dc=com
# => take a look at examples of SASL_LDAP_BIND_DN
LDAP_BIND_DN=
# empty** => admin
# => Specify the password to bind against ldap
LDAP_BIND_PW=
# e.g. `"(&(mail=%s)(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for users
LDAP_QUERY_FILTER_USER=
# e.g. `"(&(mailGroupMember=%s)(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for groups
LDAP_QUERY_FILTER_GROUP=
# e.g. `"(&(mailAlias=%s)(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for aliases
LDAP_QUERY_FILTER_ALIAS=
# e.g. `"(&(|(mail=*@%s)(mailalias=*@%s)(mailGroupMember=*@%s))(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for domains
LDAP_QUERY_FILTER_DOMAIN=
# -----------------------------------------------
# --- Dovecot Section ---------------------------
# -----------------------------------------------
# empty => no
# yes => LDAP over TLS enabled for Dovecot
DOVECOT_TLS=
# e.g. `"(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))"`
DOVECOT_USER_FILTER=
# e.g. `"(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))"`
DOVECOT_PASS_FILTER=
# Define the mailbox format to be used
# default is maildir, supported values are: sdbox, mdbox, maildir
DOVECOT_MAILBOX_FORMAT=maildir
# empty => no
# yes => Allow bind authentication for LDAP
# https://doc.dovecot.org/2.4.0/core/config/auth/databases/ldap.html#authentication-bind
DOVECOT_AUTH_BIND=
# -----------------------------------------------
# --- Postgrey Section --------------------------
# -----------------------------------------------
ENABLE_POSTGREY=0
# greylist for N seconds
POSTGREY_DELAY=300
# delete entries older than N days since the last time that they have been seen
POSTGREY_MAX_AGE=35
# response when a mail is greylisted
POSTGREY_TEXT="Delayed by Postgrey"
# whitelist host after N successful deliveries (N=0 to disable whitelisting)
POSTGREY_AUTO_WHITELIST_CLIENTS=5
# -----------------------------------------------
# --- SASL Section ------------------------------
# -----------------------------------------------
ENABLE_SASLAUTHD=0
# empty => pam
# `ldap` => authenticate against ldap server
# `shadow` => authenticate against local user db
# `mysql` => authenticate against mysql db
# `rimap` => authenticate against imap server
# Note: can be a list of mechanisms like pam ldap shadow
SASLAUTHD_MECHANISMS=
# empty => None
# e.g. with SASLAUTHD_MECHANISMS rimap you need to specify the ip-address/servername of the imap server ==> xxx.xxx.xxx.xxx
SASLAUTHD_MECH_OPTIONS=
# empty => Use value of LDAP_SERVER_HOST
# Note: You must include the desired URI scheme (`ldap://`, `ldaps://`, `ldapi://`).
SASLAUTHD_LDAP_SERVER=
# empty => Use value of LDAP_BIND_DN
# specify an object with privileges to search the directory tree
# e.g. active directory: SASLAUTHD_LDAP_BIND_DN=cn=Administrator,cn=Users,dc=mydomain,dc=net
# e.g. openldap: SASLAUTHD_LDAP_BIND_DN=cn=admin,dc=mydomain,dc=net
SASLAUTHD_LDAP_BIND_DN=
# empty => Use value of LDAP_BIND_PW
SASLAUTHD_LDAP_PASSWORD=
# empty => Use value of LDAP_SEARCH_BASE
# specify the search base
SASLAUTHD_LDAP_SEARCH_BASE=
# empty => default filter `(&(uniqueIdentifier=%u)(mailEnabled=TRUE))`
# e.g. for active directory: `(&(sAMAccountName=%U)(objectClass=person))`
# e.g. for openldap: `(&(uid=%U)(objectClass=person))`
SASLAUTHD_LDAP_FILTER=
# empty => no
# yes => LDAP over TLS enabled for SASL
# If set to yes, the protocol in SASLAUTHD_LDAP_SERVER must be ldap:// or missing.
SASLAUTHD_LDAP_START_TLS=
# empty => no
# yes => Require and verify server certificate
# If yes you must/could specify SASLAUTHD_LDAP_TLS_CACERT_FILE or SASLAUTHD_LDAP_TLS_CACERT_DIR.
SASLAUTHD_LDAP_TLS_CHECK_PEER=
# File containing CA (Certificate Authority) certificate(s).
# empty => Nothing is added to the configuration
# Any value => Fills the `ldap_tls_cacert_file` option
SASLAUTHD_LDAP_TLS_CACERT_FILE=
# Path to directory with CA (Certificate Authority) certificates.
# empty => Nothing is added to the configuration
# Any value => Fills the `ldap_tls_cacert_dir` option
SASLAUTHD_LDAP_TLS_CACERT_DIR=
# Specify what password attribute to use for password verification.
# empty => Nothing is added to the configuration but the documentation says it is `userPassword` by default.
# Any value => Fills the `ldap_password_attr` option
SASLAUTHD_LDAP_PASSWORD_ATTR=
# empty => `bind` will be used as a default value
# `fastbind` => The fastbind method is used
# `custom` => The custom method uses userPassword attribute to verify the password
SASLAUTHD_LDAP_AUTH_METHOD=
# Specify the authentication mechanism for SASL bind
# empty => Nothing is added to the configuration
# Any value => Fills the `ldap_mech` option
SASLAUTHD_LDAP_MECH=
# -----------------------------------------------
# --- SRS Section -------------------------------
# -----------------------------------------------
# envelope_sender => Rewrite only envelope sender address (default)
# header_sender => Rewrite only header sender (not recommended)
# envelope_sender,header_sender => Rewrite both senders
# An email has an "envelope" sender (indicating the sending server) and a
# "header" sender (indicating who sent it). More strict SPF policies may require
# you to replace both instead of just the envelope sender.
SRS_SENDER_CLASSES=envelope_sender
# empty => Envelope sender will be rewritten for all domains
# provide comma separated list of domains to exclude from rewriting
SRS_EXCLUDE_DOMAINS=
# empty => generated when the image is built
# provide a secret to use in base64
# you may specify multiple keys, comma separated. the first one is used for
# signing and the remaining will be used for verification. this is how you
# rotate and expire keys
SRS_SECRET=
# -----------------------------------------------
# --- Default Relay Host Section ----------------
# -----------------------------------------------
# Setup relaying all mail through a default relay host
#
# Set a default host to relay all mail through (optionally include a port)
# Example: [mail.example.com]:587
DEFAULT_RELAY_HOST=
# -----------------------------------------------
# --- Multi-Domain Relay Section ----------------
# -----------------------------------------------
# Setup relaying for multiple domains based on the domain name of the sender
# optionally uses usernames and passwords in postfix-sasl-password.cf and relay host mappings in postfix-relaymap.cf
#
# Set a default host to relay mail through
# Example: mail.example.com
RELAY_HOST=
# empty => 25
# default port to relay mail
RELAY_PORT=25
# -----------------------------------------------
# --- Relay Host Credentials Section ------------
# -----------------------------------------------
# Configure a relay user and password to use with RELAY_HOST / DEFAULT_RELAY_HOST
# empty => no default
RELAY_USER=
# empty => no default
RELAY_PASSWORD=

View File

@@ -0,0 +1,67 @@
{ config, ... }:
let
inherit (import ./lib.nix config) mkContainer mkPostgresContainer terakoda;
in
{
imports = [
(mkPostgresContainer {
name = "focalboard";
directory = "/tank/focalboard/db";
uid = config.users.users.focalboard.uid;
gid = config.users.groups.focalboard.gid;
passwordSecret = "focalboard/database";
})
];
sops.secrets = {
"focalboard/database" = {
restartUnits = [
"${config.local.container-backend}-focalboard.service"
"${config.local.container-backend}-focalboard-postgres.service"
];
mode = "0400";
owner = config.users.users.focalboard.name;
};
};
sops.templates."focalboard-config.json" = {
restartUnits = [ "${config.local.container-backend}-focalboard.service" ];
owner = config.users.users.focalboard.name;
content = builtins.toJSON {
# Defaults from https://github.com/mattermost-community/focalboard/blob/main/config.json
"serverRoot" = "https://focalboard.terakoda.com";
"port" = 8000;
"dbtype" = "postgres";
"dbconfig" = "postgres://focalboard:${
config.sops.placeholder."focalboard/database"
}@focalboard-postgres/focalboard?sslmode=disable&connect_timeout=10";
"useSSL" = true;
"prometheus_address" = ":9092";
"session_expire_time" = 2592000;
"session_refresh_time" = 18000;
"postgres_dbconfig" = "dbname=focalboard sslmode=disable";
"webpath" = "./pack";
"filespath" = "./data/files";
"telemetry" = true;
"prometheusaddress" = ":9092";
"enableLocalMode" = true;
"localModeSocketLocation" = "/var/tmp/focalboard_local.socket";
};
};
virtualisation.oci-containers.containers = {
focalboard = mkContainer {
image = "mattermost/focalboard";
hostName = "focalboard";
domain = terakoda;
dependsOn = [ "focalboard-postgres" ];
port = 8000;
user = "${toString config.users.users.focalboard.uid}:${toString config.users.groups.focalboard.gid}";
volumes = [
"/tank/focalboard/data/files:/opt/focalboard/data/files"
"${config.sops.templates."focalboard-config.json".path}:/opt/focalboard/config.json:ro"
];
};
};
}

View File

@@ -0,0 +1,20 @@
{ config, ... }:
let
inherit (import ./lib.nix config) mkContainer havenisms;
in {
virtualisation.oci-containers.containers.freshrss = mkContainer {
image = "lscr.io/linuxserver/freshrss:latest";
hostName = "freshrss";
domain = havenisms;
port = "80";
homepageOpts = {
group = "Apps";
name = "FreshRSS";
icon = "freshrss.svg";
description = "Feed aggregator";
};
volumes = [
"/tank/config/freshrss:/config"
];
};
}

View File

@@ -1,24 +1,40 @@
{ config, ... }:
let
inherit (import ./lib.nix config) hostRule blazestar;
inherit (import ./lib.nix config) mkContainer blazestar;
in
{
virtualisation.oci-containers.containers.gitea = {
sops.secrets = {
"gitea/db_password" = {
restartUnits = [ "${config.local.container-backend}-gitea.service" ];
};
"gitea/registration_token" = {
restartUnits = [ "${config.local.container-backend}-gitea-runner.service" ];
};
};
sops.templates."gitea.env".content = ''
GITEA__database__DB_TYPE="postgres"
GITEA__database__HOST="db"
GITEA__database__NAME="gitea"
GITEA__database__USER="gitea"
GITEA__database__PASSWD="${config.sops.placeholder."gitea/db_password"}"
'';
virtualisation.oci-containers.containers.gitea = mkContainer {
image = "gitea/gitea:latest-rootless";
autoStart = true;
dependsOn = [
"db"
];
extraOptions = [
"-l=traefik.enable=true"
"-l=traefik.http.routers.gitea.rule=${hostRule "git" blazestar}"
"-l=traefik.http.services.gitea.loadbalancer.server.port=3000"
"-l=homepage.group=Apps"
"-l=homepage.name=Gitea"
"-l=homepage.icon=gitea.png"
"-l=homepage.href=https://git.${blazestar}"
"-l=homepage.description=Git Server"
];
hostName = "git";
domain = blazestar;
public = true;
port = 3000;
homepageOpts = {
name = "Gitea";
icon = "gitea.png";
description = "Git Server";
group = "Apps";
};
ports = [
"2222:2222"
];
@@ -36,14 +52,21 @@ in
];
};
sops.secrets."gitea_db_password" = {
restartUnits = [ "podman-gitea.service" ];
};
sops.templates."gitea.env".content = ''
GITEA__database__DB_TYPE="postgres"
GITEA__database__HOST="db"
GITEA__database__NAME="gitea"
GITEA__database__USER="gitea"
GITEA__database__PASSWD="${config.sops.placeholder."gitea_db_password"}"
sops.templates."gitea-runner.env".content = ''
GITEA_RUNNER_NAME=MCP
GITEA_INSTANCE_URL=https://git.${blazestar}
GITEA_RUNNER_REGISTRATION_TOKEN=${config.sops.placeholder."gitea/registration_token"}
'';
virtualisation.oci-containers.containers.gitea-runner = {
image = "gitea/act_runner:latest";
autoStart = true;
environmentFiles = [
config.sops.templates."gitea-runner.env".path
];
volumes = [
# The runner will spawn new containers to run the actions
"${config.local.container-socket}:/var/run/docker.sock:ro"
];
};
}

View File

@@ -0,0 +1,58 @@
{ config, ... }:
let
inherit (import ./lib.nix config)
terakoda
blazestar
hostRule
;
in
{
imports = [
../../../features/web-containers.nix
];
virtualisation.web-containers = {
enable = true;
containers = {
goatcounter-terakoda = {
image = "arp242/goatcounter";
hostname = "goatcounter";
domain = terakoda;
public = true;
port = 8080;
volumes = [
"goatcounter-data:/home/goatcounter/goatcounter-data"
];
extraLabels = {
# "traefik.http.middlewares.strip-analytics.stripprefix.prefixes" = "/analytics";
# "traefik.http.routers.www-terakoda-com-goatcounter.middlewares" = "strip-analytics";
# Host the script on www.terakoda.com so that it is easy to fetch
"traefik.http.routers.www-terakoda-com-goatcounter.rule" =
"PathPrefix(`/count`) && ${hostRule "www" terakoda}";
"traefik.http.routers.www-terakoda-com-goatcounter.entrypoints" = "websecure";
"traefik.http.routers.www-terakoda-com-goatcounter.service" = "goatcounter-terakoda-com";
};
};
goatcounter-blazestar = {
image = "arp242/goatcounter";
hostname = "goatcounter";
domain = blazestar;
public = true;
port = 8080;
volumes = [
"goatcounter-data-blazestar:/home/goatcounter/goatcounter-data"
];
extraLabels = {
# "traefik.http.middlewares.strip-analytics.stripprefix.prefixes" = "/analytics";
# "traefik.http.routers.www-blazestar-net-goatcounter.middlewares" = "strip-analytics";
# Host the script on www.blazestar.net so that it is easy to fetch
"traefik.http.routers.www-blazestar-net-goatcounter.rule" =
"PathPrefix(`/count`) && ${hostRule "www" blazestar}";
"traefik.http.routers.www-blazestar-net-goatcounter.entrypoints" = "websecure";
"traefik.http.routers.www-blazestar-net-goatcounter.service" = "goatcounter-blazestar-net@docker";
};
};
};
};
}

View File

@@ -0,0 +1,84 @@
{ config, ... }:
let
inherit (import ../lib.nix config) hostRule havenisms;
syncRule = "(PathPrefix(`/client/`) || PathPrefix(`/_matrix/client/unstable/org.matrix.msc3575/sync`))";
wellKnownRule = "(Host(`havenisms.com`) || Host(`chat.havenisms.com`)) && PathPrefix(`/.well-known`)";
in
{
sops.secrets = {
"matrix/syncv3/db-password" = {
restartUnits = [ "${config.local.container-backend}-matrix-sliding-sync.service" ];
};
"matrix/syncv3/secret" = {
restartUnits = [ "${config.local.container-backend}-matrix-sliding-sync.service" ];
};
};
sops.templates."matrix-sliding-sync.env".content = ''
SYNCV3_SERVER=http://synapse:8008
SYNCV3_DB=postgres://syncv3:${
config.sops.placeholder."matrix/syncv3/db-password"
}@db:5432/syncv3?sslmode=disable
SYNCV3_SECRET=${config.sops.placeholder."matrix/syncv3/secret"}
SYNCV3_BINDADDR=:8009
'';
virtualisation.oci-containers.containers = {
synapse = {
image = "docker.io/matrixdotorg/synapse:latest";
autoStart = true;
dependsOn = [
"db"
];
volumes = [
"/tank/config/synapse/data:/data"
];
extraOptions = [
"-l=traefik.enable=true"
"-l=traefik.http.routers.synapse.rule=${hostRule "chat" havenisms} && !(${syncRule} || ${wellKnownRule})"
"-l=traefik.http.routers.synapse.service=synapse"
"-l=traefik.http.services.synapse.loadbalancer.server.port=8008"
# Federation forwarding
"-l=traefik.http.routers.synapse-federation.rule=${hostRule "chat" havenisms}"
"-l=traefik.http.routers.synapse-federation.service=synapse-federation"
"-l=traefik.http.routers.synapse-federation.entrypoints=matrix-federation"
"-l=traefik.http.services.synapse-federation.loadbalancer.server.port=8448"
];
};
matrix-sliding-sync = {
image = "ghcr.io/matrix-org/sliding-sync:latest";
dependsOn = [
"db"
"synapse"
];
environmentFiles = [
config.sops.templates."matrix-sliding-sync.env".path
];
extraOptions = [
"-l=traefik.enable=true"
"-l=traefik.http.routers.syncv3.rule=${hostRule "chat" havenisms} && ${syncRule}"
"-l=traefik.http.services.syncv3.loadbalancer.server.port=8009"
];
};
# This server helps to serve the .well-known files that are required by clients to find the sync server.
matrix-well-known = {
image = "nginx";
dependsOn = [ "synapse" ];
volumes = [
"/tank/config/synapse/static-files:/usr/share/nginx/html:ro"
];
extraOptions = [
"-l=traefik.enable=true"
"-l=traefik.http.middlewares.strip-well-known.stripprefix.prefixes=/.well-known"
"-l=traefik.http.routers.matrix-well-known.rule=${wellKnownRule}"
"-l=traefik.http.routers.matrix-well-known.middlewares=strip-well-known"
"-l=traefik.http.services.matrix-well-known.loadbalancer.server.port=80"
];
};
};
}

View File

@@ -0,0 +1,11 @@
{ ... }:
{
imports = [
./chat.nix
# Currently disabled because it doesn't start up properly
# ./immich.nix
./storyden.nix
./tandoor.nix
./wallabag.nix
];
}

View File

@@ -0,0 +1,73 @@
{ config, ... }:
let
inherit (import ../lib.nix config) havenisms mkPostgresContainer;
in
{
imports = [
(mkPostgresContainer {
# Immich wants a custom build of postgres with the vectors extensions.
image = "ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:c44be5f2871c59362966d71eab4268170eb6f5653c0e6170184e72b38ffdf107";
name = "immich";
directory = "/tank/immich/db";
uid = config.users.users.immich.uid;
gid = config.users.groups.immich.gid;
passwordSecret = "immich/database";
})
];
sops.secrets = {
"immich/database" = {
restartUnits = [
"${config.local.container-backend}-immich-db.service"
];
mode = "0400";
owner = config.users.users.immich.name;
};
};
sops.templates."immich.env" = {
restartUnits = [ "${config.local.container-backend}-immich.service" ];
owner = config.users.users.immich.name;
content = ''
DB_HOSTNAME=immich-postgres
DB_PASSWORD=${config.sops.placeholder."immich/database"}
DB_USERNAME=immich
DB_DATABASE_NAME=immich
REDIS_HOSTNAME=immich-redis
IMMICH_LOG_LEVEL=verbose
'';
};
virtualisation.web-containers.containers.immich = {
image = "ghcr.io/immich-app/immich-server:release";
hostname = "immich";
domain = havenisms;
port = 2283;
volumes = [
"/tank/photos/immich:/data"
"/etc/localtime:/etc/localtime:ro"
];
dependsOn = [
"immich-redis"
"immich-postgres"
];
environmentFiles = [
"${config.sops.templates."immich.env".path}"
];
};
virtualisation.oci-containers.containers = {
"immich-redis" = {
image = "docker.io/valkey/valkey";
};
"immich-machine-learning" = {
image = "ghcr.io/immich-app/immich-machine-learning:release";
volumes = [
"model-cache:/cache"
];
environmentFiles = [
"${config.sops.templates."immich.env".path}"
];
};
};
}

View File

@@ -0,0 +1,17 @@
{ config, ... }:
let
inherit (import ../lib.nix config) havenisms;
in
{
virtualisation.web-containers.containers.storyden = {
image = "ghcr.io/southclaws/storyden";
port = 8000;
hostname = "storyden";
domain = havenisms;
environment = {
PUBLIC_WEB_ADDRESS = "https://storyden.${havenisms}";
PUBLIC_API_ADDRESS = "https://storyden.${havenisms}";
};
};
}

View File

@@ -0,0 +1,30 @@
{ config, ... }:
let
inherit (import ../lib.nix config) havenisms;
in
{
sops.secrets = {
"tandoor/secret_key" = {
restartUnits = [ "${config.local.container-backend}-tandoor.service" ];
};
};
sops.templates."tandoor.env".content = ''
SECRET_KEY="${config.sops.placeholder."tandoor/secret_key"}"
DB_ENGINE=django.db.backends.sqlite3
'';
virtualisation.web-containers.containers.tandoor = {
image = "vabene1111/recipes";
hostname = "recipes";
domain = havenisms;
port = 80;
volumes = [
"/tank/tandoor-recipes/mediafiles:/opt/recipes/mediafiles"
"/tank/tandoor-recipes/staticfiles:/opt/recipes/staticfiles"
];
environmentFiles = [
config.sops.templates."tandoor.env".path
];
};
}

View File

@@ -0,0 +1,19 @@
{ config, ... }:
let
inherit (import ../lib.nix config) havenisms;
in
{
virtualisation.web-containers.containers.wallabag = {
image = "wallabag/wallabag";
hostname = "wallabag";
domain = havenisms;
port = 80;
volumes = [
"wallabag-data:/var/www/wallabag/data"
"wallabag-images:/var/www/wallabag/web/assets/images"
];
environment = {
SYMFONY__ENV__DOMAIN_NAME = "https://wallabag.${havenisms}";
};
};
}

View File

@@ -2,6 +2,8 @@ config:
let
havenisms = "havenisms.com";
blazestar = "blazestar.net";
terakoda = "terakoda.com";
terakoda_net = "terakoda.net";
hostRule = host: domain: "Host(`${host}.${domain}`)";
hostRuleHavenisms = host: hostRule host havenisms;
localNet = "192.168.0.0/16";
@@ -17,14 +19,17 @@ in
hostRuleHavenisms
localHostRuleHavenisms
havenisms
blazestar;
blazestar
terakoda
terakoda_net
;
mkContainer = {
mkContainer =
{
image,
hostName,
port,
homepageOpts,
homepageOpts ? { },
dependsOn ? [ ],
domain ? havenisms,
ports ? [ ],
@@ -32,23 +37,47 @@ in
environment ? { },
environmentFiles ? [ ],
public ? false,
user ? null,
extraOptions ? [ ],
oauthProxy ? false,
extraLabels ? { },
}:
let routerRule = if public then hostRule hostName domain else localHostRule hostName domain;
let
routerRule = if public then hostRule hostName domain else localHostRule hostName domain;
homepageLabels =
if homepageOpts == { } then
{ }
else
{
"homepage.group" = "${homepageOpts.group}";
"homepage.name" = "${homepageOpts.name}";
"homepage.icon" = "${homepageOpts.icon}";
"homepage.href" = "https://${hostName}.${domain}";
"homepage.description" = "${homepageOpts.description}";
};
oauthLabels =
if oauthProxy then { "traefik.http.routers.${hostName}.middlewares" = "oidc-auth@file"; } else { };
in
{
inherit image dependsOn volumes environment environmentFiles ports;
hostname = "${hostName}.${domain}";
inherit
image
dependsOn
volumes
environment
environmentFiles
ports
user
extraOptions
;
autoStart = true;
extraOptions = [
"-l=traefik.enable=true"
"-l=traefik.http.routers.${hostName}.rule=${routerRule}"
"-l=traefik.http.services.${hostName}.loadbalancer.server.port=${toString port}"
"-l=homepage.group=${homepageOpts.group}"
"-l=homepage.name=${homepageOpts.name}"
"-l=homepage.icon=${homepageOpts.icon}"
"-l=homepage.href=https://${hostName}.${domain}"
"-l=homepage.description=${homepageOpts.description}"
];
labels = {
"traefik.enable" = "true";
"traefik.http.routers.${hostName}.rule" = "${routerRule}";
"traefik.http.services.${hostName}.loadbalancer.server.port" = "${toString port}";
}
// oauthLabels
// homepageLabels
// extraLabels;
};
# Creates a MariaDB container for a specific app. It should be safe to give
@@ -57,13 +86,16 @@ in
# user.
#
# Note that this returns a _module_ so that it can be imported and provide many different config values.
mkMariaDbContainer = {
mkMariaDbContainer =
{
name,
uid,
gid,
passwordSecret,
directory,
}: { config, ... }: {
}:
{ config, ... }:
{
virtualisation.oci-containers.containers."${name}-mariadb" = {
image = "lscr.io/linuxserver/mariadb:latest";
autoStart = true;
@@ -83,4 +115,36 @@ in
};
};
};
mkPostgresContainer =
{
name,
uid,
gid,
passwordSecret,
directory,
containerName ? "${name}-postgres",
databaseName ? name,
username ? name,
image ? "postgres",
}:
{ config, ... }:
{
virtualisation.oci-containers.containers."${containerName}" = {
inherit image;
autoStart = true;
volumes = [
# Note that data must be mounted at this location to persist.
# See https://github.com/docker-library/docs/blob/master/postgres/README.md#pgdata
"${directory}:/var/lib/postgresql/data"
"${config.sops.secrets."${passwordSecret}".path}:/run/secrets/postgres_password"
];
user = "${toString uid}:${toString gid}";
environment = {
POSTGRES_USER = username;
POSTGRES_DB = databaseName;
POSTGRES_PASSWORD_FILE = "/run/secrets/postgres_password";
};
};
};
}

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