├── .gitignore
├── .sops.yaml
├── .vscode
└── settings.json
├── LICENSE-MIT
├── flake.lock
├── flake.nix
├── home
├── blacksteel.nix
├── invar.nix
└── modules
│ ├── alacritty.nix
│ ├── direnv.nix
│ ├── firefox.nix
│ ├── git.nix
│ ├── gpg.nix
│ ├── helix
│ └── default.nix
│ ├── lf.nix
│ ├── mail.nix
│ ├── nvim
│ ├── default.nix
│ └── vimrc.vim
│ ├── programs.nix
│ ├── rime-fcitx.nix
│ ├── rust.nix
│ ├── shell
│ ├── cmds.zsh
│ ├── completion.zsh
│ ├── default.nix
│ ├── key-bindings.zsh
│ └── prompt.zsh
│ ├── tmux.nix
│ ├── user-dirs.nix
│ ├── vscode
│ └── default.nix
│ └── xdgify.nix
├── lib.nix
├── my
├── default.nix
└── gpg-pubkey.asc
├── nixos
├── blacksteel
│ ├── configuration.nix
│ ├── secret.yaml
│ └── vm.nix
├── copper
│ └── configuration.nix
├── invar
│ ├── btrbk.nix
│ ├── configuration.nix
│ ├── game.nix
│ ├── orb.nix
│ ├── secret.yaml
│ └── syncthing.nix
├── lithium
│ ├── blah.nix
│ ├── configuration.nix
│ ├── ntfy.nix
│ ├── secret.yaml
│ └── webdav.nix
├── minimal-image
│ └── configuration.nix
├── modules
│ ├── console-env.nix
│ ├── device-fix.nix
│ ├── kde-desktop
│ │ └── default.nix
│ ├── l10n.nix
│ ├── nix-binary-cache-mirror.nix
│ ├── nix-cgroups.nix
│ ├── nix-common.nix
│ ├── nix-keep-flake-inputs.nix
│ ├── nix-registry.nix
│ ├── secure-boot.nix
│ ├── server-env.nix
│ ├── vultr-common.nix
│ ├── vultr-image.nix
│ └── zswap-enable.nix
└── unmatched
│ └── configuration.nix
├── pkgs
├── _sources
│ ├── generated.json
│ └── generated.nix
├── caddy-oxa
│ ├── 0001-caddyauth-use-same-cost-for-users-and-fake-hash.patch
│ └── default.nix
├── cargo-machete-no-spam.nix
├── coc-rust-analyzer-fix-snippet
│ └── default.nix
├── colors.nix
├── default.nix
├── keystat
│ ├── default.nix
│ └── keystat.py
├── nixos-rebuild-shortcut
│ ├── default.nix
│ └── nixos.sh
├── nvfetcher.toml
├── prismlauncher-bwrap.nix
├── rime_latex.nix
├── show-headless-desktop.nix
├── systemd-run-app.nix
├── urw-base35-fonts.nix
├── wallpaper-blur.nix
├── wallpaper.nix
└── zsh-comma.nix
├── secrets
└── ssh.yaml
├── templates
├── ci-rust
│ └── .github
│ │ └── workflows
│ │ ├── ci.yaml
│ │ └── future_proof.yaml
├── rust-bin
│ ├── .gitignore
│ ├── Cargo.toml
│ └── src
│ │ └── main.rs
├── rust-criterion
│ └── benches
│ │ └── foo.rs
└── rust-lib
│ ├── .gitignore
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
└── typos.toml
/.gitignore:
--------------------------------------------------------------------------------
1 | *.tmp
2 | result
3 | result-*
4 | .envrc
5 |
--------------------------------------------------------------------------------
/.sops.yaml:
--------------------------------------------------------------------------------
1 | keys:
2 | - &oxa F90FFD6D585C2BA1F13DE8A97571654CF88E31C2
3 |
4 | - &invar age157zcs4687hmsd834xhvt66apf6v93ss3tt2l23x72lhtvpl69ggqeejgky
5 | - &blacksteel age1l9qly5vlx20uzrqvq8qygvcrtff64mgvqchet5uvs989upy5lugq4krj2c
6 | - &lithium age1telu43gwg7fucnph6x5mgl46yvaj9z0cuj2v4e5d8fxhlsvduqas7psujn
7 |
8 | creation_rules:
9 | - path_regex: secrets/ssh\.yaml$
10 | key_groups:
11 | - age:
12 | - *invar
13 | - *blacksteel
14 | pgp:
15 | - *oxa
16 |
17 | - path_regex: /invar/secret\.yaml$
18 | key_groups:
19 | - age:
20 | - *invar
21 | pgp:
22 | - *oxa
23 |
24 | - path_regex: /blacksteel/secret\.yaml$
25 | key_groups:
26 | - age:
27 | - *blacksteel
28 | pgp:
29 | - *oxa
30 |
31 | - path_regex: /lithium/secret\.yaml$
32 | key_groups:
33 | - age:
34 | - *lithium
35 | pgp:
36 | - *oxa
37 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.trimTrailingWhitespace": true,
3 | "files.insertFinalNewline": true,
4 | "files.trimFinalNewlines": true,
5 |
6 | "editor.tabSize": 2,
7 | }
8 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
2 |
3 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
4 |
5 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6 |
--------------------------------------------------------------------------------
/flake.lock:
--------------------------------------------------------------------------------
1 | {
2 | "nodes": {
3 | "blahrs": {
4 | "inputs": {
5 | "naersk": "naersk",
6 | "nixpkgs": [
7 | "nixpkgs"
8 | ],
9 | "rust-overlay": [
10 | "rust-overlay"
11 | ]
12 | },
13 | "locked": {
14 | "lastModified": 1744763289,
15 | "narHash": "sha256-WVZoYSexN5TVmK69pLUq6yo8WJLze7wYipEMaWmg0fQ=",
16 | "owner": "Blah-IM",
17 | "repo": "blahrs",
18 | "rev": "40e4a538866cceb2735e4cb5a40d8b774d02329e",
19 | "type": "github"
20 | },
21 | "original": {
22 | "owner": "Blah-IM",
23 | "repo": "blahrs",
24 | "type": "github"
25 | }
26 | },
27 | "cargo-bloated": {
28 | "inputs": {
29 | "nixpkgs": [
30 | "nixpkgs"
31 | ]
32 | },
33 | "locked": {
34 | "lastModified": 1746944458,
35 | "narHash": "sha256-ZlzonxjZIksRSDYyEmhqJD82wpDo+GYEKoyw0C+TeQc=",
36 | "owner": "oxalica",
37 | "repo": "cargo-bloated",
38 | "rev": "58f86063efa7febba25ffc73d7d83f31afcb5e47",
39 | "type": "github"
40 | },
41 | "original": {
42 | "owner": "oxalica",
43 | "repo": "cargo-bloated",
44 | "type": "github"
45 | }
46 | },
47 | "crane": {
48 | "locked": {
49 | "lastModified": 1731098351,
50 | "narHash": "sha256-HQkYvKvaLQqNa10KEFGgWHfMAbWBfFp+4cAgkut+NNE=",
51 | "owner": "ipetkov",
52 | "repo": "crane",
53 | "rev": "ef80ead953c1b28316cc3f8613904edc2eb90c28",
54 | "type": "github"
55 | },
56 | "original": {
57 | "owner": "ipetkov",
58 | "repo": "crane",
59 | "type": "github"
60 | }
61 | },
62 | "flake-parts": {
63 | "inputs": {
64 | "nixpkgs-lib": [
65 | "lanzaboote",
66 | "nixpkgs"
67 | ]
68 | },
69 | "locked": {
70 | "lastModified": 1730504689,
71 | "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=",
72 | "owner": "hercules-ci",
73 | "repo": "flake-parts",
74 | "rev": "506278e768c2a08bec68eb62932193e341f55c90",
75 | "type": "github"
76 | },
77 | "original": {
78 | "owner": "hercules-ci",
79 | "repo": "flake-parts",
80 | "type": "github"
81 | }
82 | },
83 | "flake-utils": {
84 | "inputs": {
85 | "systems": "systems"
86 | },
87 | "locked": {
88 | "lastModified": 1731533236,
89 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
90 | "owner": "numtide",
91 | "repo": "flake-utils",
92 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
93 | "type": "github"
94 | },
95 | "original": {
96 | "owner": "numtide",
97 | "repo": "flake-utils",
98 | "type": "github"
99 | }
100 | },
101 | "home-manager": {
102 | "inputs": {
103 | "nixpkgs": [
104 | "nixpkgs"
105 | ]
106 | },
107 | "locked": {
108 | "lastModified": 1748925027,
109 | "narHash": "sha256-BJ0qRIdvt5aeqm3zg/5if7b5rruG05zrSX3UpLqjDRk=",
110 | "owner": "nix-community",
111 | "repo": "home-manager",
112 | "rev": "cb809ec1ff15cf3237c6592af9bbc7e4d983e98c",
113 | "type": "github"
114 | },
115 | "original": {
116 | "owner": "nix-community",
117 | "repo": "home-manager",
118 | "type": "github"
119 | }
120 | },
121 | "lanzaboote": {
122 | "inputs": {
123 | "crane": "crane",
124 | "flake-compat": [
125 | "blank"
126 | ],
127 | "flake-parts": "flake-parts",
128 | "nixpkgs": [
129 | "nixpkgs"
130 | ],
131 | "pre-commit-hooks-nix": [
132 | "blank"
133 | ],
134 | "rust-overlay": [
135 | "rust-overlay"
136 | ]
137 | },
138 | "locked": {
139 | "lastModified": 1737639419,
140 | "narHash": "sha256-AEEDktApTEZ5PZXNDkry2YV2k6t0dTgLPEmAZbnigXU=",
141 | "owner": "nix-community",
142 | "repo": "lanzaboote",
143 | "rev": "a65905a09e2c43ff63be8c0e86a93712361f871e",
144 | "type": "github"
145 | },
146 | "original": {
147 | "owner": "nix-community",
148 | "ref": "v0.4.2",
149 | "repo": "lanzaboote",
150 | "type": "github"
151 | }
152 | },
153 | "meta-sifive": {
154 | "flake": false,
155 | "locked": {
156 | "lastModified": 1638461064,
157 | "narHash": "sha256-Toh80cXl+w1QFrbZnCP2Bjg2eN1V8vItACOO7/rWx0k=",
158 | "owner": "sifive",
159 | "repo": "meta-sifive",
160 | "rev": "dc0441b841dba14ead2cba8f6f7c086c11ad89b0",
161 | "type": "github"
162 | },
163 | "original": {
164 | "owner": "sifive",
165 | "ref": "2021.11.00",
166 | "repo": "meta-sifive",
167 | "type": "github"
168 | }
169 | },
170 | "naersk": {
171 | "inputs": {
172 | "nixpkgs": [
173 | "blahrs",
174 | "nixpkgs"
175 | ]
176 | },
177 | "locked": {
178 | "lastModified": 1739824009,
179 | "narHash": "sha256-fcNrCMUWVLMG3gKC5M9CBqVOAnJtyRvGPxptQFl5mVg=",
180 | "owner": "nix-community",
181 | "repo": "naersk",
182 | "rev": "e5130d37369bfa600144c2424270c96f0ef0e11d",
183 | "type": "github"
184 | },
185 | "original": {
186 | "owner": "nix-community",
187 | "repo": "naersk",
188 | "type": "github"
189 | }
190 | },
191 | "nixpkgs": {
192 | "locked": {
193 | "lastModified": 1748693115,
194 | "narHash": "sha256-StSrWhklmDuXT93yc3GrTlb0cKSS0agTAxMGjLKAsY8=",
195 | "owner": "NixOS",
196 | "repo": "nixpkgs",
197 | "rev": "910796cabe436259a29a72e8d3f5e180fc6dfacc",
198 | "type": "github"
199 | },
200 | "original": {
201 | "owner": "NixOS",
202 | "ref": "nixos-unstable",
203 | "repo": "nixpkgs",
204 | "type": "github"
205 | }
206 | },
207 | "nixpkgs-logseq": {
208 | "locked": {
209 | "lastModified": 1740560979,
210 | "narHash": "sha256-Vr3Qi346M+8CjedtbyUevIGDZW8LcA1fTG0ugPY/Hic=",
211 | "owner": "NixOS",
212 | "repo": "nixpkgs",
213 | "rev": "5135c59491985879812717f4c9fea69604e7f26f",
214 | "type": "github"
215 | },
216 | "original": {
217 | "owner": "NixOS",
218 | "repo": "nixpkgs",
219 | "rev": "5135c59491985879812717f4c9fea69604e7f26f",
220 | "type": "github"
221 | }
222 | },
223 | "nixpkgs-stable": {
224 | "locked": {
225 | "lastModified": 1720535198,
226 | "narHash": "sha256-zwVvxrdIzralnSbcpghA92tWu2DV2lwv89xZc8MTrbg=",
227 | "owner": "NixOS",
228 | "repo": "nixpkgs",
229 | "rev": "205fd4226592cc83fd4c0885a3e4c9c400efabb5",
230 | "type": "github"
231 | },
232 | "original": {
233 | "owner": "NixOS",
234 | "ref": "nixos-23.11",
235 | "repo": "nixpkgs",
236 | "type": "github"
237 | }
238 | },
239 | "nixpkgs-unmatched": {
240 | "locked": {
241 | "lastModified": 1640713360,
242 | "narHash": "sha256-MzrVpY1CvK5N60fW3ShYr/P7Gn2yxCBqlSLRJKjwAqs=",
243 | "owner": "oxalica",
244 | "repo": "nixpkgs",
245 | "rev": "68ffecb7b9ed47985dab86a7d7563ffb3f2a9155",
246 | "type": "github"
247 | },
248 | "original": {
249 | "owner": "oxalica",
250 | "ref": "test/unmatched",
251 | "repo": "nixpkgs",
252 | "type": "github"
253 | }
254 | },
255 | "nocargo": {
256 | "inputs": {
257 | "flake-utils": [
258 | "flake-utils"
259 | ],
260 | "nixpkgs": [
261 | "nixpkgs"
262 | ],
263 | "registry-crates-io": "registry-crates-io"
264 | },
265 | "locked": {
266 | "lastModified": 1745995660,
267 | "narHash": "sha256-Cca7/uDRwfo4UnPhZX31+vQ7chKr9nJsMvwykGllDVA=",
268 | "owner": "oxalica",
269 | "repo": "nocargo",
270 | "rev": "089f487c2c123454c8b9a381a99999b63c53d1d6",
271 | "type": "github"
272 | },
273 | "original": {
274 | "owner": "oxalica",
275 | "repo": "nocargo",
276 | "type": "github"
277 | }
278 | },
279 | "orb": {
280 | "inputs": {
281 | "nixpkgs": [
282 | "nixpkgs"
283 | ]
284 | },
285 | "locked": {
286 | "lastModified": 1744512440,
287 | "narHash": "sha256-MaMhYiO+zM0seg6144/mI9WK4ARUzaCHE2ugUCO/IoA=",
288 | "owner": "oxalica",
289 | "repo": "orb",
290 | "rev": "0156bb182d1647f025f1128d096c88c5df78f63d",
291 | "type": "github"
292 | },
293 | "original": {
294 | "owner": "oxalica",
295 | "repo": "orb",
296 | "type": "github"
297 | }
298 | },
299 | "registry-crates-io": {
300 | "flake": false,
301 | "locked": {
302 | "lastModified": 1704732624,
303 | "narHash": "sha256-FWX5JX33ievm6JuIEp1lI5EPndYt8s6anU+fQBYuFKc=",
304 | "owner": "rust-lang",
305 | "repo": "crates.io-index",
306 | "rev": "4445fa0011e6ff9989985651bec57eb4cbefcadd",
307 | "type": "github"
308 | },
309 | "original": {
310 | "owner": "rust-lang",
311 | "repo": "crates.io-index",
312 | "type": "github"
313 | }
314 | },
315 | "root": {
316 | "inputs": {
317 | "blahrs": "blahrs",
318 | "blank": [
319 | "nixpkgs"
320 | ],
321 | "cargo-bloated": "cargo-bloated",
322 | "flake-utils": "flake-utils",
323 | "home-manager": "home-manager",
324 | "lanzaboote": "lanzaboote",
325 | "meta-sifive": "meta-sifive",
326 | "nixpkgs": "nixpkgs",
327 | "nixpkgs-logseq": "nixpkgs-logseq",
328 | "nixpkgs-stable": "nixpkgs-stable",
329 | "nixpkgs-unmatched": "nixpkgs-unmatched",
330 | "nocargo": "nocargo",
331 | "orb": "orb",
332 | "rust-overlay": "rust-overlay",
333 | "secrets": "secrets",
334 | "sops-nix": "sops-nix"
335 | }
336 | },
337 | "rust-overlay": {
338 | "inputs": {
339 | "nixpkgs": [
340 | "nixpkgs"
341 | ]
342 | },
343 | "locked": {
344 | "lastModified": 1748918260,
345 | "narHash": "sha256-KhXNXQ5IDLvwwYfJ0pXDjwIuisZ2qM6F7fcXjIGZy/4=",
346 | "owner": "oxalica",
347 | "repo": "rust-overlay",
348 | "rev": "c9736155bc1eb7c7cf3a925920850e61c07ab22a",
349 | "type": "github"
350 | },
351 | "original": {
352 | "owner": "oxalica",
353 | "repo": "rust-overlay",
354 | "type": "github"
355 | }
356 | },
357 | "secrets": {
358 | "locked": {
359 | "lastModified": 1744799127,
360 | "narHash": "sha256-5n/OSVBcfeJI9tNS+laFv5+mX8gloTuM8TTXdWJrngs=",
361 | "path": "/home/oxa/storage/repo/nixos-config-secrets",
362 | "type": "path"
363 | },
364 | "original": {
365 | "path": "/home/oxa/storage/repo/nixos-config-secrets",
366 | "type": "path"
367 | }
368 | },
369 | "sops-nix": {
370 | "inputs": {
371 | "nixpkgs": [
372 | "nixpkgs"
373 | ]
374 | },
375 | "locked": {
376 | "lastModified": 1747603214,
377 | "narHash": "sha256-lAblXm0VwifYCJ/ILPXJwlz0qNY07DDYdLD+9H+Wc8o=",
378 | "owner": "Mic92",
379 | "repo": "sops-nix",
380 | "rev": "8d215e1c981be3aa37e47aeabd4e61bb069548fd",
381 | "type": "github"
382 | },
383 | "original": {
384 | "owner": "Mic92",
385 | "repo": "sops-nix",
386 | "type": "github"
387 | }
388 | },
389 | "systems": {
390 | "locked": {
391 | "lastModified": 1681028828,
392 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
393 | "owner": "nix-systems",
394 | "repo": "default",
395 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
396 | "type": "github"
397 | },
398 | "original": {
399 | "owner": "nix-systems",
400 | "repo": "default",
401 | "type": "github"
402 | }
403 | }
404 | },
405 | "root": "root",
406 | "version": 7
407 | }
408 |
--------------------------------------------------------------------------------
/flake.nix:
--------------------------------------------------------------------------------
1 | {
2 | description = "oxalica's NixOS configuration";
3 |
4 | inputs = {
5 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
6 | nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-23.11";
7 | nixpkgs-unmatched.url = "github:oxalica/nixpkgs/test/unmatched";
8 |
9 | # WAIT: https://github.com/NixOS/nixpkgs/pull/389363
10 | nixpkgs-logseq.url = "github:NixOS/nixpkgs/5135c59491985879812717f4c9fea69604e7f26f";
11 |
12 | # Placeholder.
13 | blank.follows = "nixpkgs";
14 |
15 | flake-utils.url = "github:numtide/flake-utils";
16 | home-manager = {
17 | url = "github:nix-community/home-manager";
18 | inputs.nixpkgs.follows = "nixpkgs";
19 | };
20 | rust-overlay = {
21 | url = "github:oxalica/rust-overlay";
22 | inputs.nixpkgs.follows = "nixpkgs";
23 | };
24 | nocargo = {
25 | url = "github:oxalica/nocargo";
26 | inputs.nixpkgs.follows = "nixpkgs";
27 | inputs.flake-utils.follows = "flake-utils";
28 | };
29 | sops-nix = {
30 | url = "github:Mic92/sops-nix";
31 | inputs.nixpkgs.follows = "nixpkgs";
32 | };
33 | lanzaboote = {
34 | url = "github:nix-community/lanzaboote/v0.4.2";
35 | inputs.pre-commit-hooks-nix.follows = "blank";
36 | inputs.flake-compat.follows = "blank";
37 | inputs.nixpkgs.follows = "nixpkgs";
38 | inputs.rust-overlay.follows = "rust-overlay";
39 | };
40 | orb = {
41 | url = "github:oxalica/orb";
42 | inputs.nixpkgs.follows = "nixpkgs";
43 | };
44 | blahrs = {
45 | url = "github:Blah-IM/blahrs";
46 | inputs.nixpkgs.follows = "nixpkgs";
47 | inputs.rust-overlay.follows = "rust-overlay";
48 | };
49 | cargo-bloated = {
50 | url = "github:oxalica/cargo-bloated";
51 | inputs.nixpkgs.follows = "nixpkgs";
52 | };
53 |
54 | meta-sifive = {
55 | url = "github:sifive/meta-sifive/2021.11.00";
56 | flake = false;
57 | };
58 |
59 | # Optional.
60 | secrets.url = "/home/oxa/storage/repo/nixos-config-secrets";
61 | };
62 |
63 | outputs = { self, nixpkgs, flake-utils, ... }@inputs: let
64 |
65 | inherit (nixpkgs) lib;
66 |
67 | overlays = {
68 | };
69 |
70 | nixosModules = {
71 | # Ref: https://github.com/dramforever/config/blob/63be844019b7ca675ea587da3b3ff0248158d9fc/flake.nix#L24-L28
72 | system-label = {
73 | system.configurationRevision = self.rev or null;
74 | system.nixos.label =
75 | if self.sourceInfo ? lastModifiedDate && self.sourceInfo ? shortRev
76 | then "${lib.substring 0 8 self.sourceInfo.lastModifiedDate}.${self.sourceInfo.shortRev}"
77 | else lib.warn "Repo is dirty, revision will not be available in system label" "dirty";
78 | };
79 |
80 | home-manager = { config, inputs, my, ... }: {
81 | imports = [ inputs.home-manager.nixosModules.home-manager ];
82 | home-manager = {
83 | useGlobalPkgs = true;
84 | useUserPackages = true;
85 | verbose = true;
86 | extraSpecialArgs = {
87 | inherit inputs my;
88 | super = config;
89 | };
90 | };
91 | };
92 |
93 | sops = { config, ... }: {
94 | imports = [ inputs.sops-nix.nixosModules.sops ];
95 | sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
96 | sops.gnupg.sshKeyPaths = [];
97 | sops.defaultSopsFile = ./nixos/${config.networking.hostName}/secret.yaml;
98 | };
99 | };
100 |
101 | mkSystem = name: system: nixpkgs: { extraModules ? [] }: nixpkgs.lib.nixosSystem {
102 | inherit system;
103 | specialArgs = {
104 | inputs = inputs // { inherit nixpkgs; };
105 | my = import ./my // {
106 | pkgs = self.packages.${system};
107 | };
108 | };
109 | modules = with nixosModules; [
110 | system-label
111 | { networking.hostName = lib.mkDefault name; }
112 | { nixpkgs.overlays = builtins.attrValues overlays; }
113 | ./nixos/${name}/configuration.nix
114 | ] ++ extraModules;
115 | };
116 |
117 | in {
118 | inherit overlays nixosModules;
119 |
120 | lib = import ./lib.nix {
121 | inherit (nixpkgs) lib;
122 | };
123 |
124 | nixosSystems = lib.mapAttrs
125 | (name: conf: conf.config.system.build.toplevel)
126 | self.nixosConfigurations;
127 |
128 | nixosConfigurations = {
129 | invar = mkSystem "invar" "x86_64-linux" inputs.nixpkgs {
130 | extraModules = with nixosModules; [ home-manager sops inputs.orb.nixosModules.orb ];
131 | };
132 |
133 | blacksteel = mkSystem "blacksteel" "x86_64-linux" inputs.nixpkgs {
134 | extraModules = with nixosModules; [ home-manager sops ];
135 | };
136 |
137 | lithium = mkSystem "lithium" "x86_64-linux" inputs.nixpkgs {
138 | extraModules = with nixosModules; [ sops inputs.blahrs.nixosModules.blahd ];
139 | };
140 |
141 | copper = mkSystem "copper" "x86_64-linux" inputs.nixpkgs-stable {
142 | extraModules = with nixosModules; [ sops ];
143 | };
144 |
145 | unmatched = mkSystem "unmatched" "riscv64-linux" inputs.nixpkgs-unmatched { };
146 | unmatched-cross = mkSystem "unmatched" "x86_64-linux" inputs.nixpkgs-unmatched {
147 | extraModules = [
148 | { nixpkgs.crossSystem.config = "riscv64-unknown-linux-gnu"; }
149 | ];
150 | };
151 |
152 | minimal-image-stable = mkSystem "minimal-image" "x86_64-linux" inputs.nixpkgs-stable { };
153 | minimal-image-unstable = mkSystem "minimal-image" "x86_64-linux" inputs.nixpkgs { };
154 | };
155 |
156 | images = {
157 | minimal-iso-stable = self.nixosConfigurations.minimal-image-stable.config.system.build.isoImage;
158 | minimal-iso-unstable = self.nixosConfigurations.minimal-image-unstable.config.system.build.isoImage;
159 | };
160 |
161 | templates = {
162 | rust-bin = {
163 | description = "A simple Rust project for binaries";
164 | path = ./templates/rust-bin;
165 | };
166 | rust-lib = {
167 | description = "A simple Rust project for libraries";
168 | path = ./templates/rust-lib;
169 | };
170 | rust-criterion = {
171 | description = "Criterion benchmark templates";
172 | path = ./templates/rust-criterion;
173 | };
174 | ci-rust = {
175 | description = "A sample GitHub CI setup for Rust projects";
176 | path = ./templates/ci-rust;
177 | };
178 | };
179 |
180 | } // flake-utils.lib.eachDefaultSystem (system: rec {
181 | packages = import ./pkgs {
182 | inherit lib inputs;
183 | pkgs = nixpkgs.legacyPackages.${system};
184 | };
185 |
186 | checks = packages;
187 |
188 | devShells.default =
189 | with nixpkgs.legacyPackages.${system};
190 | mkShellNoCC {
191 | packages = [ nvfetcher packages.nixos-rebuild-shortcut ];
192 | };
193 |
194 | devShells.rust-nightly =
195 | let
196 | pkgs = nixpkgs.legacyPackages.${system};
197 | now = inputs.rust-overlay.lastModifiedDate;
198 | date = "${lib.substring 0 4 now}-${lib.substring 4 2 now}-01";
199 | toolchain = inputs.rust-overlay.packages.${system}."rust-nightly_${date}".override {
200 | extensions = [
201 | "llvm-tools"
202 | "miri"
203 | "rust-src"
204 | ];
205 | };
206 | in pkgs.mkShellNoCC {
207 | packages = [ toolchain ];
208 | env.CARGO_TARGET_DIR = "/tmp/cargo-nightly-target";
209 | };
210 | });
211 | }
212 |
--------------------------------------------------------------------------------
/home/blacksteel.nix:
--------------------------------------------------------------------------------
1 | { lib, config, ... }:
2 |
3 | {
4 | programs.home-manager.enable = true;
5 |
6 | imports = [
7 | ./modules/alacritty.nix
8 | ./modules/direnv.nix
9 | ./modules/firefox.nix
10 | ./modules/git.nix
11 | ./modules/gpg.nix
12 | ./modules/lf.nix
13 | ./modules/mail.nix
14 | ./modules/nvim
15 | ./modules/programs.nix
16 | ./modules/rime-fcitx.nix
17 | ./modules/rust.nix
18 | ./modules/shell
19 | ./modules/tmux.nix
20 | ./modules/user-dirs.nix
21 | ./modules/vscode
22 | ];
23 |
24 | programs.alacritty.settings.font.size = lib.mkForce 10;
25 |
26 | home.file = let
27 | home = config.home.homeDirectory;
28 | link = path: config.lib.file.mkOutOfStoreSymlink "${home}/${path}";
29 | linkPersonal = path: link "storage/personal/${path}";
30 | in {
31 | ".local/share/fcitx5/rime/sync".source = linkPersonal "rime-sync";
32 | ".local/share/password-store".source = linkPersonal "password-store";
33 | };
34 |
35 | xdg.enable = true;
36 |
37 | home.stateVersion = "24.11";
38 | }
39 |
--------------------------------------------------------------------------------
/home/invar.nix:
--------------------------------------------------------------------------------
1 | { lib, pkgs, config, ... }:
2 |
3 | {
4 | programs.home-manager.enable = true;
5 |
6 | imports = [
7 | ./modules/alacritty.nix
8 | ./modules/direnv.nix
9 | ./modules/firefox.nix
10 | ./modules/git.nix
11 | ./modules/gpg.nix
12 | ./modules/helix
13 | ./modules/lf.nix
14 | ./modules/mail.nix
15 | ./modules/nvim
16 | ./modules/programs.nix
17 | ./modules/rime-fcitx.nix
18 | ./modules/rust.nix
19 | ./modules/shell
20 | ./modules/tmux.nix
21 | ./modules/user-dirs.nix
22 | ./modules/vscode
23 | ];
24 |
25 | # For Xwayland apps, ie. electron and steam.
26 | xresources.properties."Xft.dpi" = 120;
27 | # NB. The Xresources is not loaded automatically outside an X session.
28 | systemd.user.services."load-xresources" = {
29 | Unit.Description = "Load user X resources from '~/.Xresources'";
30 | Service.Type = "oneshot";
31 | Service.ExecStart = "${lib.getExe pkgs.xorg.xrdb} -load ${config.xresources.path}";
32 | Unit.After = [ "plasma-kwin_wayland.service" ];
33 | Install.WantedBy = [ "graphical-session.target" ];
34 | };
35 |
36 | xdg.enable = true;
37 |
38 | home.file = let
39 | link = path: config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/${path}";
40 | in {
41 | ".local/share/password-store".source = link "storage/5x-state/51-secret/51.10-password-store";
42 | ".local/share/fcitx5/rime/sync".source = link "storage/5x-state/55-backup/55.06-rime-directory";
43 | };
44 |
45 | systemd.user.services."rime-sync" = {
46 | Unit.Description = "Export rime dictionary";
47 | # https://github.com/fcitx/fcitx5-rime/issues/28#issuecomment-828484970
48 | Service.ExecStart = ''${pkgs.qt5.qttools.bin}/bin/qdbus org.fcitx.Fcitx5 /controller org.fcitx.Fcitx.Controller1.SetConfig "fcitx://config/addon/rime/sync" ""'';
49 | };
50 | systemd.user.timers."rime-sync" = {
51 | Timer = {
52 | OnCalendar = "*-*-* 03:00:00";
53 | Persistent = true;
54 | };
55 | Install.WantedBy = [ "timers.target" ];
56 | };
57 |
58 | home.stateVersion = "24.11";
59 | }
60 |
--------------------------------------------------------------------------------
/home/modules/alacritty.nix:
--------------------------------------------------------------------------------
1 | { pkgs, ... }:
2 | {
3 | programs.alacritty = {
4 | enable = true;
5 |
6 | # https://alacritty.org/config-alacritty.html
7 | settings = {
8 | general.import = [
9 | "${pkgs.vimPlugins.nightfox-nvim}/extra/nightfox/alacritty.toml"
10 | ];
11 |
12 | window.padding = { x = 4; y = 0; };
13 | # window.startup_mode = "Fullscreen";
14 | window.startup_mode = "Maximized";
15 |
16 | scrolling.history = 1000; # Should not matter since we have tmux.
17 | scrolling.multiplier = 5;
18 |
19 | font.size = 12;
20 |
21 | terminal.shell = {
22 | program = "${pkgs.tmux}/bin/tmux";
23 | args = [ "new-session" "-t" "main" ];
24 | };
25 |
26 | mouse.hide_when_typing = true;
27 | };
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/home/modules/direnv.nix:
--------------------------------------------------------------------------------
1 | { ... }:
2 | {
3 | programs.direnv = {
4 | enable = true;
5 | nix-direnv.enable = true;
6 | # bash
7 | stdlib = ''
8 | : ''${XDG_CACHE_HOME:=$HOME/.cache}
9 | declare -A direnv_layout_dirs
10 | direnv_layout_dir() {
11 | echo "''${direnv_layout_dirs[$PWD]:=$(
12 | echo -n "$XDG_CACHE_HOME"/direnv/layouts/
13 | echo -n "$PWD" | sha1sum | cut -d ' ' -f 1
14 | )}"
15 | }
16 | '';
17 | };
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/home/modules/firefox.nix:
--------------------------------------------------------------------------------
1 | { pkgs, ... }:
2 | {
3 | programs.firefox = {
4 | enable = true;
5 |
6 | package = pkgs.firefox.overrideAttrs (old: {
7 | nativeBuildInputs = old.nativeBuildInputs or [] ++ [ pkgs.zip pkgs.unzip ];
8 |
9 | # bash
10 | buildCommand = old.buildCommand + ''
11 | sed '/exec /i [[ "$XDG_SESSION_TYPE" == wayland ]] && export MOZ_ENABLE_WAYLAND=1' \
12 | --in-place "$out/bin/firefox"
13 |
14 | # Rebind C-W to C-S-W for closing tab.
15 | from1=''
16 | to__1=''
17 | from2=''
18 | to__2=' '
19 | file="$out/lib/firefox/browser/omni.ja"
20 | # The original file is a symlink.
21 | sed -E "s|$from1|$to__1|; s|$from2|$to__2|" "$file" >"$file.new"
22 | size1="$(stat -L -c '%s' "$file")"
23 | size2="$(stat -L -c '%s' "$file.new")"
24 | echo "$size1 $size2"
25 | [[ $size1 -eq $size2 ]]
26 | mv "$file.new" "$file"
27 | '';
28 | });
29 |
30 | profiles."main.profile" = {
31 | id = 0;
32 | isDefault = true;
33 |
34 | settings = {
35 | # Random config
36 | "browser.aboutConfig.showWarning" = false;
37 | "browser.toolbars.bookmarks.visibility" = "newtab";
38 | "browser.quitShortcut.disabled" = true; # Prevent C-Q to exit browser.
39 |
40 | # 2 = Set "Referer" only when full host name match.
41 | # See:
42 | "network.http.referer.XOriginPolicy" = 2;
43 |
44 | # Theme.
45 | "devtools.theme" = "auto";
46 | "extensions.activeThemeID" = "efault-theme@mozilla.org";
47 | "browser.display.use_system_colors" = true;
48 |
49 | # Let our font-config choose final fonts.
50 | "font.language.group" = "zh-CN";
51 | "font.name.monospace.zh-CN" = "monospace";
52 | "font.name.sans-serif.zh-CN" = "sans-serif";
53 | "font.name.serif.zh-CN" = "serif";
54 |
55 | # Hardware video decoding support.
56 | # See: https://wiki.archlinux.org/index.php/Firefox#Hardware_video_acceleration
57 | "gfx.webrender.all" = true;
58 | "media.ffmpeg.vaapi.enabled" = true;
59 |
60 | # Enable user chrome, which is by default disabled.
61 | "toolkit.legacyUserProfileCustomizations.stylesheets" = true;
62 |
63 | # Site isolation.
64 | "fission.autostart" = true;
65 | };
66 |
67 | # Hide tab
68 | userChrome = ''
69 | #main-window[tabsintitlebar="true"]:not([extradragspace="true"]) #TabsToolbar > .toolbar-items {
70 | opacity: 0;
71 | pointer-events: none;
72 | }
73 | #main-window:not([tabsintitlebar="true"]) #TabsToolbar {
74 | visibility: collapse !important;
75 | }
76 | '';
77 | };
78 |
79 | # For test.
80 | profiles."test.profile" = {
81 | id = 1;
82 | isDefault = false;
83 | };
84 | };
85 |
86 | # Host bridge for `pass` integration.
87 | programs.browserpass = {
88 | enable = true;
89 | browsers = [ "firefox" ];
90 | };
91 |
92 | # https://bugzilla.mozilla.org/show_bug.cgi?id=1699942
93 | home.packages = [ pkgs.arc-theme ];
94 | }
95 |
--------------------------------------------------------------------------------
/home/modules/git.nix:
--------------------------------------------------------------------------------
1 | { pkgs, my, ... }:
2 | {
3 | programs.git = {
4 | enable = true;
5 |
6 | ignores = [
7 | # vim swap files.
8 | "*~" "*.swp"
9 |
10 | # Editor local settings.
11 | ".vim/coc-settings.json"
12 | ".vscode"
13 |
14 | # Environments
15 | ".envrc"
16 | ];
17 |
18 | aliases = {
19 | br = "branch";
20 | cmt = "commit";
21 | co = "checkout";
22 | cp = "cherry-pick";
23 | d = "diff";
24 | dc = "diff --cached";
25 | dt = "difftool";
26 | l = "log";
27 | mt = "mergetool";
28 | st = "status";
29 | sub = "submodule";
30 | };
31 |
32 | extraConfig = {
33 | # User & signing.
34 | user.name = "oxalica";
35 | user.email = "oxalicc@pm.me";
36 | user.signingKey = my.gpg.fingerprint;
37 | tag.gpgSign = true;
38 |
39 | # Pull.
40 | pull.ff = "only";
41 |
42 | # Rebase.
43 | rebase.autoSquash = true;
44 | rebase.abbreviateCommands = true;
45 |
46 | # Diff & merge.
47 | diff.external = "${pkgs.difftastic}/bin/difft";
48 | diff.tool = "nvimdiff";
49 | difftool.prompt = false;
50 | merge.tool = "nvimdiff";
51 | merge.conflictstyle = "diff3";
52 | mergetool.prompt = false;
53 | rerere.enabled = true;
54 |
55 | # Pager.
56 | core.pager = "less";
57 | pager.branch = "less --quit-if-one-screen";
58 | pager.stash = "less --quit-if-one-screen";
59 |
60 | # Display.
61 | # Always show branches and tags for `git log` in `vim-fugitive`.
62 | # See: https://github.com/tpope/vim-fugitive/issues/1965
63 | log.decorate = true;
64 | # Show detailed diff by default for `git stash show`.
65 | stash.showPatch = true;
66 |
67 | # Misc.
68 | init.defaultBranch = "main";
69 | push.autoSetupRemote = true;
70 | advice.detachedHead = false;
71 | };
72 | };
73 | }
74 |
--------------------------------------------------------------------------------
/home/modules/gpg.nix:
--------------------------------------------------------------------------------
1 | { pkgs, my, ... }:
2 | {
3 | programs.gpg = {
4 | enable = true;
5 | settings = {
6 | default-key = my.gpg.fingerprint;
7 | personal-cipher-preferences = "AES256 AES192 AES TWOFISH";
8 | personal-digest-preferences = "SHA512 SHA256";
9 | personal-compress-preferences = "ZLIB BZIP2 Uncompressed";
10 | keyserver = "hkps://keys.openpgp.org";
11 | };
12 | scdaemonSettings = {
13 | deny-admin = true;
14 | };
15 | };
16 |
17 | services.gpg-agent = {
18 | enable = true;
19 | enableScDaemon = true;
20 | enableSshSupport = true;
21 |
22 | pinentry.package = pkgs.pinentry-qt;
23 | defaultCacheTtl = 600; # Default
24 | maxCacheTtl = 1800; # Default
25 | };
26 |
27 | programs.password-store = {
28 | enable = true;
29 | package = pkgs.pass.withExtensions (ps: [ ps.pass-audit ps.pass-import ps.pass-otp ]);
30 | };
31 |
32 | home.packages = [ pkgs.qtpass ];
33 | }
34 |
--------------------------------------------------------------------------------
/home/modules/helix/default.nix:
--------------------------------------------------------------------------------
1 | { lib, pkgs, inputs, ... }:
2 | let
3 | inherit (inputs.self.lib) toTOML;
4 | in {
5 | home.packages = with pkgs; [ helix ];
6 |
7 | xdg.configFile = {
8 | "helix/config.toml".text = toTOML {
9 | theme = "nightfox";
10 |
11 | editor = {
12 | scrolloff = 5;
13 | scroll-lines = 5;
14 | shell = [ "${lib.getBin pkgs.zsh}/bin/zsh" "-c" ];
15 | idle-timeout = 0;
16 |
17 | lsp.display-messages = true;
18 | auto-pairs = true;
19 |
20 | auto-format = false;
21 |
22 | cursor-shape = {
23 | normal = "block";
24 | insert = "bar";
25 | select = "block";
26 | };
27 | };
28 |
29 | keys = {
30 | normal = {
31 | "g"."h" = [ "select_mode" "goto_line_start" "normal_mode" ];
32 | "g"."l" = [ "select_mode" "goto_line_end" "normal_mode" ];
33 | "x" = "extend_to_line_bounds";
34 | "X" = "extend_line";
35 | };
36 | insert = {
37 | "C-space" = "completion";
38 | };
39 | };
40 | };
41 |
42 | "helix/themes/nightfox.toml".text = toTOML {
43 | palette = rec {
44 | black = "#393b44";
45 | black_bright = "#575860";
46 | black_dim = "#30323a";
47 | blue = "#719cd6";
48 | blue_bright = "#86abdc";
49 | blue_dim = "#6085b6";
50 | cyan = "#63cdcf";
51 | cyan_bright = "#7ad4d6";
52 | cyan_dim = "#54aeb0";
53 | green = "#81b29a";
54 | green_bright = "#8ebaa4";
55 | green_dim = "#6e9783";
56 | magenta = "#9d79d6";
57 | magenta_bright = "#baa1e2";
58 | magenta_dim = "#8567b6";
59 | orange = "#f4a261";
60 | orange_bright = "#f6b079";
61 | orange_dim = "#cf8a52";
62 | pink = "#d67ad2";
63 | pink_bright = "#dc8ed9";
64 | pink_dim = "#b668b2";
65 | red = "#c94f6d";
66 | red_bright = "#d16983";
67 | red_dim = "#ab435d";
68 | white = "#dfdfe0";
69 | white_bright = "#e4e4e5";
70 | white_dim = "#bebebe";
71 | yellow = "#dbc074";
72 | yellow_bright = "#e0c989";
73 | yellow_dim = "#baa363";
74 |
75 | comment = "#768390";
76 |
77 | bg = "#192330";
78 | bg_float = "#131a24";
79 | bg_cursorline = "#29394e";
80 | bg_border = "#415166";
81 | bg_sel = "#223249";
82 | bg_search = "#3a567d";
83 | bg_incsearch = green;
84 | fg = "#cdcecf";
85 | fg_status = "#aeafb0";
86 | fg_linenr = "#71839b";
87 |
88 |
89 | bracket = fg_status; # Brackets and Punctuation
90 | builtin_var = red; # Builtin variable
91 | builtin_type = cyan_bright; # Builtin type
92 | builtin_const = orange_bright; # Builtin const
93 | conditional = magenta_bright; # Conditional and loop
94 | const = orange_bright; # Constants, imports and booleans
95 | deprecated = fg_linenr; # Deprecated
96 | field = fg_status; # Field
97 | func = blue_bright; # Functions and Titles
98 | ident = cyan; # Identifiers
99 | keyword = magenta; # Keywords
100 | number = orange; # Numbers
101 | operator = fg_status; # Operators
102 | preproc = pink_bright; # PreProc
103 | regex = yellow_bright; # Regex
104 | statement = magenta; # Statements
105 | string = green; # Strings
106 | type = yellow; # Types
107 | variable = white; # Variables
108 |
109 | error = red;
110 | warning = yellow;
111 | info = blue;
112 | hint = green;
113 |
114 | added = green;
115 | removed = red;
116 | changed = yellow;
117 | };
118 |
119 | "ui.text".fg = "fg";
120 | "ui.text.focus".fg = "fg";
121 | "ui.background".bg = "bg";
122 | "ui.virtual.whitespace".fg = "bg_cursorline";
123 | # "ui.virtual.ruler" = { bg = "gray" }
124 |
125 | "ui.cursor".bg = "bg_incsearch";
126 | "ui.cursor.primary".modifiers = ["reversed"];
127 | "ui.cursor.select".bg = "bg_incsearch";
128 | "ui.cursor.match" = { fg = "yellow"; modifiers = ["bold"]; };
129 |
130 | "ui.selection".bg = "bg_sel";
131 | "ui.selection.primary".bg = "bg_search";
132 |
133 | "ui.linenr".fg = "fg_linenr";
134 | "ui.linenr.selected".fg = "yellow";
135 |
136 | "ui.statusline" = { fg = "fg_status"; bg = "bg_float"; };
137 | "ui.statusline.inactive" = { fg = "fg_linenr"; bg = "bg_float"; };
138 |
139 | "ui.help".bg = "bg_sel";
140 | "ui.popup".bg = "bg_sel";
141 | "ui.menu".bg = "bg_sel";
142 | "ui.menu.selected".bg = "bg_search";
143 | "ui.window".fg = "fg_linenr";
144 |
145 | "warning".fg = "warning";
146 | "error".fg = "error";
147 | "info".fg = "info";
148 | "hint".fg = "hint";
149 | "diagnostic".modifiers = ["underlined"];
150 |
151 | "diff.plus".fg = "added";
152 | "diff.minus".fg = "deleted";
153 | "diff.delta".fg = "changed";
154 |
155 | # "markup.heading" =
156 |
157 | "attribute".fg = "const";
158 | "comment".fg = "comment";
159 | "constant".fg = "const";
160 | "constant.builtin".fg = "builtin_const";
161 | "constant.character".fg = "string";
162 | "constant.character.escape" = { fg = "regex"; modifiers = ["bold"]; };
163 | "constant.numeric".fg = "number";
164 | "constructor".fg = "keyword";
165 | "function".fg = "func";
166 | "function.builtin".fg = "builtin_var";
167 | "function.macro".fg = "preproc";
168 | "keyword".fg = "keyword";
169 | "keyword.control".fg = "conditional";
170 | "keyword.control.import".fg = "preproc";
171 | "keyword.directive".fg = "constant";
172 | "keyword.function".fg = "builtin_var";
173 | "keyword.operator".fg = "operator";
174 | "label".fg = "conditional";
175 | "namespace".fg = "builtin_type";
176 | "operator".fg = "operator";
177 | "property".fg = "field";
178 | "special".fg = "func";
179 | "string".fg = "string";
180 | "string.regexp".fg = "regex";
181 | "string.special".fg = "func";
182 | "type".fg = "type";
183 | "variable".fg = "variable";
184 | "variable.builtin".fg = "builtin_var";
185 | "variable.other.member".fg = "field";
186 | "variable.parameter".fg = "builtin_var";
187 |
188 | # "markup.heading".fg = "";
189 | };
190 | };
191 | }
192 |
--------------------------------------------------------------------------------
/home/modules/lf.nix:
--------------------------------------------------------------------------------
1 | {
2 | programs.lf = {
3 | enable = true;
4 |
5 | settings = {
6 | scrolloff = 5;
7 | };
8 |
9 | keybindings = {
10 | # Mouse.
11 | "" = "scroll-up";
12 | "" = "scroll-down";
13 |
14 | "" = "delete";
15 | D = "delete";
16 | x = "cut";
17 | "" = "set hidden!";
18 | };
19 |
20 | extraConfig = ''
21 | set mouse
22 | set scrolloff 5
23 | '';
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/home/modules/mail.nix:
--------------------------------------------------------------------------------
1 | { pkgs, ... }:
2 | {
3 | home.packages = with pkgs; [
4 | (thunderbird.overrideAttrs (old: {
5 | # bash
6 | buildCommand = old.buildCommand + ''
7 | sed '/exec /i [[ "$XDG_SESSION_TYPE" == wayland ]] && export MOZ_ENABLE_WAYLAND=1' \
8 | --in-place "$out/bin/thunderbird"
9 | '';
10 | }))
11 | ];
12 | }
13 |
--------------------------------------------------------------------------------
/home/modules/nvim/default.nix:
--------------------------------------------------------------------------------
1 | { lib, config, pkgs, my, ... }:
2 | let
3 | inherit (pkgs) vimPlugins;
4 |
5 | vimrc = builtins.readFile ./vimrc.vim;
6 |
7 | vimrc' = builtins.replaceStrings
8 | ["@fcitx5-remote@"]
9 | ["${lib.getBin pkgs.fcitx5}/bin/fcitx5-remote"]
10 | vimrc;
11 |
12 | plugins =
13 | map (x: vimPlugins.${lib.elemAt x 0})
14 | (lib.filter (x: lib.isList x)
15 | (builtins.split ''" plugin: ([A-Za-z_-]+)'' vimrc)) ++
16 | cocPlugins ++ [
17 | (pkgs.runCommandNoCC "koka-vim" { } ''
18 | cp -r ${pkgs.koka.src}/support/vim $out
19 | '')
20 | ];
21 |
22 | coc-rust-analyzer = my.pkgs.coc-rust-analyzer-fix-snippet;
23 |
24 | cocPlugins = with vimPlugins; [
25 | coc-eslint
26 | coc-json
27 | coc-pyright
28 | coc-rust-analyzer
29 | coc-sumneko-lua
30 | coc-tsserver
31 | ];
32 |
33 | cocSettings = {
34 | "coc.preferences.currentFunctionSymbolAutoUpdate" = true;
35 | "coc.preferences.extensionUpdateCheck" = "never";
36 | "diagnostic.errorSign" = "⮾ ";
37 | "diagnostic.hintSign" = "💡";
38 | "diagnostic.infoSign" = "🛈 ";
39 | "diagnostic.warningSign" = "⚠";
40 | "links.tooltip" = true;
41 | "semanticTokens.enable" = true;
42 | "workspace.ignoredFolders" = [
43 | "${config.xdg.cacheHome}/cargo/**"
44 | "/nix/store/**"
45 | ];
46 |
47 | "[rust]"."coc.preferences.formatOnSave" = true;
48 |
49 | "rust-analyzer.updates.checkOnStartup" = false;
50 | "rust-analyzer.server.path" = "rust-analyzer"; # Use relative path, so it prefers direnv if possible.
51 | "rust-analyzer.check.command" = "clippy";
52 | "rust-analyzer.imports.granularity.group" = "module";
53 | "rust-analyzer.semanticHighlighting.strings.enable" = false;
54 | "rust-analyzer.inlayHints.parameterHints.enable" = false;
55 |
56 | "sumneko-lua.checkUpdate" = false;
57 | # https://github.com/xiyaowong/coc-sumneko-lua/issues/22#issuecomment-1252284377
58 | "sumneko-lua.serverDir" = "${pkgs.sumneko-lua-language-server}/share/lua-language-server";
59 | "Lua.misc.parameters" = [
60 | "--metapath=${config.xdg.cacheHome}/sumneko_lua/meta"
61 | "--logpath=${config.xdg.cacheHome}/sumneko_lua/log"
62 | ];
63 |
64 | languageserver = {
65 | nix = {
66 | # Use from PATH to allow overriding.
67 | command = "nil";
68 | filetypes = [ "nix" ];
69 | rootPatterns = [ "flake.nix" ".git" ];
70 | settings.nil = {
71 | formatting.command = [ (lib.getExe pkgs.nixfmt-rfc-style) "-" ];
72 | };
73 | };
74 | koka = {
75 | filetypes = [ "koka" ];
76 | command = "koka";
77 | args = [ "--language-server" "--lsstdio" ];
78 | };
79 | };
80 | };
81 |
82 | in
83 | {
84 | programs.neovim = {
85 | enable = true;
86 | withRuby = false;
87 | inherit plugins;
88 | extraConfig = vimrc';
89 |
90 | coc = {
91 | enable = true;
92 | settings = cocSettings;
93 | };
94 | };
95 |
96 | home.sessionVariables.EDITOR = "nvim";
97 |
98 | home.packages = with pkgs; [
99 | nil
100 | rust-analyzer
101 | watchman # Required by coc.nvim for file watching.
102 | fzf bat # Required by fzf.vim.
103 | nodejs # FIXME: coc.nvim cannot find node executable
104 | ];
105 |
106 | # Forbid some LSP (eg. pyright) from watching big directories.
107 | home.file.".watchman.json".text = builtins.toJSON {
108 | ignore_dirs = [
109 | "/" "/nix" "/nix/store"
110 | "${config.home.homeDirectory}/storage"
111 | "${config.home.homeDirectory}/archive"
112 | ];
113 | };
114 | }
115 |
--------------------------------------------------------------------------------
/home/modules/nvim/vimrc.vim:
--------------------------------------------------------------------------------
1 | " Settings. {{{1
2 |
3 | " Core.
4 | set fileencodings=ucs-bom,utf-8,gb18030,latin1
5 | set foldmethod=marker
6 | set lazyredraw
7 | set mouse=a
8 | set scrolloff=5
9 | set undofile
10 |
11 | " No undo for tmp files
12 | autocmd BufWritePre /tmp/*,/var/tmp/*,/dev/shm/* setlocal noundofile nobackup
13 |
14 | " Input.
15 | set shiftwidth=4
16 | set softtabstop=-1 " Follows shiftwidth
17 | set shiftround
18 | set expandtab
19 | set ttimeoutlen=1
20 | set updatetime=500 " coc.nvim relies on relatively fast CursorHold.
21 |
22 | " Render.
23 | set number
24 | set relativenumber
25 | set cursorline
26 | set hlsearch
27 | set signcolumn=yes " Always show.
28 | set list
29 | set listchars=tab:-->,extends:>,precedes:<
30 |
31 | " Highlight on yank.
32 | autocmd TextYankPost * silent! lua vim.highlight.on_yank {higroup="IncSearch", timeout=200}
33 |
34 | " TMUX takes precedence. Also enable OSC 52 clipboard via `-w`.
35 | if !empty($TMUX)
36 | let g:clipboard = {
37 | \ 'name': 'tmux',
38 | \ 'copy': {
39 | \ '+': ['tmux', 'load-buffer', '-w', '-'],
40 | \ '*': ['tmux', 'load-buffer', '-w', '-'],
41 | \ },
42 | \ 'paste': {
43 | \ '+': ['tmux', 'save-buffer', '-'],
44 | \ '*': ['tmux', 'save-buffer', '-'],
45 | \ },
46 | \ }
47 | endif
48 |
49 | " Status line.
50 | " Reference: https://github.com/lilydjwg/dotvim/blob/07c4467153f2f44264fdb0e23c085b56cad519db/vimrc#L548
51 | " "+y
72 |
73 | " Move lines.
74 | nmap :move+
75 | nmap :move-2
76 | vmap :move'>+gv
77 | vmap :move'<-2gv
78 |
79 | " Mouse.
80 | nmap
81 | nmap
82 | imap
83 | imap
84 |
85 | " Options
86 | nmap set relativenumber!\|set relativenumber?
87 | nmap set wrap!\|set wrap?
88 | nmap nohlsearch
89 |
90 | " Commands. {{{1
91 | command! -nargs=0 Sudow w !sudo tee % >/dev/null
92 | command! -nargs=* W w
93 |
94 | " Plugins. {{{1
95 |
96 | " plugin: vim-repeat
97 |
98 | " plugin: plenary-nvim
99 |
100 | " plugin: vim-nix
101 |
102 | " plugin: editorconfig-vim
103 | let g:EditorConfig_exclude_patterns = ['fugitive://.*', 'scp://.*']
104 |
105 | " plugin: fcitx-vim
106 | let g:fcitx5_remote = '@fcitx5-remote@'
107 |
108 | " plugin: fzf-vim {{{
109 | let g:fzf_history_dir = stdpath('cache') . '/fzf_history'
110 |
111 | function! s:build_quickfix_list(lines)
112 | call setqflist(map(copy(a:lines), '{ "filename": v:val }'))
113 | copen
114 | cc
115 | endfunction
116 | let g:fzf_action = {
117 | \ 'ctrl-q': function('s:build_quickfix_list'),
118 | \ 'ctrl-t': 'tab split',
119 | \ 'ctrl-s': 'split',
120 | \ 'ctrl-v': 'vsplit',
121 | \ }
122 |
123 | function! FZFRg(pat, args, fullscreen)
124 | let args = "--column --line-number --no-heading --color=always " . a:args
125 | call fzf#vim#grep("rg " . args . " -- " . shellescape(a:pat), 1, fzf#vim#with_preview(), a:fullscreen)
126 | endfunction
127 | command -nargs=1 -bang RgF call FZFRg(, "--fixed-strings", 0)
128 | nmap ff call fzf#vim#files("", fzf#vim#with_preview(), 0)
129 | nmap f. call fzf#vim#files(expand('%:h'), fzf#vim#with_preview(), 0)
130 | nmap fp call fzf#vim#files(expand('%:h:h'), fzf#vim#with_preview(), 0)
131 | nmap fw call FZFRg(expand(''), '--fixed-strings --word-regexp', 0)
132 | nmap fb Buffers
133 | nmap fh Helptags
134 | nmap fr :Rg
135 | "}}}
136 |
137 | " plugin: gitgutter
138 |
139 | " plugin: leap-nvim
140 | lua require('leap').add_default_mappings()
141 |
142 | " plugin: markdown-preview-nvim
143 |
144 | " plugin: vim-commentary {{{
145 | nmap c CommentaryLine
146 | xmap c Commentary
147 | "}}}
148 |
149 | " plugin: vim-better-whitespace {{{
150 | let g:show_spaces_that_precede_tabs = 1
151 | "}}}
152 |
153 | " plugin: vim-fugitive {{{
154 | " plugin: fugitive-gitlab-vim
155 | " plugin: vim-rhubarb
156 |
157 | nmap tab Git
158 | command -nargs=* GL tab Git log --max-count=500
159 | "}}}
160 |
161 | " plugin: vim-sandwich {{{
162 | " Use vim-surround keymap.
163 | runtime PACK macros/sandwich/keymap/surround.vim
164 | " Use behavior of vim-surround for left parenthesis input. https://github.com/machakann/vim-sandwich/issues/44
165 | let g:sandwich#recipes += [
166 | \ {'buns': ['{ ', ' }'], 'nesting': 1, 'match_syntax': 1, 'kind': ['add', 'replace'], 'action': ['add'], 'input': ['{']},
167 | \ {'buns': ['[ ', ' ]'], 'nesting': 1, 'match_syntax': 1, 'kind': ['add', 'replace'], 'action': ['add'], 'input': ['[']},
168 | \ {'buns': ['( ', ' )'], 'nesting': 1, 'match_syntax': 1, 'kind': ['add', 'replace'], 'action': ['add'], 'input': ['(']},
169 | \ {'buns': ['{\s*', '\s*}'], 'nesting': 1, 'regex': 1, 'match_syntax': 1, 'kind': ['delete', 'replace', 'textobj'], 'action': ['delete'], 'input': ['{']},
170 | \ {'buns': ['\[\s*', '\s*\]'], 'nesting': 1, 'regex': 1, 'match_syntax': 1, 'kind': ['delete', 'replace', 'textobj'], 'action': ['delete'], 'input': ['[']},
171 | \ {'buns': ['(\s*', '\s*)'], 'nesting': 1, 'regex': 1, 'match_syntax': 1, 'kind': ['delete', 'replace', 'textobj'], 'action': ['delete'], 'input': ['(']},
172 | \ ]
173 | "}}}
174 |
175 | " plugin: crates-nvim {{{
176 | " Should be setup early, or it cannot trigger autocmd inside autocmd.
177 | lua require('crates').setup()
178 | "}}}
179 |
180 | " plugin: nightfox-nvim {{{
181 | lua < call CocAction('diagnosticToggle')
212 |
213 | " Completion.
214 | inoremap coc#pum#visible() ? coc#pum#confirm() : "\"
215 | inoremap coc#refresh()
216 | inoremap "\u\\=coc#on_enter()\"
217 |
218 |
219 | " Motion.
220 | nmap gd (coc-definition)
221 | nmap gy (coc-type-definition)
222 | nmap gi (coc-implementation)
223 | nmap gr (coc-references)
224 |
225 | nmap [d (coc-diagnostic-prev)
226 | nmap ]d (coc-diagnostic-next)
227 |
228 | nmap (coc-range-select)
229 | xmap (coc-range-select)
230 |
231 | xmap if (coc-funcobj-i)
232 | omap if (coc-funcobj-i)
233 | xmap af (coc-funcobj-a)
234 | omap af (coc-funcobj-a)
235 | xmap ic (coc-classobj-i)
236 | omap ic (coc-classobj-i)
237 | xmap ac (coc-classobj-a)
238 | omap ac (coc-classobj-a)
239 |
240 | " Scrolling.
241 | nnoremap coc#float#has_scroll() ? coc#float#scroll(1) : "\"
242 | nnoremap coc#float#has_scroll() ? coc#float#scroll(0) : "\"
243 | inoremap coc#float#has_scroll() ? "\=coc#float#scroll(1)\" : "\"
244 | inoremap coc#float#has_scroll() ? "\=coc#float#scroll(0)\" : "\"
245 | vnoremap coc#float#has_scroll() ? coc#float#scroll(1) : "\"
246 | vnoremap coc#float#has_scroll() ? coc#float#scroll(0) : "\"
247 |
248 | " Actions.
249 | nmap r (coc-rename)
250 | nmap a (coc-codeaction-cursor)
251 | xmap a (coc-codeaction-selected)
252 | nmap q (coc-fix-current)
253 | nmap l (coc-codelens-action)
254 |
255 | nmap gl (coc-openlink)
256 |
257 | nmap F (coc-format)
258 | xmap F (coc-format-selected)
259 |
260 | " Hover.
261 | nnoremap call CocActionAsync('doHover')
262 | nnoremap d call CocActionAsync('definitionHover')
263 |
264 | " CoCList.
265 | nnoremap fd CocList diagnostics
266 | nnoremap fc CocList commands
267 | nnoremap fo CocList outline
268 | " Workspace symbols.
269 | nnoremap fs CocList -I symbols
270 | " Resume latest coc list.
271 | nnoremap fp CocListResume
272 |
273 | augroup coc_autocmd
274 | autocmd!
275 | " Highlight the symbol and its references when holding the cursor.
276 | autocmd CursorHold * silent call CocActionAsync('highlight')
277 | " Setup formatexpr specified filetype(s).
278 | autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
279 | " Update signature help on jump placeholder.
280 | autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
281 | augroup end
282 |
283 | " Additional highlighting.
284 | highlight! link CocSemTypeAsync Conditional
285 | highlight! link CocSemTypeControlFlow Conditional
286 | highlight! link CocSemTypeDocumentation SpecialComment
287 | highlight! link CocSemTypeLifetime Label
288 | highlight! link CocSemTypeEnum Constant
289 | highlight! link CocSemTypeEnumMember Constant
290 |
291 | highlight! link CocSemModBuiltin @variable.builtin
292 | highlight! link CocSemTypeModBuiltinConstant @constant.builtin
293 | highlight! link CocSemTypeModBuiltinFunction @function.builtin
294 | highlight! link CocSemTypeModBuiltinNamespace @namespace.builtin
295 | highlight! link CocSemTypeBuiltinType @type.builtin
296 | highlight! link CocSemTypeConstant Constant
297 |
298 | if !empty(synIDattr(hlID('@field'), 'fg'))
299 | execute "highlight CocSemWithAttribute gui=underline guifg="..synIDattr(hlID('@field'), 'fg')
300 | endif
301 |
302 | " vim:shiftwidth=2:softtabstop=2:expandtab
303 |
--------------------------------------------------------------------------------
/home/modules/programs.nix:
--------------------------------------------------------------------------------
1 | { lib, pkgs, super, my, inputs, ... }:
2 |
3 | let
4 | myPython = pkgs.python3.withPackages (ps: with ps; [
5 | aiohttp
6 | numpy
7 | pylint
8 | pyyaml
9 | requests
10 | toml
11 | z3
12 | ]);
13 |
14 | obs = pkgs.wrapOBS {
15 | plugins = with pkgs.obs-studio-plugins; [
16 | obs-pipewire-audio-capture
17 | obs-vaapi
18 | ];
19 | };
20 |
21 | prismlauncher = my.pkgs.prismlauncher-bwrap.override {
22 | jdks = [ pkgs.jdk21 pkgs.jdk17 ];
23 | };
24 |
25 | logseq = (import inputs.nixpkgs-logseq {
26 | inherit (pkgs) system;
27 | config.permittedInsecurePackages = [ "electron-27.3.11" ];
28 | }).logseq;
29 |
30 | in {
31 | home.packages = with pkgs; [
32 | # Console
33 | scc bubblewrap difftastic typos # Random stuff
34 | xsel wl-clipboard # CLI-Desktop
35 | beancount # Accounting
36 | tealdeer man-pages # Manual
37 | sops # Sops
38 |
39 | # GUI
40 | libreoffice mpv logseq lyx dwarfs # Files
41 | electron-cash
42 | electrum
43 | monero-gui
44 | # steam is enabled system-wide.
45 | prismlauncher # Games
46 | telegram-desktop nheko # Messaging
47 | obs # Recording
48 | my.pkgs.systemd-run-app
49 | syncplay
50 |
51 | # Dev
52 | cachix patchelf nixpkgs-review nix-update nix-output-monitor nixfmt-rfc-style # Nix utils
53 | gcc ghc myPython koka # Compiler & interpreters
54 | gdb # Debugger
55 | sqlite-interactive # sqlite
56 | super.boot.kernelPackages.perf hyperfine
57 | ];
58 |
59 | programs.feh.enable = true;
60 |
61 | xdg.configFile = let
62 | gen = path: {
63 | name = "autostart/${builtins.unsafeDiscardStringContext (builtins.baseNameOf path)}";
64 | value.source = path;
65 | };
66 | in lib.listToAttrs (map gen [
67 | "${pkgs.firefox}/share/applications/firefox.desktop"
68 | "${pkgs.telegram-desktop}/share/applications/org.telegram.desktop.desktop"
69 | "${pkgs.nheko}/share/applications/nheko.desktop"
70 | "${pkgs.thunderbird}/share/applications/thunderbird.desktop"
71 | ]);
72 | }
73 |
--------------------------------------------------------------------------------
/home/modules/rime-fcitx.nix:
--------------------------------------------------------------------------------
1 | { lib, config, pkgs, ... }:
2 | let
3 | toYAML = builtins.toJSON;
4 | buildDir = "${config.xdg.cacheHome}/fcitx5-rime";
5 | onChange = ''
6 | rimeSettingChanged=1
7 | '';
8 | in {
9 | home.activation.setupRimeCacheDirectory = lib.hm.dag.entryAfter [ "writeBoundary" "onFilesChange" ] ''
10 | run mkdir -p "${buildDir}"
11 | if [[ -v rimeSettingChanged ]]; then
12 | run rm -rf "${buildDir}"/*
13 | fi
14 | if [[ -z "$(ls ${buildDir})" ]]; then
15 | run ${pkgs.qt5.qttools.bin}/bin/qdbus org.fcitx.Fcitx5 /controller org.fcitx.Fcitx.Controller1.SetConfig "fcitx://config/addon/rime/deploy" ""
16 | fi
17 | '';
18 |
19 | xdg.dataFile = {
20 | "fcitx5/rime/build".source = config.lib.file.mkOutOfStoreSymlink buildDir;
21 |
22 | "fcitx5/rime/default.custom.yaml" = {
23 | inherit onChange;
24 | text = toYAML {
25 | patch = {
26 | "menu/page_size" = 9;
27 | schema_list = [
28 | { schema = "double_pinyin"; }
29 | { schema = "latex"; }
30 | ];
31 | };
32 | };
33 | };
34 |
35 | "fcitx5/rime/double_pinyin.custom.yaml" = {
36 | inherit onChange;
37 | text = toYAML {
38 | __include = "emoji_suggestion:/";
39 | "switches/@2/reset" = 1;
40 | };
41 | };
42 | };
43 | }
44 |
--------------------------------------------------------------------------------
/home/modules/rust.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | pkgs,
5 | inputs,
6 | my,
7 | ...
8 | }:
9 |
10 | let
11 | inherit (inputs.self.lib) toTOML;
12 |
13 | cargo-machete = my.pkgs.cargo-machete-no-spam;
14 |
15 | cargoConfig = {
16 | # Ref: https://doc.rust-lang.org/cargo/reference/registry-authentication.html#recommended-configuration
17 | registry.global-credential-providers = [
18 | "cargo:token"
19 | "cargo:libsecret"
20 | ];
21 |
22 | install.root = "${config.home.homeDirectory}/.local";
23 |
24 | build.target-dir = "${config.xdg.cacheHome}/cargo/target";
25 |
26 | # Prefer MSRV-compatible dependency versions.
27 | resolver.incompatible-rust-versions = "fallback";
28 |
29 | target = {
30 | "${pkgs.hostPlatform.rust.rustcTarget}".linker = gcc-lld;
31 | "riscv64gc-unknown-linux-gnu".linker = "riscv64-unknown-linux-gnu-gcc";
32 | "aarch64-unknown-linux-gnu".linker = "aarch64-unknown-linux-gnu-gcc";
33 | };
34 | };
35 |
36 | # Seems it reject missing fields.
37 | # https://github.com/rustsec/rustsec/blob/5058319167c0a86eae7bf25ebc820a8eefeb1c55/cargo-audit/audit.toml.example
38 | cargoAudit = {
39 | database = {
40 | path = "${config.xdg.cacheHome}/cargo/advisory-db";
41 | url = "https://github.com/RustSec/advisory-db.git";
42 | fetch = true;
43 | stale = false;
44 | };
45 | };
46 |
47 | # `--no-rosegment` is required for flamegraph
48 | # https://github.com/flamegraph-rs/flamegraph#cargo-flamegraph
49 | gcc-lld = pkgs.writeShellScript "gcc-lld" ''
50 | export PATH="${pkgs.llvmPackages_latest.bintools}/bin''${PATH:+:}$PATH"
51 | exec ${lib.getExe pkgs.gcc} -fuse-ld=lld -Wl,--no-rosegment "$@"
52 | '';
53 |
54 | rust-overlay-pkgs = inputs.rust-overlay.packages.${pkgs.system};
55 | curDate = inputs.rust-overlay.lastModifiedDate;
56 | # Use nightly rustfmt from yyyy-mm-01.
57 | rustfmt =
58 | rust-overlay-pkgs."rust-nightly_${lib.substring 0 4 curDate}-${lib.substring 4 2 curDate}-01".availableComponents.rustfmt;
59 |
60 | rustToolchain = (
61 | rust-overlay-pkgs.rust.override {
62 | extensions = [
63 | "rust-src"
64 | "llvm-tools" # For cargo-llvm-cov
65 | ];
66 | targets = [
67 | "aarch64-unknown-linux-gnu"
68 | "riscv64gc-unknown-linux-gnu"
69 | "wasm32-unknown-unknown"
70 | "x86_64-pc-windows-msvc"
71 | ];
72 | }
73 | );
74 |
75 | in
76 | {
77 | home.packages = with pkgs; [
78 | (lib.hiPrio rustfmt)
79 | rustToolchain
80 |
81 | cargo-audit
82 | inputs.cargo-bloated.packages.${pkgs.system}.default
83 | cargo-deny
84 | cargo-expand
85 | cargo-flamegraph
86 | cargo-hack
87 | cargo-insta
88 | cargo-license
89 | cargo-llvm-cov
90 | cargo-machete
91 | cargo-outdated
92 | cargo-show-asm
93 | ];
94 |
95 | # Setup cargo directories.
96 | # https://doc.rust-lang.org/cargo/commands/cargo.html?highlight=cargo_home#files
97 | home.sessionVariables."CARGO_HOME" = "${pkgs.runCommandLocal "cargo-home"
98 | {
99 | cargoConfig = toTOML cargoConfig;
100 | cargoAudit = toTOML cargoAudit;
101 | }
102 | ''
103 | mkdir -p $out
104 | ln -st $out "${config.xdg.cacheHome}"/cargo/{registry,git,.global-cache,.package-cache,.package-cache-mutate,advisory-dbs}
105 | ln -st $out "${config.xdg.configHome}"/cargo/credentials.toml
106 | echo -n "$cargoConfig" >$out/config.toml
107 | echo -n "$cargoAudit" >$out/audit.toml
108 | ''
109 | }";
110 |
111 | home.activation.setupCargoDirectories = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
112 | run mkdir -p "${config.xdg.configHome}"/cargo "${config.xdg.cacheHome}"/cargo/{registry,git,advisory-dbs}
113 | if [[ ! -e "${config.xdg.configHome}"/cargo/credentials.toml ]]; then
114 | run touch -a "${config.xdg.configHome}"/cargo/credentials.toml
115 | fi
116 | for f in .global-cache .package-cache .package-cache-mutate; do
117 | if [[ ! -e "${config.xdg.cacheHome}"/cargo/"$f" ]]; then
118 | run touch -a "${config.xdg.cacheHome}"/cargo/"$f"
119 | fi
120 | done
121 | '';
122 | }
123 |
--------------------------------------------------------------------------------
/home/modules/shell/cmds.zsh:
--------------------------------------------------------------------------------
1 | local DEFAULT_LS_ARGS=(
2 | --escape
3 | --color=auto
4 | --classify
5 | --time-style=iso
6 | --human-readable
7 | --kibibytes
8 | )
9 | alias l="command ls $DEFAULT_LS_ARGS"
10 | alias la="command ls $DEFAULT_LS_ARGS --almost-all"
11 | alias ll="command ls $DEFAULT_LS_ARGS -l"
12 | alias lla="command ls $DEFAULT_LS_ARGS -l --almost-all"
13 |
14 | alias n="nix"
15 | alias nb="nix build"
16 | alias nf="nix flake"
17 | alias nr="nix repl"
18 | alias nrp="nix repl -f ''"
19 |
20 | alias v="nvim"
21 | alias g="git"
22 | alias py="python"
23 | alias rl="readlink"
24 | alias rp="realpath"
25 | alias t="bsdtar"
26 | alias hex="hexdump -C"
27 | alias o="xdg-open"
28 | alias reset="tput reset"
29 | alias mv="mv --no-copy"
30 |
31 | # List tree.
32 | lt() {
33 | # `-C` for `color=always`.
34 | tree -C $@ | eval $PAGER
35 | }
36 |
37 | # Clipboard input/output.
38 | +() {
39 | local board
40 | if [[ "$XDG_SESSION_TYPE" == wayland ]]; then
41 | case $1 in
42 | p) board=--primary;;
43 | b|"") ;;
44 | *) echo "Invalid argument" >&2; return 1;;
45 | esac
46 | if [[ -t 0 ]]; then # stdin is tty, print clipboard
47 | wl-paste $board
48 | elif [[ -t 1 ]]; then # stdout is tty, put into clipboard
49 | wl-copy $board
50 | else
51 | echo "Cannot use '+' as pipe" >&2
52 | return 1
53 | fi
54 | else
55 | case $1 in
56 | p) board=--primary;;
57 | s) board=--secondary;;
58 | b|"") board=--clipboard;;
59 | *) echo "Invalid argument" >&2; return 1;;
60 | esac
61 | if [[ -t 0 ]]; then # stdin is tty, print clipboard
62 | xsel --output $board
63 | elif [[ -t 1 ]]; then # stdout is tty, put into clipboard
64 | xsel --input $board
65 | else
66 | echo "Cannot use '+' as pipe" >&2
67 | return 1
68 | fi
69 | fi
70 | }
71 |
72 | # Realpath of which.
73 | rwhich() {
74 | command which $@ | xargs realpath
75 | }
76 |
77 | # Binary diff.
78 | bdiff() {
79 | diff <(hexdump -C $1) <(hexdump -C $2) ${@:3}
80 | }
81 |
82 | # Length of stream, in human size.
83 | len() {
84 | wc -c | numfmt --to=iec-i
85 | }
86 |
87 | # mkdir && cd
88 | mkcd() {
89 | mkdir -p $1 && cd $1
90 | }
91 |
92 | # Run with limited memory.
93 | limitmem() {
94 | (( $# < 3 )) && { echo "USAGE: limitmem " >&2; return 1; }
95 | local cmd=(systemd-run --scope --user -p MemorySwapMax=0 -p MemoryHigh=$1 -p MemoryMax=$2 $argv[3,-1])
96 | echo -E "+ ${(q)cmd[@]}"
97 | ${cmd[@]}
98 | }
99 |
100 | # Patch interpreter to the dynamic linker.
101 | patchinterp() {
102 | local interp glibc
103 | interp="$(patchelf --print-interpreter $1)" || return 1
104 | [[ $interp != /nix/store/* ]] || { echo "Already patched: $interp"; return 1; }
105 | linker="$(nix eval --raw nixpkgs#bintools.dynamicLinker)" && patchelf --set-interpreter $linker $1
106 | }
107 |
108 | closure() {
109 | nix path-info -Shr $@ | eval $PAGER
110 | }
111 |
--------------------------------------------------------------------------------
/home/modules/shell/completion.zsh:
--------------------------------------------------------------------------------
1 | # Modified from: https://github.com/ohmyzsh/ohmyzsh/blob/706b2f3765d41bee2853b17724888d1a3f6f00d9/lib/completion.zsh
2 |
3 | ZSH_CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/zsh"
4 | ZSH_COMPDUMP="$ZSH_CACHE_DIR/zcompdump"
5 | mkdir -p $ZSH_CACHE_DIR
6 |
7 | # fixme - the load process here seems a bit bizarre
8 | zmodload -i zsh/complist
9 |
10 | WORDCHARS='*?_-.[]~=&;!#$%^(){}<>' # remove '/'
11 |
12 | unsetopt menu_complete # do not autoselect the first completion entry
13 | unsetopt flowcontrol
14 | setopt auto_menu # show completion menu on successive tab press
15 | setopt complete_in_word
16 | setopt always_to_end
17 |
18 | # should this be in keybindings?
19 | bindkey -M menuselect '^o' accept-and-infer-next-history
20 | zstyle ':completion:*:*:*:*:*' menu select
21 |
22 | # Don't try to expand multiple partial paths.
23 | zstyle ':completion:*' path-completion false
24 |
25 | # 1. Prefix completion.
26 | # 2. Substring completion.
27 | zstyle ':completion:*' matcher-list 'r:|=*' 'l:|=* r:|=*'
28 |
29 | zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"
30 |
31 | # Use caching so that commands like apt and dpkg complete are useable
32 | zstyle ':completion:*' use-cache yes
33 | zstyle ':completion:*' cache-path $ZSH_CACHE_DIR
34 |
35 | # Completing indicator.
36 | expand-or-complete-with-dots() {
37 | print -Pn "%F{blue}...%f"
38 | zle expand-or-complete
39 | zle redisplay
40 | }
41 | zle -N expand-or-complete-with-dots
42 | bindkey '^I' expand-or-complete-with-dots
43 |
44 | # Load bash completion functions.
45 | autoload -U +X bashcompinit && bashcompinit
46 |
47 | # Dump the current completion states.
48 | () {
49 | local fpath_real=${fpath:P}
50 | local fpath_line="# fpath: ${fpath_real[*]}"
51 | local need_init=0
52 |
53 | if [[ "$(tail -n1 $ZSH_COMPDUMP 2>/dev/null)" != "$fpath_line" ]]; then
54 | need_init=1
55 | rm -f $ZSH_COMPDUMP
56 | fi
57 |
58 | autoload -U compinit
59 | compinit -u -C -d $ZSH_COMPDUMP
60 |
61 | if (( $need_init )); then
62 | printf '\n%s' $fpath_line >>$ZSH_COMPDUMP
63 | fi
64 | }
65 |
--------------------------------------------------------------------------------
/home/modules/shell/default.nix:
--------------------------------------------------------------------------------
1 | { lib, pkgs, config, my, ... }:
2 | {
3 | home.sessionVariables = {
4 | # Rust and python outputs.
5 | PATH = "$HOME/.local/bin\${PATH:+:}$PATH";
6 |
7 | FZF_DEFAULT_COMMAND = "${lib.getBin pkgs.fd}/bin/fd --type=f --hidden --exclude=.git";
8 | FZF_DEFAULT_OPTS = lib.concatStringsSep " " [
9 | "--layout=reverse" # Top-first.
10 | "--color=16" # 16-color theme.
11 | "--info=inline"
12 | "--exact" # Substring matching by default, `'`-quote for subsequence matching.
13 | "--bind=alt-p:toggle-preview,alt-a:select-all"
14 | ];
15 |
16 | BAT_THEME = "ansi";
17 | };
18 |
19 | # The default `command-not-found` relies on nix-channel. Use `nix-index` instead.
20 | programs.command-not-found.enable = false;
21 | programs.nix-index = {
22 | enable = true;
23 | # Don't install the hook.
24 | enableBashIntegration = false;
25 | enableZshIntegration = false;
26 | };
27 |
28 | programs.zsh = {
29 | enable = true;
30 | dotDir = ".config/zsh";
31 |
32 | dirHashes = {
33 | target = "${config.xdg.cacheHome}/cargo/target";
34 | nixpkgs = "${config.home.homeDirectory}/repo/fork/nixpkgs";
35 | };
36 |
37 | # Disable /etc/{zshrc,zprofile} that contains the "sane-default" setup.
38 | # See `/etc/zshrc` for more info.
39 | envExtra = ''
40 | setopt no_global_rcs
41 | '';
42 |
43 | autosuggestion.enable = true;
44 | enableCompletion = false; # We do it ourselves.
45 | enableVteIntegration = true;
46 |
47 | history = {
48 | ignoreDups = true;
49 | ignoreSpace = true;
50 | expireDuplicatesFirst = true;
51 | extended = true;
52 | share = false;
53 | path = "${config.xdg.stateHome}/zsh/history";
54 | save = 1000000;
55 | size = 1000000;
56 | ignorePatterns = [
57 | "rm *" "\\rm *"
58 | "sudo *rm*"
59 | "g* stash (clear|drop)*"
60 | ":"
61 | ];
62 | };
63 |
64 | # Ref: https://blog.quarticcat.com/zh/posts/how-do-i-make-my-zsh-smooth-as-fuck/
65 | # 550 = Before compinit.
66 | initContent = lib.mkOrder 550 ''
67 | setopt auto_pushd
68 | setopt interactive_comments
69 | setopt multios
70 | setopt noextended_glob # Breaks flake path reference nixpkgs#foo.
71 |
72 | setopt hist_verify
73 | setopt inc_append_history_time
74 |
75 | LS_COLORS="$(dircolors --sh)"
76 | LS_COLORS="''${''${LS_COLORS#*\'}%\'*}"
77 | export LS_COLORS
78 | TIMEFMT=$'%J %uU user %uS system %uE/%*E elapsed %PCPU (%Xavgtext+%Davgdata %Mmaxresident)k\n%Iinputs+%Ooutputs (%Fmajor+%Rminor)pagefaults %Wswaps'
79 |
80 | source ${pkgs.git}/share/git/contrib/completion/git-prompt.sh
81 | source ${./prompt.zsh}
82 | source ${./cmds.zsh}
83 | source ${./key-bindings.zsh}
84 | source ${./completion.zsh}
85 |
86 | ZSH_AUTOSUGGEST_MANUAL_REBIND=1
87 | ZSH_AUTOSUGGEST_HISTORY_IGNORE=$'*\n*'
88 | source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
89 | source ${pkgs.zsh-fast-syntax-highlighting}/share/zsh/site-functions/fast-syntax-highlighting.plugin.zsh
90 | source ${my.pkgs.zsh-comma}/share/zsh/comma/comma.zsh
91 | FAST_HIGHLIGHT[use_async]=1 # Improve paste delay for nix store paths.
92 | source <(${lib.getExe pkgs.fzf} --zsh)
93 | '';
94 | };
95 |
96 | programs.zoxide.enable = true;
97 |
98 | home.packages = with pkgs; [
99 | nix-zsh-completions # Prefer nix's builtin completion.
100 | my.pkgs.colors
101 | my.pkgs.zsh-comma
102 | ];
103 | }
104 |
--------------------------------------------------------------------------------
/home/modules/shell/key-bindings.zsh:
--------------------------------------------------------------------------------
1 | # References:
2 | # - https://github.com/ohmyzsh/ohmyzsh/blob/706b2f3765d41bee2853b17724888d1a3f6f00d9/lib/key-bindings.zsh
3 | # - https://github.com/dramforever/config/blob/446e232cba4f3e05d83fb126516b1d9181fb7e67/home/zshrc
4 | # - `/etc/zinputrc` from NixOS.
5 | # - http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Builtins
6 | # - http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Standard-Widgets
7 |
8 | zmodload zsh/zle
9 | zmodload zsh/terminfo
10 |
11 | # Escape sequence timeout in 1/100s.
12 | KEYTIMEOUT=1
13 |
14 | # Make sure the terminal is in application mode, when zle is
15 | # active. Only then are the values from $terminfo valid.
16 | # From `/etc/zinputrc`.
17 | if (( ${+terminfo[smkx]} && ${+terminfo[rmkx]} )); then
18 | zle-line-init() echoti smkx
19 | zle-line-finish() echoti rmkx
20 | zle -N zle-line-init
21 | zle -N zle-line-finish
22 | fi
23 |
24 | # Mode indicator.
25 | zle-keymap-select() {
26 | RPS1=${KEYMAP/(main|viins)/}
27 | zle redisplay
28 | }
29 | zle -N zle-keymap-select
30 |
31 | # Use viins key bindings
32 | bindkey -v
33 |
34 | bind() {
35 | [[ -z $1 ]] || bindkey $1 $2
36 | }
37 |
38 | # [Delete] - Delete forward
39 | bind "${terminfo[kdch1]}" delete-char
40 | # [Home]
41 | bind "${terminfo[khome]}" beginning-of-line
42 | # [End]
43 | bind "${terminfo[kend]}" end-of-line
44 | # [PageUp]
45 | bind "${terminfo[kpp]}" beginning-of-buffer-or-history
46 | # [PageDown]
47 | bind "${terminfo[knp]}" end-of-buffer-or-history
48 | # [Ctrl-RightArrow]
49 | bind '^[[1;5C' forward-word
50 | # [Ctrl-LeftArrow]
51 | bind '^[[1;5D' backward-word
52 |
53 |
54 | # [Left]
55 | bind "${terminfo[kcub1]}" backward-char
56 | # [Right]
57 | bind "${terminfo[kcuf1]}" forward-char
58 | # [Up]
59 | bind "${terminfo[kcuu1]}" up-line-or-history
60 | # [Down]
61 | bind "${terminfo[kcud1]}" down-line-or-history
62 |
63 | # [Shift-Tab]
64 | bind "${terminfo[kcbt]}" reverse-menu-complete
65 |
66 | autoload -U up-line-or-beginning-search
67 | autoload -U down-line-or-beginning-search
68 | zle -N up-line-or-beginning-search
69 | zle -N down-line-or-beginning-search
70 | # [Ctrl-p]
71 | bind '^p' up-line-or-beginning-search
72 | # [Ctrl-n]
73 | bind '^n' down-line-or-beginning-search
74 |
75 | # [Space]
76 | bind ' ' magic-space
77 |
78 | unfunction bind
79 |
80 | preexec_load_history() {
81 | if [[ $1 == : ]]; then
82 | fc -RI
83 | fi
84 | }
85 | autoload -Uz add-zsh-hook
86 | add-zsh-hook -Uz preexec preexec_load_history
87 |
--------------------------------------------------------------------------------
/home/modules/shell/prompt.zsh:
--------------------------------------------------------------------------------
1 | # AVIT ZSH Theme Simplified
2 |
3 | setopt promptsubst
4 |
5 | typeset +H _current_dir='%B%F{blue}%3~%f%b'
6 | typeset +H _return_status=' %(?..%B%F{red}[%?]%f%b)'
7 | typeset +H _shell_level='%(2L. <%L>.)'
8 |
9 | PROMPT='
10 | $(_user_host)${_current_dir}$(_git_info)${_shell_level}${_return_status}
11 | %(!.%F{red}.)>%f '
12 |
13 | PROMPT2='%(!.%F{red}.)|%f '
14 |
15 | # Use an inverted space as NOEOL marker so it's easier to copy.
16 | PROMPT_EOL_MARK="%B%S %s%b"
17 |
18 | _user_host() {
19 | local me
20 | if [[ -n $SSH_CONNECTION ]]; then
21 | me="%n@%m"
22 | elif [[ $LOGNAME != $USER ]]; then
23 | me="%n"
24 | fi
25 | if [[ -n $me ]]; then
26 | echo -nE "%F{cyan}$me%f "
27 | fi
28 | }
29 |
30 | _git_info() {
31 | echo -nE "%F{green}$(__git_ps1)%f"
32 | }
33 |
--------------------------------------------------------------------------------
/home/modules/tmux.nix:
--------------------------------------------------------------------------------
1 | { ... }:
2 | {
3 | programs.tmux = {
4 | enable = true;
5 | baseIndex = 1;
6 | clock24 = true;
7 | escapeTime = 1;
8 | historyLimit = 100000;
9 | keyMode = "vi";
10 | prefix = "C-a";
11 | terminal = "tmux-256color"; # Fix weird behaviors for dim colors.
12 |
13 | # tmux
14 | extraConfig = ''
15 | set -g mouse on
16 | set -g set-clipboard on
17 | set -g word-separators " ,\"'[](){}<>=:@"
18 |
19 | set -sa terminal-overrides "alacritty:Tc"
20 | # Hyperlinks.
21 | set -sa terminal-overrides '*:Hls=\E]8;id=%p1%s;%p2%s\E\\:Hlr=\E]8;;\E\\'
22 | # SGR 53 (Overline).
23 | set -sa terminal-overrides '*:Smol=\E[53m'
24 | # Styled underlines.
25 | set -sa terminal-overrides '*:Smulx=\E[4::%p1%dm'
26 | # Underline colors.
27 | set -sa terminal-overrides '*:Setulc=\E[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m'
28 |
29 | # Colors
30 | set -g status-style fg=green
31 | set -g window-status-current-style reverse
32 |
33 | # Custom window title.
34 | set -g automatic-rename on
35 | set -g automatic-rename-format '#{b:pane_current_path}#{?#{!=:#{pane_current_command},zsh},:#{pane_current_command},}'
36 | set -g status-interval 1
37 |
38 | # Split panes.
39 | bind v split-window -h -c "#{pane_current_path}"
40 | bind s split-window -v -c "#{pane_current_path}"
41 |
42 | # Resize panes.
43 | bind -r H resize-pane -L 5
44 | bind -r J resize-pane -D 5
45 | bind -r K resize-pane -U 5
46 | bind -r L resize-pane -R 5
47 |
48 | # Move between panes.
49 | bind -r C-h select-pane -L
50 | bind -r C-j select-pane -D
51 | bind -r C-k select-pane -U
52 | bind -r C-l select-pane -R
53 |
54 | # Copy mode behaviors.
55 | # Ref: https://github.com/tmux/tmux/issues/140#issuecomment-474341833
56 | # Don't exit after selection.
57 | bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-selection-no-clear
58 | bind-key -T copy-mode-vi DoubleClick1Pane send-keys -X select-word \; send-keys -X copy-selection-no-clear
59 | bind-key -T copy-mode-vi TripleClick1Pane send-keys -X select-line \; send-keys -X copy-selection-no-clear
60 | # Clear selection on single-click.
61 | bind-key -T copy-mode-vi MouseDown1Pane select-pane \; send-keys -X clear-selection
62 | # Quick enter and leave.
63 | bind-key -n DoubleClick3Pane copy-mode -M \; send-keys -X select-word \; send-keys -X copy-selection-no-clear
64 | bind-key -n TripleClick3Pane copy-mode -M \; send-keys -X select-line \; send-keys -X copy-selection-no-clear
65 | bind-key -T copy-mode-vi MouseDown3Pane send-keys -X cancel
66 | '';
67 | };
68 | }
69 |
--------------------------------------------------------------------------------
/home/modules/user-dirs.nix:
--------------------------------------------------------------------------------
1 | { ... }:
2 | {
3 | xdg.userDirs = {
4 | enable = true;
5 | desktop = "$HOME/Desktop";
6 | download = "$HOME/Downloads";
7 | pictures = "$HOME/Pictures";
8 | documents = "$HOME";
9 | music = "$HOME";
10 | publicShare = "$HOME";
11 | templates = "$HOME";
12 | videos = "$HOME/Video";
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/home/modules/vscode/default.nix:
--------------------------------------------------------------------------------
1 | { pkgs, ... }:
2 | {
3 | programs.vscode = {
4 | enable = true;
5 | package = pkgs.vscodium;
6 | };
7 | }
8 |
--------------------------------------------------------------------------------
/home/modules/xdgify.nix:
--------------------------------------------------------------------------------
1 | # Reference: https://gitlab.com/NickCao/flakes/-/blob/master/nixos/local/home.nix#L71
2 | { config, ... }:
3 | {
4 | home.sessionVariables = {
5 | HISTFILE = "${config.xdg.stateHome}/bash/history";
6 | LESSHISTFILE = "${config.xdg.stateHome}/less/history";
7 | SQLITE_HISTORY = "${config.xdg.stateHome}/sqlite/history";
8 | };
9 |
10 | # XDG Spec doesn't have BIN_HOME yet.
11 | home.xdg.configFile."go/env".text = ''
12 | GOPATH=${config.xdg.cacheHome}/go
13 | GOBIN=${config.homeDirectory}/.local/bin
14 | '';
15 | }
16 |
--------------------------------------------------------------------------------
/lib.nix:
--------------------------------------------------------------------------------
1 | { lib }:
2 | {
3 | toTOML = let
4 | inherit (builtins) toJSON concatStringsSep isAttrs isList isFloat;
5 | inherit (lib) isStringLike concatMapStringsSep mapAttrsToList;
6 |
7 | # We use `toJSON` for serialization of string, numbers and booleans.
8 | # The only incompatibility is that JSON allows `"\/"` while TOML does not.
9 | # But `builtins.toJSON` does not escape `/` anyway, so it's fine.
10 |
11 | inf = 1.0e308 * 10;
12 |
13 | toTopLevel = obj:
14 | concatStringsSep ""
15 | (mapAttrsToList
16 | (name: value: "${toJSON name}=${toInline value}\n")
17 | obj);
18 |
19 | toInline = obj:
20 | # Exclude drvs here, or we'll easily get infinite recursion.
21 | if isAttrs obj && !isStringLike obj then
22 | "{${concatStringsSep ","
23 | (mapAttrsToList
24 | (name: value: "${toJSON name}=${toInline value}")
25 | obj)
26 | }}"
27 | else if isList obj then
28 | "[${concatMapStringsSep "," toInline obj}]"
29 | else if obj == null then
30 | throw "“null” is not supported by TOML"
31 | else if !isFloat obj then
32 | # Strings, integers and booleans.
33 | toJSON obj
34 | # Sanitize +-inf and NaN. They'll produce "null", which is invalid for TOML.
35 | else if obj == inf then
36 | "inf"
37 | else if obj == -inf then
38 | "-inf"
39 | else if obj != obj then
40 | "nan"
41 | else
42 | toJSON obj;
43 |
44 | in
45 | toTopLevel;
46 | }
47 |
--------------------------------------------------------------------------------
/my/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | gpg = {
3 | fingerprint = "F90FFD6D585C2BA1F13DE8A97571654CF88E31C2";
4 | publicKeyFile = ./gpg-pubkey.asc;
5 | };
6 |
7 | ssh = rec {
8 | identities = {
9 | oxa = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHn7rLiEt5UHKNsX/uNam7679guLh4chbYdE2eoC00+p openpgp:0x4E59DAB9";
10 |
11 | oxa-invar = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJYl9bIMoMrs8gWUmIAF42mGnKVxqY6c+g2gmE6u2E/B oxa@invar";
12 | oxa-blacksteel = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICU0P/fbBnnPCVni+efxfl//NQ1jeOe4lUDH6okvLzr1 oxa@blacksteel";
13 | shu-iwkr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOtqhzrEH5VnSSxcLn7MJKbCw7QFhQmX8hkSmsEMq8/I shu@iwkr";
14 | } // builtins.mapAttrs (name: value: value.publicKey) knownHosts;
15 |
16 | knownHosts = {
17 | invar.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPp0GGkE81OeO1JUQ+T/DfsjzQSNRz1lzpNTU+UgpAv1";
18 | blacksteel.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICVBNvOEn0ncdylnKQIFKd75muElg5TBaMFWrbamAlx+";
19 | iwkr.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEmt0cK3uNWAtpK2k3BA+liaIKWFPa8mDtRh15GAjF3J";
20 |
21 | copper = {
22 | extraHostNames = [ "|1|dBmAkr6d+gTzhvfiA8p7l+H34co=|3U8aEJXTtWbmM/j/c+qAGKb44d8=" ];
23 | publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO1TnA8NpurpJFgf4xZZvJrgFpkaE9y6qRgFiFe1mX21";
24 | };
25 | lithium = {
26 | extraHostNames = [ "|1|yrXSPIhZYqHg3ii/siCoKs2PRU4=|uaJAOcFrhozPJsul0YF/+1CaAKw=" ];
27 | publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMPG3JTJrW5kDTFXOftags+aWWjn2D1E5iIbU57ni9rH";
28 | };
29 |
30 | aluminum = {
31 | extraHostNames = [ "aluminum.lan.hexade.ca" ];
32 | publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOqzykYcCVpDJqkayG8tzoh3AurOsilAsBTX7heF0h3u";
33 | };
34 | };
35 | };
36 | }
37 |
--------------------------------------------------------------------------------
/my/gpg-pubkey.asc:
--------------------------------------------------------------------------------
1 | -----BEGIN PGP PUBLIC KEY BLOCK-----
2 |
3 | mDMEYdjEDRYJKwYBBAHaRw8BAQdA32pR8t7apbBFQrNpfh9jtsHPEIt1q4YpB42U
4 | b7mf0WW0F094YWxpY2EgPG94YWxpY2NAcG0ubWU+iJMEExYKADsWIQT5D/1tWFwr
5 | ofE96Kl1cWVM+I4xwgUCYdjEDQIbAwUJBaOagAQLCQgHBBUKCQgEFgIDAAIeAQIX
6 | gAAKCRB1cWVM+I4xwqqxAQDeaf8OvivYlLs0R17HrBqOUjr9BQOwuuzx+vLvdMEu
7 | kAEAyoB3yVDOlPw+TgQPaH3rCB4WPqF61fmk7VWnxbgvkg+4MwRh2YynFgkrBgEE
8 | AdpHDwEBB0DD1mzvFdANRKZ9FfCHxxMTwPH3luHSN12sxGGKA4izu4jvBBgWCAAg
9 | FiEE+Q/9bVhcK6HxPeipdXFlTPiOMcIFAmHZjKcCGwIAgQkQdXFlTPiOMcJ2IAQZ
10 | FggAHRYhBLvM58SqAv6vso1WUtQlyyPK3oLZBQJh2YynAAoJENQlyyPK3oLZQboA
11 | +gN6i5K8ei/tryPad1Zq7mNqdeK0H8slzryL3KRDdXuPAP9tBMo4C62rrVI1xm58
12 | jsr5Dwpl6JICUUHCsCeMF1+qB7siAP4hqe40v3RPMsXV9mvf3+T9+WrDXsTDjHCK
13 | 7UtQzggZqAEAwxxlFTY0b+65QpkI3hYVqvCq23/vPHAiQeulpi0E2Qe4OARh2Yy4
14 | EgorBgEEAZdVAQUBAQdA5mq6F/tOP0S2y4Lz9zX3lSNgnSQMwPrwNs/3lyozkzcD
15 | AQgHiHgEGBYIACAWIQT5D/1tWFwrofE96Kl1cWVM+I4xwgUCYdmMuAIbDAAKCRB1
16 | cWVM+I4xwsGsAQD0bVjp2nxwvA5sApuSJC1CKFXuNPfXZoLtmcbCWaCOvwEAzxfv
17 | OYEbfgpXOWjXdps6G32oM+ZJImwNwcgwxfwpRAu4MwRh2YzLFgkrBgEEAdpHDwEB
18 | B0B5+6y4hLeVByjbF/7jWpu+u/YLi4eHIW2HRNnqAtNPqYh4BBgWCAAgFiEE+Q/9
19 | bVhcK6HxPeipdXFlTPiOMcIFAmHZjMsCGyAACgkQdXFlTPiOMcL1NAEA7aayPPJ2
20 | 7YLdl2428pemnqcFlPMX1CqlB+LmEFAsgxQBALnjHJZqOwxF4IGEGy38Z8rr8YYW
21 | 5O7JW7TaoBs0rpwC
22 | =QQHt
23 | -----END PGP PUBLIC KEY BLOCK-----
24 |
--------------------------------------------------------------------------------
/nixos/blacksteel/configuration.nix:
--------------------------------------------------------------------------------
1 | { lib, config, pkgs, inputs, my, ... }:
2 |
3 | {
4 | imports = [
5 | ./vm.nix
6 |
7 | ../modules/console-env.nix
8 | ../modules/device-fix.nix
9 | ../modules/kde-desktop
10 | ../modules/nix-cgroups.nix
11 | ../modules/nix-common.nix
12 | ../modules/nix-keep-flake-inputs.nix
13 | ../modules/nix-registry.nix
14 | ../modules/secure-boot.nix
15 | ../modules/zswap-enable.nix
16 | ] ++ lib.optional (inputs ? secrets) (inputs.secrets.nixosModules.blacksteel);
17 |
18 | nixpkgs.config.allowUnfreePredicate = drv:
19 | lib.elem (lib.getName drv) [
20 | "steam"
21 | "steam-unwrapped"
22 | ];
23 |
24 | nixpkgs.config.permittedInsecurePackages = [
25 | # FIXME: `nheko` depends on olm: https://github.com/Nheko-Reborn/nheko/issues/1786
26 | "olm-3.2.16"
27 | ];
28 |
29 | # Boot.
30 |
31 | boot = {
32 | initrd = {
33 | systemd.enable = true;
34 | availableKernelModules = [ "xhci_pci" "nvme" "rtsx_pci_sdmmc" ];
35 | kernelModules = [ ];
36 | luks.devices."luksroot" = {
37 | device = "/dev/disk/by-uuid/8e445c05-75cc-45c7-bebd-46a73cf50a74";
38 | allowDiscards = true;
39 | crypttabExtraOpts = [ "fido2-device=auto" ];
40 | };
41 | };
42 |
43 | kernelPackages = pkgs.linuxPackages_latest;
44 | kernelModules = [ "kvm-intel" ];
45 | extraModulePackages = [ ];
46 |
47 | loader = {
48 | systemd-boot.consoleMode = "max"; # Don't clip boot menu.
49 | efi.canTouchEfiVariables = true;
50 | timeout = 1;
51 | };
52 |
53 | kernel.sysctl = {
54 | "kernel.sysrq" = "1";
55 | "net.ipv4.tcp_congestion_control" = "bbr";
56 | };
57 | };
58 |
59 | fileSystems = {
60 | "/" = {
61 | device = "/dev/disk/by-uuid/fbfe849d-2d2f-415f-88d3-65ded870e46b";
62 | fsType = "btrfs";
63 | options = [ "noatime" "compress=zstd:1" "subvol=@" ];
64 | };
65 |
66 | "/boot" = {
67 | device = "/dev/disk/by-uuid/9C91-4441";
68 | fsType = "vfat";
69 | };
70 | };
71 |
72 | swapDevices = [
73 | { device = "/var/swap/resume"; }
74 | ];
75 |
76 | # Hardware.
77 |
78 | hardware = {
79 | cpu.intel.updateMicrocode = true;
80 | bluetooth.enable = true;
81 | logitech.wireless.enable = true;
82 | enableRedistributableFirmware = true; # Required for WIFI.
83 | graphics.extraPackages = with pkgs; [ intel-media-driver ]; # vaapi
84 | };
85 | console = {
86 | font = "${pkgs.terminus_font}/share/consolefonts/ter-v28n.psf.gz";
87 | useXkbConfig = true;
88 | earlySetup = true;
89 | };
90 | networking = {
91 | hostName = "blacksteel";
92 | firewall.logRefusedConnections = false;
93 | networkmanager.dns = "systemd-resolved";
94 | };
95 | services.resolved.enable = true;
96 | systemd.network.wait-online.enable = false;
97 |
98 | time.timeZone = "America/Toronto";
99 |
100 | # KDE pulls in pipewire via xdg-desktop-portal anyways.
101 | services.pipewire = {
102 | enable = true;
103 | pulse.enable = true;
104 | alsa.enable = true;
105 | };
106 | security.rtkit.enable = true; # pipewire expects this.
107 |
108 | # Swap capslock and leftctrl only for the builtin keyboard.
109 | # Ref: https://wiki.archlinux.org/title/Map_scancodes_to_keycodes
110 | services.udev.extraHwdb = ''
111 | evdev:atkbd:dmi:bvnLENOVO:*:pvrThinkPadX1Carbon5th*
112 | KEYBOARD_KEY_3a=leftctrl
113 | KEYBOARD_KEY_1d=capslock
114 | '';
115 |
116 | # Users.
117 |
118 | sops.secrets.passwd.neededForUsers = true;
119 | programs.zsh.enable = true;
120 | users = {
121 | mutableUsers = false;
122 | users."oxa" = {
123 | isNormalUser = true;
124 | shell = pkgs.zsh;
125 | hashedPasswordFile = config.sops.secrets.passwd.path;
126 | uid = 1000;
127 | group = config.users.groups.oxa.name;
128 | extraGroups = [ "wheel" "kvm" "adbusers" "libvirtd" "wireshark" ];
129 |
130 | openssh.authorizedKeys.keys = with my.ssh.identities; [ oxa ];
131 | };
132 | groups."oxa".gid = 1000;
133 | };
134 | home-manager.users."oxa" =
135 | import ../../home/blacksteel.nix;
136 |
137 | # Services.
138 |
139 | services = {
140 | dbus.implementation = "broker";
141 | openssh = {
142 | enable = true;
143 | authorizedKeysInHomedir = false;
144 | settings = {
145 | KbdInteractiveAuthentication = false;
146 | PasswordAuthentication = false;
147 | PermitRootLogin = "no";
148 | };
149 | };
150 | fstrim = {
151 | enable = true;
152 | interval = "Wed,Sat 02:00";
153 | };
154 | timesyncd.enable = true;
155 | earlyoom = {
156 | enable = true;
157 | enableNotifications = true;
158 | };
159 | btrbk.instances.snapshot = {
160 | onCalendar = "*:00,30";
161 | settings = {
162 | timestamp_format = "long-iso";
163 | preserve_day_of_week = "monday";
164 | preserve_hour_of_day = "6";
165 | snapshot_preserve_min = "6h";
166 | volume."/" = {
167 | snapshot_dir = ".snapshots";
168 | subvolume."home/oxa".snapshot_preserve = "48h 7d";
169 | subvolume."home/oxa/storage".snapshot_preserve = "48h 7d 4w";
170 | };
171 | };
172 | };
173 | };
174 |
175 | nix = {
176 | buildMachines = [
177 | {
178 | hostName = "aluminum.lan.hexade.ca";
179 | maxJobs = 24;
180 | protocol = "ssh-ng";
181 | sshUser = "oxa";
182 | sshKey = "/etc/ssh/ssh_host_ed25519_key";
183 | systems = [ "x86_64-linux" "i686-linux" ];
184 | supportedFeatures = [ "kvm" "big-parallel" "nixos-test" "benchmark" ];
185 | }
186 | ];
187 | };
188 |
189 | # Global ssh settings. Also for remote builders.
190 | programs.ssh = {
191 | knownHosts = my.ssh.knownHosts;
192 | extraConfig = ''
193 | Include ${config.sops.secrets.ssh-hosts.path}
194 | '';
195 | };
196 | sops.secrets.ssh-hosts = {
197 | sopsFile = ../../secrets/ssh.yaml;
198 | mode = "0444";
199 | };
200 |
201 | programs.adb.enable = true;
202 |
203 | programs.steam.enable = true;
204 |
205 | programs.wireshark = {
206 | enable = true;
207 | package = pkgs.wireshark-qt;
208 | };
209 |
210 | programs.virt-manager.enable = true;
211 |
212 | services.btrfs.autoScrub = {
213 | enable = true;
214 | fileSystems = [ "/" ];
215 | interval = "monthly";
216 | };
217 |
218 | programs.gamemode = {
219 | enable = true;
220 | settings = {
221 | general.igpu_desiredgov = "performance";
222 | gpu = {
223 | apply_gpu_optimisations = "accept-responsibility";
224 | gpu_device = 1;
225 | };
226 | custom = {
227 | start = "${lib.getExe pkgs.libnotify} 'Enter GameMode'";
228 | end = "${lib.getExe pkgs.libnotify} 'Leave GameMode'";
229 | };
230 | };
231 | };
232 | users.groups."gamemode".members = [ config.users.users.oxa.name ];
233 |
234 | environment.systemPackages = with pkgs; [
235 | ltunify
236 | ];
237 |
238 | system.stateVersion = "25.05";
239 | }
240 |
--------------------------------------------------------------------------------
/nixos/blacksteel/secret.yaml:
--------------------------------------------------------------------------------
1 | passwd: ENC[AES256_GCM,data:jMLYujz0zRIgWCCC3ysEDgM6ZkmJkXtIpkxOrKDi/hbHIkGkCzEzulvWIL5Ap70ntNUYt5wrLT6+oRdMJ0tIimVYKtApE4/54eXVNoVrtoCKpalEiEYMdDdkJKZn+gG/KKHGlJ3UB0VrOQ==,iv:2wT6/nM8uJqgF0wX9vbUX3xRl9b2d/Tpb6PltOvxAl8=,tag:H5LoAaaXqQK+/kS0cO+97w==,type:str]
2 | sops:
3 | kms: []
4 | gcp_kms: []
5 | azure_kv: []
6 | hc_vault: []
7 | age:
8 | - recipient: age1l9qly5vlx20uzrqvq8qygvcrtff64mgvqchet5uvs989upy5lugq4krj2c
9 | enc: |
10 | -----BEGIN AGE ENCRYPTED FILE-----
11 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzZkFpMXFBa1hJRmpjVkxu
12 | dnBqMGpZcktORit2YWN6TzlyWDlCWmhnaFMwCmhsVmFteGRzeTRCQnRQbTd0by9Q
13 | N3JJWUZyNUtqYTI2WldSZS9HOWU5UHcKLS0tIHFDaFBEQ2VEQVlySnA3VU43QmtE
14 | NFBURVRVS0wvejBXcjF1VEVWSmJVNzQKAtChN2sLTatYhSrdPFxc9gkW1y0rwLP6
15 | 2Sx/5f38XVinmEsy63eNIzdwWCDtCa7/tHgwqIEXojA5OVg1pHQmVQ==
16 | -----END AGE ENCRYPTED FILE-----
17 | lastmodified: "2022-08-19T16:56:57Z"
18 | mac: ENC[AES256_GCM,data:SZ7RUJ/8qkKSbYjM72QCSsb6ZqJ3+OmtYiGjeZ8yMRd9cCN83bSMJTmynWGen/7+rrqQUVlC799dFBWcqSV5L0yih/ZnlkIeLiX8wns7SdUkAN0Y4KgmqGC/HSHGmgpj/UlTO4azJExnw0j+Fj2mtB3b2ulJm/FtLHBcJxlROp8=,iv:T4ZLd3vEDcb85+bfqMb8Ouv6fsJv7pUZSZ7T8Pc3YTQ=,tag:/Lzkfbc213KhgCnEWXOF3g==,type:str]
19 | pgp:
20 | - created_at: "2023-04-02T15:33:27Z"
21 | enc: |-
22 | -----BEGIN PGP MESSAGE-----
23 |
24 | wV4Dhs332B8tbXUSAQdAg2TKsM/gYOd4gbTIzIxrIXeHIE+c0RI53RGrSEg2GAkw
25 | lW1s/3ebnMfEODW17ukxoVeypCXvpKsm2Yn3khOEsqQ2xvafF533RJIgG7mWRRyP
26 | 0lEBb0yKOehSPZAYAVX2JJ06s+9wf9KhypqeyWsNjoTuJyYGQ42tpSnT1jxw4IGi
27 | KP6MeL3ZOdSE3mTnlM6zBiaGfm3UeO5t9SuFK5eEaRVo100=
28 | =T6VT
29 | -----END PGP MESSAGE-----
30 | fp: F90FFD6D585C2BA1F13DE8A97571654CF88E31C2
31 | unencrypted_suffix: _unencrypted
32 | version: 3.7.3
33 |
--------------------------------------------------------------------------------
/nixos/blacksteel/vm.nix:
--------------------------------------------------------------------------------
1 | { pkgs, ... }:
2 | {
3 | virtualisation.libvirtd = {
4 | enable = true;
5 | qemu.package = pkgs.qemu_kvm;
6 | };
7 | boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
8 | virtualisation.kvmgt = {
9 | enable = true;
10 | # Random generated UUIDs.
11 | # vgpus."i915-GVTg_V5_4".uuid = "7dbe463d-94fc-425c-8ccd-55d0f9d5d26b"; # 1920x1200
12 | vgpus."i915-GVTg_V5_8".uuid = [ "89584099-86a4-4b77-b770-16c0a93c260a" ]; # 1024x768
13 | };
14 |
15 | systemd.services."win10-hd-vm-disk" = let
16 | dmName = "win10-hd-vm-disk";
17 |
18 | devWin = "/dev/disk/by-uuid/CE8A6B398A6B1D69";
19 | secWin = 262047414;
20 | devGpt = "/dev/disk/by-partuuid/4f3131a2-ee06-425e-b3af-bbf35c00d192";
21 | secGptBefore = 262144; # 128 MiB
22 | secGptAfter = 2048; # 1 MiB
23 |
24 | in {
25 | description = "Device mapper for Windows 10 VM";
26 | unitConfig.RequiresMountsFor = "/home/oxa/vm/pool";
27 | wantedBy = [ "multi-user.target" ];
28 | serviceConfig.Type = "oneshot";
29 | serviceConfig.RemainAfterExit = true;
30 |
31 | path = with pkgs; [ util-linux lvm2 ];
32 | script = ''
33 | sec_win=$(blockdev --getsz ${devWin})
34 | sec_gpt=$(blockdev --getsz ${devGpt})
35 | echo "Windows partition has $sec_win sectors"
36 | echo "GPT partition has $sec_gpt sectors"
37 | if [[ "$sec_win" -ne ${toString secWin} || "$sec_gpt" -ne ${toString (secGptBefore + secGptAfter)} ]]; then
38 | echo "Size mismatch"
39 | exit 1
40 | fi
41 |
42 | dmsetup create ${dmName} <./config.json
85 | ${lib.getExe config.services.caddy.package} validate --config ./config.json
86 | '';
87 | });
88 |
89 | };
90 |
91 | systemd.tmpfiles.settings."caddy-logs" = {
92 | ${logDir}.d = {
93 | group = config.users.groups.caddy.name;
94 | user = config.users.users.caddy.name;
95 | mode = "0755";
96 | };
97 | };
98 |
99 | system.stateVersion = "25.05";
100 | }
101 |
--------------------------------------------------------------------------------
/nixos/lithium/ntfy.nix:
--------------------------------------------------------------------------------
1 | # Ref: https://github.com/NickCao/flakes/blob/3b03efb676ea602575c916b2b8bc9d9cd13b0d85/nixos/hcloud/iad1/ntfy.nix
2 | { lib, config, ... }:
3 | let
4 | inherit (lib) singleton;
5 | host = "ntfy.oxa.li";
6 | in
7 | {
8 |
9 | services.ntfy-sh = {
10 | enable = true;
11 | settings = {
12 | base-url = "https://${host}";
13 | listen-http = "";
14 | listen-unix = "/run/ntfy-sh/ntfy.sock";
15 | listen-unix-mode = 511; # 0777
16 | behind-proxy = true;
17 | };
18 | };
19 |
20 | systemd.services.ntfy-sh.serviceConfig.RuntimeDirectory = "ntfy-sh";
21 |
22 | services.caddy.settings.apps.http.servers.default.routes = singleton {
23 | match = singleton { host = singleton host; };
24 | terminal = true;
25 | handle = singleton {
26 | handler = "reverse_proxy";
27 | upstreams = singleton { dial = "unix/${config.services.ntfy-sh.settings.listen-unix}"; };
28 | };
29 | };
30 | }
31 |
--------------------------------------------------------------------------------
/nixos/lithium/secret.yaml:
--------------------------------------------------------------------------------
1 | caddy-env: ENC[AES256_GCM,data:v7alrb5cDdLfAsbRLkA7wTjJ1j/XrUtwr159giQAC8F8s4fpf9/RihE/dmCY1P74EIAIOM+21PRaqBQowsFEMNd79U3ZZOufhKG5gJk3/7RvXStGLmfTUwJtbAk4qvbGFcTgZBA=,iv:cLZOHsjYnpSAQzYDaJ+01Wwyf6hZcWMaSbDuysu8bnI=,tag:KEFgVuLaQmZ3l0Epe8J/rQ==,type:str]
2 | sops:
3 | kms: []
4 | gcp_kms: []
5 | azure_kv: []
6 | hc_vault: []
7 | age:
8 | - recipient: age1telu43gwg7fucnph6x5mgl46yvaj9z0cuj2v4e5d8fxhlsvduqas7psujn
9 | enc: |
10 | -----BEGIN AGE ENCRYPTED FILE-----
11 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6cnRMMERKQ3hvYjloWjl0
12 | bHYvQlVUcXNCYjRRay9KN0VlblV4NldiM2tJClNpNlpPZzRTVXZxZVcrYXZLOTQ0
13 | RUhHamxEazQ1bTgwM0tYTkI4QkdXWkEKLS0tIEdvM3pkVUlWa3ZPSUZRRzFuQTR3
14 | a1NPNlp6Wm1PTUk1WTlkUy8rUjFMRlUKayVPRf3VtInuMViUgZ6waBMy+ctRAiGi
15 | bipOcAvc+gjMceGvICeZa2+zw+LPvn3NvNn1Cz4DwrlWTW9/ElOAgg==
16 | -----END AGE ENCRYPTED FILE-----
17 | lastmodified: "2024-09-01T23:16:54Z"
18 | mac: ENC[AES256_GCM,data:XdSB+l63v7z++d7gj+nEcf9Mhr0j1pOt2bEKmAFTNSyFa6+Hx+amm9vu/WL81e1F9T08DzZ0bWSQ8pMNoQZYb6ZUw8h2RmXXFx5BhoSLgpp5uIxvWp6bRK1B4CvDw7je7d0aKGw6FkwgxaM6mjebOafBtUSqfJRufgCkR4bCx9k=,iv:ndgQLd3TBDAHukh4fpFBMh9NrC8Wv60NUTGn+0XdU4g=,tag:w0qkVtC/kg+Wro2YV0eFHA==,type:str]
19 | pgp:
20 | - created_at: "2024-09-07T04:43:35Z"
21 | enc: |-
22 | -----BEGIN PGP MESSAGE-----
23 |
24 | hF4Dhs332B8tbXUSAQdAue0uC50aYtAQKzcn3qkHxY8YA8ogooUvGuiXVlDW8nQw
25 | AnB7dC/TtD8lsmvb8yGga7MQLIJKaUs5GPLnIKlxLCQGw30pgY71h2Q+JKq59xH2
26 | 0l4Bo6fOGOrfBIc14T/yKho1b+AU2y0OpGbwG6DEj+HG4rUBFbEza+C3+8wWSM/j
27 | KnKF7A3ue2TRO3Dyf5HU98AQqmChuZsdOC9kVhXeLamlKzP23I/R6gR3SBnhnTnU
28 | =nrel
29 | -----END PGP MESSAGE-----
30 | fp: F90FFD6D585C2BA1F13DE8A97571654CF88E31C2
31 | unencrypted_suffix: _unencrypted
32 | version: 3.9.0
33 |
--------------------------------------------------------------------------------
/nixos/lithium/webdav.nix:
--------------------------------------------------------------------------------
1 | { lib, config, ... }:
2 | let
3 | inherit (lib) singleton;
4 |
5 | route = "/webdav";
6 | srvPath = "/srv/webdav";
7 |
8 | in
9 | {
10 | # This requires service restart anyway. Leave it to human.
11 | sops.secrets.caddy-env = { };
12 | systemd.services.caddy = {
13 | serviceConfig = {
14 | RuntimeDirectory = "caddy";
15 | ReadWritePaths = singleton srvPath;
16 | EnvironmentFile = singleton config.sops.secrets.caddy-env.path;
17 | };
18 | after = [ "systemd-tmpfiles-setup.service" ];
19 | };
20 |
21 | # NB. Limit can only be set manually.
22 | systemd.tmpfiles.settings."webdav" = {
23 | ${srvPath}.v = {
24 | group = config.users.groups.caddy.name;
25 | user = config.users.users.caddy.name;
26 | mode = "0755";
27 | };
28 | };
29 |
30 | services.caddy.settings.apps.http.servers.default.routes = lib.singleton {
31 | match = singleton {
32 | host = singleton config.networking.fqdn;
33 | path = singleton "${route}/*";
34 | };
35 | handle = [
36 | {
37 | handler = "authentication";
38 | providers.http_basic.accounts = singleton {
39 | username = "{env.WEBDAV_USERNAME}";
40 | password = "{env.WEBDAV_PASSWORD}";
41 | };
42 | }
43 | {
44 | handler = "webdav";
45 | root = srvPath;
46 | # Workaround: prefix makes HEAD fail with 405 (Method Not Allowed)
47 | # See: https://github.com/mholt/caddy-webdav/issues/19
48 | # prefix = route;
49 | }
50 | ];
51 | };
52 | }
53 |
--------------------------------------------------------------------------------
/nixos/minimal-image/configuration.nix:
--------------------------------------------------------------------------------
1 | # NB. systemd-initrd doesn't work for ISO yet.
2 | { lib, config, pkgs, modulesPath, my, ... }:
3 | {
4 | imports = [
5 | (modulesPath + "/installer/cd-dvd/installation-cd-minimal-new-kernel-no-zfs.nix")
6 | ../modules/console-env.nix
7 | ../modules/nix-binary-cache-mirror.nix
8 | ];
9 |
10 | isoImage = {
11 | isoBaseName = lib.mkForce "nixoxa";
12 | volumeID = "NIXOXA";
13 | # Worse compression but way faster.
14 | squashfsCompression = "zstd -Xcompression-level 6";
15 | };
16 |
17 | # Workaround: https://github.com/NixOS/nixpkgs/issues/254807
18 | boot.swraid.enable = lib.mkForce false;
19 |
20 | networking.hostName = "nixoxa";
21 | networking.wireless.enable = true;
22 |
23 | nix = {
24 | settings = {
25 | experimental-features = [
26 | "nix-command"
27 | "flakes"
28 | ];
29 |
30 | flake-registry = "";
31 | };
32 |
33 | nixPath = [ "nixpkgs=${config.nix.registry.nixpkgs.to.path}" ];
34 | };
35 |
36 | environment.systemPackages = with pkgs; [
37 | neofetch
38 | sbctl # Secure boot.
39 | ];
40 |
41 | users.users.root.openssh.authorizedKeys.keys = with my.ssh.identities; [ oxa ];
42 | services.openssh = {
43 | enable = true;
44 | settings = {
45 | PasswordAuthentication = false;
46 | KbdInteractiveAuthentication = false;
47 | PermitRootLogin = lib.mkForce "prohibit-password";
48 | };
49 | };
50 |
51 | system.stateVersion = "24.11";
52 | }
53 |
--------------------------------------------------------------------------------
/nixos/modules/console-env.nix:
--------------------------------------------------------------------------------
1 | { lib, pkgs, my, ... }:
2 | {
3 | # Reduce the closure size.
4 | i18n.supportedLocales = lib.mkDefault [ "en_US.UTF-8/UTF-8" ];
5 | i18n.defaultLocale = lib.mkDefault "en_US.UTF-8";
6 |
7 | fonts.fontconfig.enable = lib.mkDefault false;
8 |
9 | # Default:
10 | # - perl # No.
11 | # - rsync strace # Already in systemPackages.
12 | environment.defaultPackages = [ ];
13 |
14 | environment.systemPackages = with pkgs; [
15 | cntr # Nix helpers.
16 | btdu procs ncdu swapview smartmontools pciutils usbutils # System info.
17 | moreutils curl git strace pv tree fd ripgrep lsof jq bc file rsync dnsutils # Utilities.
18 | compsize e2fsprogs # Filesystems.
19 | gnupg age pwgen sops ssh-to-age # Crypto.
20 | libarchive zstd # Compression.
21 |
22 | my.pkgs.nixos-rebuild-shortcut
23 | ];
24 |
25 | programs.less = {
26 | enable = true;
27 | lessopen = null;
28 | };
29 | environment.variables = let
30 | common = [
31 | "--RAW-CONTROL-CHARS" # Only allow colors.
32 | "--mouse"
33 | "--wheel-lines=5"
34 | "--LONG-PROMPT"
35 | ];
36 | in {
37 | PAGER = "less";
38 | # Don't use `programs.less.envVariables.LESS`, which will be override by `LESS` set by `man`.
39 | LESS = lib.concatStringsSep " " common;
40 | SYSTEMD_LESS = lib.concatStringsSep " " (common ++ [
41 | "--quit-if-one-screen"
42 | "--chop-long-lines"
43 | "--no-init" # Keep content after quit.
44 | ]);
45 | };
46 |
47 | programs.tmux.enable = true;
48 |
49 | programs.htop.enable = true;
50 | programs.iotop.enable = true;
51 | programs.iftop.enable = true;
52 |
53 | programs.mtr.enable = true;
54 |
55 | # Don't stuck for searching missing commands.
56 | programs.command-not-found.enable = false;
57 |
58 | programs.vim = {
59 | enable = true;
60 | defaultEditor = true;
61 | };
62 |
63 | programs.nano.enable = lib.mkDefault false;
64 | }
65 |
--------------------------------------------------------------------------------
/nixos/modules/device-fix.nix:
--------------------------------------------------------------------------------
1 | { ... }:
2 | {
3 | # Fix Fn2 for MIIIW Keyboard.
4 | boot.extraModprobeConfig = ''
5 | options hid_apple fnmode=2
6 | '';
7 |
8 | # Enable TRIM for the WD harddisk.
9 | services.udev.extraRules = ''
10 | ACTION=="add|change", ATTRS{idVendor}=="1058", ATTRS{idProduct}=="25a2", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"
11 | '';
12 | }
13 |
--------------------------------------------------------------------------------
/nixos/modules/kde-desktop/default.nix:
--------------------------------------------------------------------------------
1 | { pkgs, ... }:
2 | {
3 | imports = [ ../l10n.nix ];
4 |
5 | environment.systemPackages = with pkgs.kdePackages; [
6 | filelight
7 | kolourpaint
8 | okular
9 | gwenview
10 | pkgs.qpwgraph
11 | ];
12 |
13 | programs = {
14 | partition-manager.enable = true;
15 | kdeconnect.enable = true;
16 | };
17 |
18 | services.desktopManager.plasma6.enable = true;
19 | services.displayManager.sddm = {
20 | enable = true;
21 | wayland.enable = true;
22 | };
23 |
24 | networking.networkmanager.enable = true;
25 | }
26 |
--------------------------------------------------------------------------------
/nixos/modules/l10n.nix:
--------------------------------------------------------------------------------
1 | { lib, pkgs, my, ... }:
2 | {
3 | i18n = {
4 | supportedLocales = [ "all" ]; # Override console-env.
5 | defaultLocale = "en_CA.UTF-8";
6 | inputMethod = {
7 | enable = true;
8 | type = "fcitx5";
9 | fcitx5 = {
10 | addons = with pkgs; [
11 | (fcitx5-rime.override {
12 | rimeDataPkgs = [ rime-data my.pkgs.rime_latex ];
13 | })
14 | ];
15 | };
16 | };
17 | };
18 |
19 | # Ref: https://catcat.cc/post/2021-03-07/
20 | fonts = {
21 | enableDefaultPackages = false;
22 | fontDir.enable = true;
23 |
24 | packages = with pkgs; [
25 | noto-fonts
26 | noto-fonts-cjk-sans
27 | noto-fonts-cjk-serif
28 | noto-fonts-color-emoji
29 | twemoji-color-font
30 | font-awesome
31 | hanazono
32 | # Use bin to save build time (~11min).
33 | (iosevka-bin.override { variant = "SGr-IosevkaFixed"; })
34 |
35 | # Roman for PDF.
36 | liberation_ttf
37 | ];
38 |
39 | fontconfig = {
40 | enable = true;
41 |
42 | defaultFonts = {
43 | monospace = [ "Iosevka Fixed" "Noto Sans CJK SC" "Font Awesome 6 Free" "Twemoji" ];
44 | sansSerif = [ "Noto Sans" "Noto Sans CJK SC" "Twemoji" ];
45 | serif = [ "Noto Serif" "Noto Serif CJK SC" "Twemoji" ];
46 | emoji = [ "Twemoji" ];
47 | };
48 |
49 | localConf = ''
50 |
51 |
52 |
53 |
54 | ${lib.concatMapStringsSep "\n" ({ lang, variant }:
55 | let
56 | replace = from: to: ''
57 |
58 |
59 | ${lang}
60 |
61 |
62 | ${from}
63 |
64 |
65 | ${to}
66 |
67 |
68 | '';
69 | in
70 | replace "sans-serif" "Noto Sans CJK ${variant}" +
71 | replace "serif" "Noto Serif CJK ${variant}"
72 | ) [
73 | { lang = "zh"; variant = "SC"; }
74 | { lang = "zh-TW"; variant = "TC"; }
75 | { lang = "zh-HK"; variant = "HK"; }
76 | { lang = "ja"; variant = "JP"; }
77 | { lang = "ko"; variant = "KR"; }
78 | ]}
79 |
80 | '';
81 | };
82 | };
83 | }
84 |
--------------------------------------------------------------------------------
/nixos/modules/nix-binary-cache-mirror.nix:
--------------------------------------------------------------------------------
1 | { lib, ... }:
2 | let
3 | urls = [
4 | # "https://mirror.sjtu.edu.cn/nix-channels/store" # Frequent download stall.
5 | "https://mirrors.bfsu.edu.cn/nix-channels/store"
6 |
7 | # Do no try to enable TUNA! Scary thing will happen!
8 | # "https://mirrors.tuna.tsinghua.edu.cn/nix-channels/store" # May suffer from download stalled issue.
9 | # "https://mirrors.ustc.edu.cn/nix-channels/store"
10 | ];
11 | in
12 | {
13 | nix.settings.substituters = lib.mkBefore urls;
14 | }
15 |
--------------------------------------------------------------------------------
/nixos/modules/nix-cgroups.nix:
--------------------------------------------------------------------------------
1 | {
2 | nix.settings = {
3 | experimental-features = [
4 | "auto-allocate-uids"
5 | "cgroups"
6 | ];
7 | auto-allocate-uids = true;
8 | use-cgroups = true;
9 | };
10 | }
11 |
--------------------------------------------------------------------------------
/nixos/modules/nix-common.nix:
--------------------------------------------------------------------------------
1 | { lib, pkgs, inputs, ... }:
2 | {
3 | # Ensure this is >= 2.22.1 with the following fix included, or it failes to eval.
4 | # https://github.com/NixOS/nix/pull/10456
5 | nix.package = lib.mkDefault pkgs.nixVersions.latest;
6 |
7 | nix.channel.enable = false;
8 |
9 | nix.gc = {
10 | automatic = true;
11 | dates = "Wed,Sat 01:00";
12 | options = "--delete-older-than 8d";
13 | persistent = false;
14 | };
15 | systemd.services.nix-gc.serviceConfig = {
16 | Nice = 19;
17 | IOSchedulingClass = "idle";
18 | MemorySwapMax = 0;
19 | };
20 |
21 | nix.settings = {
22 | experimental-features = [
23 | "nix-command"
24 | "flakes"
25 | "ca-derivations"
26 | ];
27 |
28 | flake-registry = "";
29 |
30 | allow-import-from-derivation = false;
31 | auto-optimise-store = true;
32 | trusted-users = [ "root" "@wheel" ];
33 |
34 | connect-timeout = 10;
35 | download-attempts = 3;
36 | stalled-download-timeout = 10;
37 |
38 | # Workaround: https://github.com/NixOS/nixpkgs/pull/273170
39 | nix-path = "nixpkgs=${inputs.nixpkgs}";
40 | };
41 |
42 | nix.registry = {
43 | nixpkgs = {
44 | from = { id = "nixpkgs"; type = "indirect"; };
45 | flake = inputs.nixpkgs;
46 | };
47 | };
48 |
49 | nix.nixPath = [
50 | "nixpkgs=${inputs.nixpkgs}"
51 | ];
52 | }
53 |
--------------------------------------------------------------------------------
/nixos/modules/nix-keep-flake-inputs.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | {
3 | system.extraDependencies = let
4 | collectFlakeInputs =
5 | input: [ input ] ++ builtins.concatMap collectFlakeInputs (builtins.attrValues (input.inputs or {}));
6 | in
7 | builtins.concatMap collectFlakeInputs (builtins.attrValues inputs);
8 | }
9 |
--------------------------------------------------------------------------------
/nixos/modules/nix-registry.nix:
--------------------------------------------------------------------------------
1 | { lib, inputs, ... }:
2 | {
3 | nix.registry = lib.mapAttrs (name: value: {
4 | flake = value;
5 | }) inputs;
6 | }
7 |
--------------------------------------------------------------------------------
/nixos/modules/secure-boot.nix:
--------------------------------------------------------------------------------
1 | # https://github.com/nix-community/lanzaboote/blob/master/docs/QUICK_START.md
2 | { pkgs, inputs, ... }:
3 | {
4 | imports = [
5 | inputs.lanzaboote.nixosModules.lanzaboote
6 | ];
7 |
8 | # This should already be here from switching to bootspec earlier.
9 | # It's not required anymore, but also doesn't do any harm.
10 | boot.bootspec.enable = true;
11 |
12 | environment.systemPackages = [
13 | pkgs.sbctl
14 | ];
15 |
16 | # Lanzaboote currently replaces the systemd-boot module.
17 | # This setting is usually set to true in configuration.nix
18 | # generated at installation time. So we force it to false
19 | # for now.
20 | boot.loader.systemd-boot.enable = false;
21 |
22 | boot.lanzaboote = {
23 | enable = true;
24 | # See: https://github.com/nix-community/lanzaboote/issues/413
25 | pkiBundle = "/var/lib/sbctl";
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/nixos/modules/server-env.nix:
--------------------------------------------------------------------------------
1 | { lib, pkgs, ... }:
2 | {
3 | # Reduce the closure size.
4 | i18n.supportedLocales = [ "en_US.UTF-8/UTF-8" ];
5 | i18n.defaultLocale = "en_US.UTF-8";
6 | fonts.fontconfig.enable = false;
7 | documentation = {
8 | enable = false;
9 | man.enable = false;
10 | info.enable = lib.mkDefault false;
11 | };
12 |
13 | # Partially copied from `nixos/modules/profiles/perlless.nix`.
14 | system.disableInstallerTools = lib.mkDefault true;
15 | boot.enableContainers = lib.mkDefault false;
16 |
17 | # Default:
18 | # - perl # No.
19 | # - rsync strace # Already in systemPackages.
20 | environment.defaultPackages = [ ];
21 |
22 | environment.systemPackages = with pkgs; [
23 | # Utilities.
24 | compsize
25 | curl
26 | dnsutils
27 | fd
28 | file
29 | jq
30 | libarchive
31 | lsof
32 | ncdu
33 | procs
34 | pv
35 | ripgrep
36 | rsync
37 | strace
38 | tree
39 | zstd
40 |
41 | # Cryptography.
42 | age
43 | gnupg
44 | ssh-to-age
45 |
46 | # Version control.
47 | gitMinimal
48 | ];
49 |
50 | programs.less = {
51 | enable = true;
52 | lessopen = null;
53 | };
54 | environment.variables =
55 | let
56 | common = [
57 | "--RAW-CONTROL-CHARS" # Only allow colors.
58 | "--mouse"
59 | "--wheel-lines=5"
60 | "--LONG-PROMPT"
61 | ];
62 | in
63 | {
64 | PAGER = "less";
65 | # Don't use `programs.less.envVariables.LESS`, which will be override by `LESS` set by `man`.
66 | LESS = lib.concatStringsSep " " common;
67 | SYSTEMD_LESS = lib.concatStringsSep " " (
68 | common
69 | ++ [
70 | "--quit-if-one-screen"
71 | "--chop-long-lines"
72 | "--no-init" # Keep content after quit.
73 | ]
74 | );
75 | };
76 |
77 | programs.tmux.enable = true;
78 |
79 | programs.htop.enable = true;
80 | programs.iotop.enable = true;
81 | programs.iftop.enable = true;
82 |
83 | programs.mtr.enable = true;
84 |
85 | programs.command-not-found.enable = false;
86 |
87 | programs.vim = {
88 | enable = true;
89 | defaultEditor = true;
90 | };
91 |
92 | programs.nano.enable = lib.mkDefault false;
93 | }
94 |
--------------------------------------------------------------------------------
/nixos/modules/vultr-common.nix:
--------------------------------------------------------------------------------
1 | { lib, pkgs, modulesPath, my, ... }:
2 | {
3 | imports = [
4 | "${modulesPath}/profiles/qemu-guest.nix"
5 |
6 | ../modules/nix-common.nix
7 | ../modules/server-env.nix
8 | ../modules/zswap-enable.nix
9 | ./vultr-image.nix
10 | ];
11 |
12 | boot.loader.systemd-boot.enable = true;
13 | boot.loader.timeout = 1;
14 |
15 | boot.initrd.systemd.enable = true;
16 | boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "sr_mod" ];
17 | boot.initrd.kernelModules = [ ];
18 | boot.kernelModules = [ ];
19 | boot.extraModulePackages = [ ];
20 |
21 | boot.kernel.sysctl = {
22 | "net.ipv4.tcp_congestion_control" = "bbr";
23 | };
24 |
25 | fileSystems."/" = {
26 | device = "/dev/disk/by-label/nixos";
27 | fsType = "btrfs";
28 | options = [ "noatime" "compress=zstd" ];
29 | };
30 | fileSystems."/boot" = {
31 | device = "/dev/disk/by-label/ESP";
32 | fsType = "vfat";
33 | };
34 |
35 | swapDevices = [ ];
36 |
37 | networking.useNetworkd = true;
38 | networking.useDHCP = false;
39 | networking.interfaces.enp1s0.useDHCP = true;
40 | networking.firewall.enable = false; # Already have a hardware firewall.
41 | networking.nameservers = [
42 | "1.1.1.1" "1.0.0.1"
43 | "2606:4700:4700::1111" "2606:4700:4700::1001"
44 | ];
45 |
46 | systemd.sysusers.enable = lib.mkDefault true;
47 | users.mutableUsers = lib.mkDefault false;
48 | users.users.root.openssh.authorizedKeys.keys = with my.ssh.identities; [ oxa ];
49 | services.getty.autologinUser = lib.mkDefault "root";
50 |
51 | nix.package = pkgs.nix;
52 | nix.gc.options = lib.mkForce "--delete-older-than 3d";
53 | # Avoid dependency to nixpkgs itself.
54 | nix.settings.nix-path = lib.mkForce "";
55 | nix.registry = lib.mkForce { };
56 | nix.nixPath = lib.mkForce [ ];
57 |
58 | services.openssh = {
59 | enable = true;
60 | ports = [ 798 ];
61 | settings = {
62 | PasswordAuthentication = false;
63 | KbdInteractiveAuthentication = false;
64 | PermitRootLogin = "prohibit-password";
65 | };
66 | };
67 | }
68 |
--------------------------------------------------------------------------------
/nixos/modules/vultr-image.nix:
--------------------------------------------------------------------------------
1 | # Ref: https://x86.lol/generic/2024/08/28/systemd-sysupdate.html
2 | {
3 | lib,
4 | config,
5 | pkgs,
6 | modulesPath,
7 | ...
8 | }:
9 | let
10 | inherit (lib)
11 | mkOption
12 | types
13 | ;
14 |
15 | inherit (pkgs.hostPlatform) efiArch;
16 |
17 | cfg = config.vultrImage;
18 | in
19 | {
20 | imports = [
21 | (modulesPath + "/image/repart.nix")
22 | ];
23 |
24 | options.vultrImage = {
25 | name = mkOption {
26 | type = types.str;
27 | description = "The name of the generated derivation";
28 | default = "nixos-vultr-image-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}";
29 | };
30 |
31 | efiPartSize = mkOption {
32 | type = types.str;
33 | default = "128M";
34 | example = "256M";
35 | description = "The start offset of EFI partition.";
36 | };
37 | };
38 |
39 | config.image.repart = {
40 | name = cfg.name;
41 | compression.enable = true;
42 | mkfsOptions.btrfs = [ "--shrink" ];
43 | partitions = {
44 | "10-esp" = {
45 | contents = {
46 | "/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source = "${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi";
47 | "/EFI/Linux/${config.system.boot.loader.ukiFile}".source = "${config.system.build.uki}/${config.system.boot.loader.ukiFile}";
48 | };
49 | repartConfig = {
50 | Label = "ESP";
51 | Type = "esp";
52 | Format = "vfat";
53 | SizeMinBytes = cfg.efiPartSize;
54 | SizeMaxBytes = cfg.efiPartSize;
55 | };
56 | };
57 | "20-root" = {
58 | storePaths = [ config.system.build.toplevel ];
59 | repartConfig = {
60 | Label = "nixos";
61 | Type = "root";
62 | Format = "btrfs";
63 | Minimize = "guess";
64 | # WAIT: `Compression=` requires https://github.com/kdave/btrfs-progs/pull/882
65 | };
66 | };
67 | };
68 | };
69 | }
70 |
--------------------------------------------------------------------------------
/nixos/modules/zswap-enable.nix:
--------------------------------------------------------------------------------
1 | { ... }: {
2 | systemd.tmpfiles.settings."zswap" = {
3 | "/sys/module/zswap/parameters/enabled"."w-".argument = "1";
4 | "/sys/module/zswap/parameters/zpool"."w-".argument = "zsmalloc";
5 | };
6 | }
7 |
--------------------------------------------------------------------------------
/nixos/unmatched/configuration.nix:
--------------------------------------------------------------------------------
1 | # From: https://github.com/NickCao/nixos-riscv/blob/720c8ee6fc8eee85f741e309a4e0291dc3a90f59/flake.nix#L82
2 | { pkgs, lib, inputs, my, ... }:
3 | {
4 | imports = [
5 | # (modulesPath + "/installer/sd-card/sd-image.nix")
6 | # ../modules/console-env.nix
7 | ];
8 |
9 | disabledModules = [ "profiles/all-hardware.nix" ];
10 |
11 | # For firmware.
12 | nixpkgs.config.allowUnfree = true;
13 |
14 | nixpkgs.overlays = [
15 | (final: prev: {
16 | boost = final.boost17x;
17 | })
18 | ];
19 |
20 | /*
21 | sdImage = {
22 | populateRootCommands = ''
23 | mkdir -p ./files/boot
24 | ${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
25 | '';
26 | populateFirmwareCommands = "";
27 | };
28 | */
29 |
30 | boot.loader = {
31 | grub.enable = false;
32 | generic-extlinux-compatible.enable = true;
33 | generic-extlinux-compatible.configurationLimit = 5;
34 | };
35 | boot.initrd.kernelModules = [ "nvme" "mmc_block" "mmc_spi" "spi_sifive" "spi_nor" "uas" "sdhci_pci" ];
36 | boot.kernelParams = [ "loglevel=7" ]; # DEBUG
37 | boot.kernelPackages = pkgs.linuxPackages_latest;
38 | boot.kernelPatches = map (patch: { name = patch; patch = inputs.meta-sifive + "/recipes-kernel/linux/files/${patch}"; }) [
39 | "0001-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch"
40 | "0002-riscv-sifive-unmatched-update-regulators-values.patch"
41 | "0003-riscv-sifive-unmatched-define-PWM-LEDs.patch"
42 | "0004-riscv-sifive-unmatched-add-gpio-poweroff-node.patch"
43 | "0005-SiFive-HiFive-Unleashed-Add-PWM-LEDs-D1-D2-D3-D4.patch"
44 | "0006-riscv-sifive-unleashed-define-opp-table-cpufreq.patch"
45 | "riscv-sbi-srst-support.patch"
46 | ] ++ [
47 | {
48 | name = "sifive";
49 | patch = null;
50 | extraConfig = ''
51 | SOC_SIFIVE y
52 | PCIE_FU740 y
53 | PWM_SIFIVE y
54 | EDAC_SIFIVE y
55 | SIFIVE_L2 y
56 | RISCV_ERRATA_ALTERNATIVE y
57 | ERRATA_SIFIVE y
58 | ERRATA_SIFIVE_CIP_453 y
59 | ERRATA_SIFIVE_CIP_1200 y
60 | '';
61 | }
62 | # https://github.com/zhaofengli/unmatched-nixos/blob/e04fff15b62846d5151c0d98da79398e238b69f6/pkgs/linux/default.nix
63 | {
64 | name = "cpufreq";
65 | patch = null;
66 | extraConfig = ''
67 | CPU_IDLE y
68 | CPU_FREQ y
69 | CPU_FREQ_DEFAULT_GOV_USERSPACE y
70 | CPU_FREQ_GOV_PERFORMANCE y
71 | CPU_FREQ_GOV_USERSPACE y
72 | CPU_FREQ_GOV_ONDEMAND y
73 | '';
74 | }
75 | ];
76 |
77 | fileSystems."/" = {
78 | device = "/dev/disk/by-uuid/27b822c9-7087-4f52-8b7e-88a0ac476808";
79 | fsType = "ext4";
80 | };
81 | fileSystems."/boot" = {
82 | device = "/dev/disk/by-uuid/3A9E-9961";
83 | fsType = "vfat";
84 | };
85 | swapDevices = [
86 | {
87 | device = "/var/swapfile";
88 | size = 4 * 1024; # 4G
89 | }
90 | ];
91 |
92 | systemd.services."pwm-fan" = {
93 | description = "PWM fan control";
94 | wantedBy = [ "basic.target" ];
95 | after = [ "-.mount" ];
96 | path = [ pkgs.coreutils ];
97 |
98 | serviceConfig = {
99 | Type = "oneshot";
100 | RemainAfterExit = true;
101 | Restart = "on-failure";
102 | };
103 |
104 | script = ''
105 | cd /sys/class/pwm/pwmchip4
106 | [[ -d pwm2 ]] || echo 2 >export
107 | cd pwm2
108 | echo 0 >duty_cycle || true
109 | echo 10000000 >period
110 | echo 800000 >duty_cycle
111 | echo 1 >enable
112 | '';
113 |
114 | preStop = ''
115 | cd /sys/class/pwm/pwmchip4
116 | [[ ! -d pwm2 ]] || echo 0 >pwm2/enable
117 | '';
118 | };
119 |
120 | documentation.nixos.enable = false;
121 | services.udisks2.enable = false;
122 | security.polkit.enable = false;
123 |
124 | services.getty.autologinUser = "root";
125 | services.openssh.enable = true;
126 |
127 | environment.systemPackages = with pkgs; [
128 | neofetch
129 | lm_sensors
130 | pciutils
131 | htop
132 | git
133 | lsof
134 | btrfs-progs
135 | tmux
136 | ];
137 |
138 | hardware.firmware = with pkgs; [ firmwareLinuxNonfree ];
139 | # hardware.opengl.enable = true;
140 | # programs.sway.enable = true;
141 |
142 | i18n.supportedLocales = lib.mkDefault [ "en_US.UTF-8/UTF-8" ];
143 | i18n.defaultLocale = lib.mkDefault "en_US.UTF-8";
144 | fonts.fontconfig.enable = false;
145 | programs.command-not-found.enable = false;
146 |
147 | # Don't use vim_configurable.
148 | programs.vim = {
149 | enable = true;
150 | defaultEditor = true;
151 | };
152 |
153 | nix = {
154 | extraOptions = ''
155 | experimental-features = nix-command flakes
156 | keep-outputs = true # Keep build-dependencies.
157 | flake-registry = /etc/nix/registry.json
158 | '';
159 |
160 | registry = {
161 | nixpkgs = {
162 | from = { id = "nixpkgs"; type = "indirect"; };
163 | flake = inputs.nixpkgs-unmatched;
164 | };
165 | };
166 |
167 | binaryCaches = lib.mkBefore [
168 | "https://riscv64.cachix.org"
169 | ];
170 | };
171 |
172 | users = {
173 | mutableUsers = false;
174 | users.root.openssh.authorizedKeys.keys = with my.ssh.identities; [ oxa invar blacksteel ];
175 | };
176 | }
177 |
--------------------------------------------------------------------------------
/pkgs/_sources/generated.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors": {
3 | "cargoLocks": null,
4 | "date": null,
5 | "extract": null,
6 | "name": "colors",
7 | "passthru": null,
8 | "pinned": false,
9 | "src": {
10 | "name": null,
11 | "sha256": "sha256-l/RTPZp2v7Y4ffJRT5Fy5Z3TDB4dvWfE7wqMbquXdJA=",
12 | "type": "url",
13 | "url": "https://gist.githubusercontent.com/lilydjwg/fdeaf79e921c2f413f44b6f613f6ad53/raw/94d8b2be62657e96488038b0e547e3009ed87d40/colors.py"
14 | },
15 | "version": "94d8b2be62657e96488038b0e547e3009ed87d40"
16 | },
17 | "rime_latex": {
18 | "cargoLocks": null,
19 | "date": "2025-04-03",
20 | "extract": null,
21 | "name": "rime_latex",
22 | "passthru": null,
23 | "pinned": false,
24 | "src": {
25 | "deepClone": false,
26 | "fetchSubmodules": false,
27 | "leaveDotGit": false,
28 | "name": null,
29 | "owner": "shenlebantongying",
30 | "repo": "rime_latex",
31 | "rev": "858f2abc645f0e459e468e98122470ce20b16b30",
32 | "sha256": "sha256-i8Rgze+tQhbE+nl+JSj09ILXeUvf6MOS9Eqsuqis1n0=",
33 | "sparseCheckout": [],
34 | "type": "github"
35 | },
36 | "version": "858f2abc645f0e459e468e98122470ce20b16b30"
37 | }
38 | }
--------------------------------------------------------------------------------
/pkgs/_sources/generated.nix:
--------------------------------------------------------------------------------
1 | # This file was generated by nvfetcher, please do not modify it manually.
2 | { fetchgit, fetchurl, fetchFromGitHub, dockerTools }:
3 | {
4 | colors = {
5 | pname = "colors";
6 | version = "94d8b2be62657e96488038b0e547e3009ed87d40";
7 | src = fetchurl {
8 | url = "https://gist.githubusercontent.com/lilydjwg/fdeaf79e921c2f413f44b6f613f6ad53/raw/94d8b2be62657e96488038b0e547e3009ed87d40/colors.py";
9 | sha256 = "sha256-l/RTPZp2v7Y4ffJRT5Fy5Z3TDB4dvWfE7wqMbquXdJA=";
10 | };
11 | };
12 | rime_latex = {
13 | pname = "rime_latex";
14 | version = "858f2abc645f0e459e468e98122470ce20b16b30";
15 | src = fetchFromGitHub {
16 | owner = "shenlebantongying";
17 | repo = "rime_latex";
18 | rev = "858f2abc645f0e459e468e98122470ce20b16b30";
19 | fetchSubmodules = false;
20 | sha256 = "sha256-i8Rgze+tQhbE+nl+JSj09ILXeUvf6MOS9Eqsuqis1n0=";
21 | };
22 | date = "2025-04-03";
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/pkgs/caddy-oxa/0001-caddyauth-use-same-cost-for-users-and-fake-hash.patch:
--------------------------------------------------------------------------------
1 | From ffce3249f373dfc7f25b45cb99b3e7902df4dfcd Mon Sep 17 00:00:00 2001
2 | From: oxalica
3 | Date: Thu, 29 Aug 2024 12:55:30 -0400
4 | Subject: [PATCH] caddyauth: use same cost for users and fake hash
5 |
6 | This prevents timing attack when user provided hash is different than
7 | the fake hash.
8 | ---
9 | modules/caddyhttp/caddyauth/basicauth.go | 32 +++++++++++++++++++-----
10 | modules/caddyhttp/caddyauth/hashes.go | 6 ++---
11 | 2 files changed, 28 insertions(+), 10 deletions(-)
12 |
13 | diff --git a/modules/caddyhttp/caddyauth/basicauth.go b/modules/caddyhttp/caddyauth/basicauth.go
14 | index 52a5a08c..8438c416 100644
15 | --- a/modules/caddyhttp/caddyauth/basicauth.go
16 | +++ b/modules/caddyhttp/caddyauth/basicauth.go
17 | @@ -24,6 +24,7 @@ import (
18 | "strings"
19 | "sync"
20 |
21 | + "golang.org/x/crypto/bcrypt"
22 | "golang.org/x/sync/singleflight"
23 |
24 | "github.com/caddyserver/caddy/v2"
25 | @@ -92,15 +93,11 @@ func (hba *HTTPBasicAuth) Provision(ctx caddy.Context) error {
26 | return fmt.Errorf("hash is required")
27 | }
28 |
29 | - // if supported, generate a fake password we can compare against if needed
30 | - if hasher, ok := hba.Hash.(Hasher); ok {
31 | - hba.fakePassword = hasher.FakeHash()
32 | - }
33 | -
34 | repl := caddy.NewReplacer()
35 |
36 | // load account list
37 | hba.Accounts = make(map[string]Account)
38 | + hashCost := 0
39 | for i, acct := range hba.AccountList {
40 | if _, ok := hba.Accounts[acct.Username]; ok {
41 | return fmt.Errorf("account %d: username is not unique: %s", i, acct.Username)
42 | @@ -126,10 +123,33 @@ func (hba *HTTPBasicAuth) Provision(ctx caddy.Context) error {
43 | }
44 | }
45 |
46 | + // FIXME: Only support bcrypt here.
47 | + curHashCost, err := bcrypt.Cost(acct.password)
48 | + if err != nil {
49 | + return fmt.Errorf("account %d: invalid bcrypt hash, must be a bcrypt-2a hash");
50 | + }
51 | + if hashCost != 0 && hashCost != curHashCost {
52 | + return fmt.Errorf("account %d: all bcrypt cost must be the same");
53 | + }
54 | + hashCost = curHashCost
55 | +
56 | hba.Accounts[acct.Username] = acct
57 | }
58 | hba.AccountList = nil // allow GC to deallocate
59 |
60 | + if hashCost == 0 {
61 | + // FIXME: Hardcoded default cost.
62 | + hashCost = 14;
63 | + }
64 | +
65 | + // if supported, generate a fake password we can compare against if needed
66 | + if hasher, ok := hba.Hash.(Hasher); ok {
67 | + hba.fakePassword, err = hasher.FakeHash(hashCost)
68 | + if err != nil {
69 | + return fmt.Errorf("failed to generate fake hash");
70 | + }
71 | + }
72 | +
73 | if hba.HashCache != nil {
74 | hba.HashCache.cache = make(map[string]bool)
75 | hba.HashCache.mu = new(sync.RWMutex)
76 | @@ -280,7 +300,7 @@ type Comparer interface {
77 | // can be used for timing side-channel mitigation.
78 | type Hasher interface {
79 | Hash(plaintext []byte) ([]byte, error)
80 | - FakeHash() []byte
81 | + FakeHash(cost int) ([]byte, error)
82 | }
83 |
84 | // Account contains a username and password.
85 | diff --git a/modules/caddyhttp/caddyauth/hashes.go b/modules/caddyhttp/caddyauth/hashes.go
86 | index ce3df901..c02f5f27 100644
87 | --- a/modules/caddyhttp/caddyauth/hashes.go
88 | +++ b/modules/caddyhttp/caddyauth/hashes.go
89 | @@ -53,10 +53,8 @@ func (BcryptHash) Hash(plaintext []byte) ([]byte, error) {
90 | }
91 |
92 | // FakeHash returns a fake hash.
93 | -func (BcryptHash) FakeHash() []byte {
94 | - // hashed with the following command:
95 | - // caddy hash-password --plaintext "antitiming" --algorithm "bcrypt"
96 | - return []byte("$2a$14$X3ulqf/iGxnf1k6oMZ.RZeJUoqI9PX2PM4rS5lkIKJXduLGXGPrt6")
97 | +func (BcryptHash) FakeHash(cost int) ([]byte, error) {
98 | + return bcrypt.GenerateFromPassword([]byte("antitiming"), cost)
99 | }
100 |
101 | // Interface guards
102 | --
103 | 2.47.0
104 |
105 |
--------------------------------------------------------------------------------
/pkgs/caddy-oxa/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | lib,
3 | caddy,
4 | }:
5 | let
6 | caddy' = caddy.withPlugins {
7 | plugins = [
8 | "github.com/mholt/caddy-webdav@v0.0.0-20241008162340-42168ba04c9d"
9 | ];
10 | hash = "sha256-fURqPgMpZ17ubhvr+JmY8jBgDaKBb654wo9Z4izjlro=";
11 | };
12 |
13 | caddy'' = caddy'.overrideAttrs (old: {
14 | # NB. Overriding `version` will break the build. Because it seems to be
15 | # popular to use `finalAttrs.version` in build steps. Sad.
16 | pname = old.pname + "-oxa";
17 | prePatch = "pushd vendor/github.com/caddyserver/caddy/v2";
18 | patches =
19 | assert old.patches or [ ] == [ ];
20 | [
21 | ./0001-caddyauth-use-same-cost-for-users-and-fake-hash.patch
22 | ];
23 | postPatch = "popd";
24 | });
25 |
26 | in
27 | caddy''
28 |
--------------------------------------------------------------------------------
/pkgs/cargo-machete-no-spam.nix:
--------------------------------------------------------------------------------
1 | { cargo-machete, fetchpatch }:
2 | cargo-machete.overrideAttrs (old: {
3 | patches = old.patches or [ ] ++ [
4 | # https://github.com/bnjbvr/cargo-machete/pull/134
5 | (fetchpatch {
6 | url = "https://github.com/oxalica/cargo-machete/commit/c70efceea0ee894c692da1e443da5da15703e609.patch";
7 | hash = "sha256-q7Pd0MTQTs6h1hlyt2l1WwKadKpphXNVnGByQutoTq8=";
8 | excludes = [ "CHANGELOG.md" ];
9 | })
10 | ];
11 | })
12 |
--------------------------------------------------------------------------------
/pkgs/coc-rust-analyzer-fix-snippet/default.nix:
--------------------------------------------------------------------------------
1 | # See: https://github.com/fannheyward/coc-rust-analyzer/issues/1279
2 | {
3 | lib,
4 | fetchFromGitHub,
5 | buildNpmPackage,
6 | vimPlugins,
7 | }:
8 | let
9 | nodePkg = buildNpmPackage rec {
10 | pname = "coc-rust-analyzer";
11 | version = "0-unstable-2025-01-20";
12 |
13 | src = fetchFromGitHub {
14 | owner = "fannheyward";
15 | repo = pname;
16 | rev = "a4d6aa3a5d7fcf9e701a687f5a6953067ab55cb7";
17 | hash = "sha256-/890Ns1LFc/OVN4ZxYf9Kr8etXooeK2YUZW1DdV/mrw=";
18 | };
19 | npmDepsHash = "sha256-lowD4iS/5moizMHe9cFqX2h/2eAx2RIL/LaTq+IduvU=";
20 |
21 | meta.license = lib.licenses.mit;
22 | };
23 |
24 | vimPkg = vimPlugins.coc-rust-analyzer.overrideAttrs {
25 | src = "${nodePkg}/lib/node_modules/coc-rust-analyzer";
26 | };
27 |
28 | in
29 | vimPkg
30 |
--------------------------------------------------------------------------------
/pkgs/colors.nix:
--------------------------------------------------------------------------------
1 | { source, runCommand, python3 }:
2 | runCommand source.pname {
3 | inherit (source) src;
4 | nativeBuildInputs = [ python3 ];
5 | } ''
6 | install -Dm555 $src $out/bin/colors
7 | patchShebangs $out/bin
8 | ''
9 |
--------------------------------------------------------------------------------
/pkgs/default.nix:
--------------------------------------------------------------------------------
1 | { lib, pkgs, inputs }:
2 | let
3 | inherit (builtins) readDir;
4 | inherit (lib) mapAttrs' filterAttrs;
5 |
6 | sources = pkgs.callPackage ./_sources/generated.nix { };
7 | entries = removeAttrs (readDir ./.) [ "_sources" "default.nix" "nvfetcher.toml" ];
8 |
9 | self = mapAttrs' (file: _: rec {
10 | name = lib.removeSuffix ".nix" file;
11 | value = pkgs.newScope (self // {
12 | inherit inputs;
13 | source = sources.${name} or null;
14 | }) ./${file} { };
15 | }) entries;
16 | in
17 | # Remove unsupported or broken packages.
18 | filterAttrs
19 | (name: drv: drv ? meta.platforms -> lib.meta.availableOn pkgs.hostPlatform drv)
20 | self
21 |
--------------------------------------------------------------------------------
/pkgs/keystat/default.nix:
--------------------------------------------------------------------------------
1 | { writeTextFile, python3, showmethekey }:
2 | writeTextFile {
3 | name = "keystat";
4 | destination = "/lib/systemd/system/keystat.service";
5 | text = ''
6 | [Unit]
7 | Description=Keyboard statistics
8 |
9 | [Service]
10 | Type=exec
11 | ExecStart=${python3}/bin/python ${./keystat.py} ${showmethekey}/bin/showmethekey-cli
12 | DeviceAllow=char-input rw
13 | StateDirectory=keystat
14 | StateDirectoryMode=0700
15 |
16 | IPAddressDeny=any
17 | LockPersonality=yes
18 | MemoryDenyWriteExecute=yes
19 | NoNewPrivileges=yes
20 | PrivateMounts=yes
21 | ProtectClock=yes
22 | ProtectHostname=yes
23 | RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
24 | RestrictRealtime=yes
25 | RestrictSUIDSGID=yes
26 | SystemCallArchitectures=native
27 | SystemCallErrorNumber=EPERM
28 | SystemCallFilter=@system-service
29 |
30 | [Install]
31 | WantedBy=multi-user.target
32 | '';
33 | }
34 |
--------------------------------------------------------------------------------
/pkgs/keystat/keystat.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | import datetime
3 | import json
4 | import os
5 | import subprocess
6 | import sys
7 |
8 | PERIOD = 256
9 | LOG_FILE = Path(os.environ['STATE_DIRECTORY']) / str(datetime.datetime.now())
10 | KEYLOGGER_PATH = sys.argv[1]
11 |
12 | keyMap = { 'TOTAL': 0 }
13 |
14 | with subprocess.Popen(KEYLOGGER_PATH, text=True, stdout=subprocess.PIPE) as pipe:
15 | for line in pipe.stdout:
16 | record = json.loads(line)
17 | if record['state_name'] != 'PRESSED':
18 | continue
19 | key = f"{record['event_name']}-{record['key_name']}"
20 | keyMap[key] = keyMap.get(key, 0) + 1
21 | keyMap['TOTAL'] += 1
22 |
23 | if keyMap['TOTAL'] % PERIOD == 1:
24 | tmpFile = LOG_FILE.with_suffix('.tmp');
25 | tmpFile.write_text(''.join(f'{k} {n}\n' for k, n in keyMap.items()))
26 | tmpFile.rename(LOG_FILE)
27 |
28 | print('Broken pipe', file=sys.stderr)
29 | exit(1)
30 |
--------------------------------------------------------------------------------
/pkgs/nixos-rebuild-shortcut/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | lib,
3 | stdenv,
4 | runCommand,
5 | runtimeShell,
6 | hostname,
7 | coreutils,
8 | nixos-rebuild-ng,
9 | git,
10 | nix,
11 | nix-output-monitor,
12 | ...
13 | }:
14 | runCommand "nixos-rebuild-shortcut"
15 | {
16 | preferLocalBuild = true;
17 | allowSubstitutes = false;
18 |
19 | inherit runtimeShell;
20 | paths = lib.escapeShellArg (
21 | lib.makeBinPath [
22 | coreutils
23 | git
24 | hostname
25 | nix
26 | nix-output-monitor
27 | nixos-rebuild-ng
28 | ]
29 | );
30 | }
31 | ''
32 | mkdir -p $out/bin
33 | substituteAll ${./nixos.sh} $out/bin/nixos
34 | chmod +x $out/bin/nixos
35 | ${stdenv.shellDryRun} $out/bin/nixos
36 | ''
37 |
--------------------------------------------------------------------------------
/pkgs/nixos-rebuild-shortcut/nixos.sh:
--------------------------------------------------------------------------------
1 | #!@runtimeShell@
2 | set -eo pipefail
3 | export PATH="$PATH${PATH:+:}"@paths@
4 |
5 | localname="$(hostname)"
6 | name="$localname"
7 | action=build
8 | if [[ "${1-}" == @* ]]; then
9 | name="${1:1}"
10 | shift
11 | fi
12 | if [[ "${1-}" = [^-]* ]]; then
13 | action="$1"
14 | shift
15 | fi
16 |
17 | # Simple local build.
18 | if [[ "$action" == build && "$name" == "$localname" ]]; then
19 | set -x
20 | exec nom build .#nixosSystems."$name" "$@" --keep-going
21 | fi
22 |
23 | if [[ "$action" =~ (boot|switch|test) && "$name" == "$localname" && "$(id -u)" != 0 ]]; then
24 | echo "'$action' expects root permission" >&2
25 | exit 1
26 | fi
27 |
28 | cmd=(nixos-rebuild "$action" --flake ".#$name" --keep-going)
29 | if [[ "$name" != "$localname" && "$action" != *build* ]]; then
30 | cmd+=(
31 | --use-remote-sudo
32 | --target-host "$name"
33 | )
34 | fi
35 |
36 | cmd+=("$@")
37 |
38 | echo "+ ${cmd[*]}"
39 | "${cmd[@]}"
40 |
41 | newVer="$(nix eval ".#nixosConfigurations.$name.config.system.build.kernel.version" --raw)"
42 | curVer="$(uname --kernel-release)"
43 | if [[ "$newVer" != "$curVer" ]]; then
44 | echo -e "\e[32;1mnote\e[0m: built kernel $newVer is different than the current $curVer"
45 | fi
46 |
--------------------------------------------------------------------------------
/pkgs/nvfetcher.toml:
--------------------------------------------------------------------------------
1 | [colors]
2 | src.manual = "94d8b2be62657e96488038b0e547e3009ed87d40"
3 | fetch.url = "https://gist.githubusercontent.com/lilydjwg/fdeaf79e921c2f413f44b6f613f6ad53/raw/$ver/colors.py"
4 |
5 | [rime_latex]
6 | src.git = "https://github.com/shenlebantongying/rime_latex"
7 | fetch.github = "shenlebantongying/rime_latex"
8 |
--------------------------------------------------------------------------------
/pkgs/prismlauncher-bwrap.nix:
--------------------------------------------------------------------------------
1 | {
2 | bubblewrap,
3 | jdk17,
4 | jdk21,
5 | jdk8,
6 | kdePackages,
7 | makeWrapper,
8 | prismlauncher,
9 | prismlauncher-unwrapped,
10 | runCommandLocal,
11 | stdenv,
12 |
13 | additionalLibs ? [ ],
14 | additionalPrograms ? [ ],
15 | controllerSupport ? stdenv.hostPlatform.isLinux,
16 | gamemodeSupport ? stdenv.hostPlatform.isLinux,
17 | jdks ? [
18 | jdk21
19 | jdk17
20 | jdk8
21 | ],
22 | msaClientID ? null,
23 | textToSpeechSupport ? stdenv.hostPlatform.isLinux,
24 | }:
25 | let
26 | prismlauncher-unwrapped' = prismlauncher-unwrapped.override {
27 | inherit msaClientID gamemodeSupport;
28 | };
29 |
30 | prismlauncher' = prismlauncher.override {
31 | prismlauncher-unwrapped = prismlauncher-unwrapped';
32 |
33 | inherit
34 | additionalLibs
35 | additionalPrograms
36 | controllerSupport
37 | gamemodeSupport
38 | jdks
39 | msaClientID
40 | textToSpeechSupport
41 | ;
42 | };
43 |
44 | # Passthrough
45 | # Ref: https://github.com/NixOS/nixpkgs/blob/5e871d8aa6f57cc8e0dc087d1c5013f6e212b4ce/pkgs/build-support/build-fhsenv-bubblewrap/default.nix#L170
46 | wrapperPreExec = ''
47 | args=()
48 | if [[ "$DISPLAY" == :* ]]; then
49 | local_socket="/tmp/.X11-unix/X''${DISPLAY#?}"
50 | args+=(--ro-bind-try "$local_socket" "$local_socket")
51 | fi
52 | if [[ -n "$XAUTHORITY" ]]; then
53 | args+=(--ro-bind-try "$XAUTHORITY" "$XAUTHORITY")
54 | fi
55 | if [[ "$WAYLAND_DISPLAY" = /* ]]; then
56 | args+=(--ro-bind-try "$WAYLAND_DISPLAY" "$WAYLAND_DISPLAY")
57 | elif [[ -n "$WAYLAND_DISPLAY" ]]; then
58 | args+=(--ro-bind-try "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" "/tmp/$WAYLAND_DISPLAY")
59 | fi
60 | '';
61 |
62 | bwrapArgs = [
63 | "--unshare-user"
64 | "--unshare-ipc"
65 | "--unshare-pid"
66 | "--unshare-uts"
67 | "--unshare-cgroup"
68 | "--die-with-parent"
69 |
70 | "--dev /dev"
71 | "--proc /proc"
72 | "--ro-bind /nix /nix"
73 | "--ro-bind /etc /etc"
74 | "--ro-bind /var /var" # Required for some symlinks under `/etc`, eg. `/etc/machine-id`.
75 | "--tmpfs /tmp"
76 |
77 | # Network is required.
78 | "--share-net"
79 | "--ro-bind /run/systemd/resolve /run/systemd/resolve"
80 |
81 | # Mesa & OpenGL.
82 | "--ro-bind /run/opengl-driver /run/opengl-driver"
83 | "--dev-bind-try /dev/dri /dev/dri"
84 | "--ro-bind-try /sys/class /sys/class"
85 | "--ro-bind-try /sys/dev/char /sys/dev/char"
86 | "--ro-bind-try /sys/devices/pci0000:00 /sys/devices/pci0000:00"
87 | "--ro-bind-try /sys/devices/system/cpu /sys/devices/system/cpu"
88 |
89 | # Audio.
90 | "--setenv XDG_RUNTIME_DIR /tmp"
91 | ''--ro-bind-try "$XDG_RUNTIME_DIR/pulse" /tmp/pulse''
92 | ''--ro-bind-try "$XDG_RUNTIME_DIR/pipewire-0" /tmp/pipewire-0''
93 |
94 | # Runtime args from `wrapperPreExec`.
95 | ''"''${args[@]}"''
96 |
97 | # Data storage.
98 | ''--bind "''${XDG_DATA_HOME:+$HOME/.local/share}/PrismLauncher" $HOME/.local/share/PrismLauncher''
99 | "--unsetenv XDG_DATA_HOME"
100 |
101 | # Block dangerous D-Bus.
102 | "--unsetenv DBUS_SESSION_BUS_ADDRESS"
103 |
104 | "--"
105 | "${prismlauncher-unwrapped'}/bin/prismlauncher"
106 | ];
107 |
108 | in
109 | runCommandLocal "prismlauncher-bwrap-${prismlauncher-unwrapped'.version}"
110 | {
111 | nativeBuildInputs = [
112 | kdePackages.wrapQtAppsHook
113 |
114 | # Force to use the shell wrapper instead of the binary wrapper. We have scripts.
115 | makeWrapper
116 | ];
117 |
118 | inherit wrapperPreExec bwrapArgs;
119 | inherit (prismlauncher') buildInputs qtWrapperArgs;
120 |
121 | inherit (prismlauncher-unwrapped') meta;
122 | }
123 | ''
124 | qtWrapperArgs+=(--run "$wrapperPreExec" --add-flags "$bwrapArgs")
125 | makeQtWrapper ${bubblewrap}/bin/bwrap $out/bin/prismlauncher
126 | ln -s ${prismlauncher-unwrapped'}/share $out/share
127 | ''
128 |
--------------------------------------------------------------------------------
/pkgs/rime_latex.nix:
--------------------------------------------------------------------------------
1 | { lib, source, runCommand }:
2 | runCommand "rime_latex" {
3 | inherit (source) version src;
4 | meta.license = with lib.licenses; [ gpl3Only ];
5 | } ''
6 | install -Dm444 -t $out/share/rime-data $src/latex.{dict,schema}.yaml
7 | ''
8 |
--------------------------------------------------------------------------------
/pkgs/show-headless-desktop.nix:
--------------------------------------------------------------------------------
1 | { lib, makeDesktopItem, wl-mirror }:
2 | makeDesktopItem {
3 | name = "show-headless1";
4 | desktopName = "Show Headless Output 1";
5 | comment = "Show content of headless output HEADLESS-1";
6 | exec = "${lib.getBin wl-mirror}/bin/wl-mirror HEADLESS-1";
7 | categories = [ "Utility" ];
8 | }
9 |
--------------------------------------------------------------------------------
/pkgs/systemd-run-app.nix:
--------------------------------------------------------------------------------
1 | # From https://github.com/NickCao/flakes/blob/67fac11e53d6ee0ff27a90fcaf9cab2e59a935a6/pkgs/systemd-run-app/default.nix
2 | { writeShellApplication, coreutils }:
3 | writeShellApplication {
4 | name = "systemd-run-app";
5 | text = ''
6 | name="$(/run/current-system/systemd/bin/systemd-escape "$(${coreutils}/bin/basename "$1")")"
7 | unit="app-$name-$(printf %04x $RANDOM)"
8 | exec /run/current-system/systemd/bin/systemd-run \
9 | --user \
10 | --scope \
11 | --unit="$unit" \
12 | --slice=app \
13 | --same-dir \
14 | --collect \
15 | --property PartOf=graphical-session.target \
16 | --property After=graphical-session.target \
17 | -- \
18 | /run/current-system/systemd/bin/systemd-cat \
19 | --identifier="$unit" \
20 | -- \
21 | "$@"
22 | '';
23 | }
24 |
--------------------------------------------------------------------------------
/pkgs/urw-base35-fonts.nix:
--------------------------------------------------------------------------------
1 | { lib, stdenvNoCC, fetchFromGitHub }:
2 |
3 | stdenvNoCC.mkDerivation {
4 | pname = "urw-base35-fonts";
5 | version = "2020-09-10";
6 |
7 | src = fetchFromGitHub {
8 | owner = "ArtifexSoftware";
9 | repo = "urw-base35-fonts";
10 | rev = "20200910";
11 | hash = "sha256-YQl5IDtodcbTV3D6vtJi7CwxVtHHl58fG6qCAoSaP4U=";
12 | };
13 |
14 | installPhase = ''
15 | runHook preInstall
16 | install -Dm644 -t $out/share/fonts/urw-base35-fonts fonts/*.{afm,otf,t1,ttf}
17 | runHook postInstall
18 | '';
19 |
20 | meta = with lib; {
21 | description = "URW++ base 35 font set";
22 | homepage = "https://github.com/ArtifexSoftware/urw-base35-fonts";
23 | license = licenses.agpl3Only;
24 | maintainers = [ ];
25 | platforms = platforms.all;
26 | };
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/pkgs/wallpaper-blur.nix:
--------------------------------------------------------------------------------
1 | { runCommand, wallpaper, imagemagick }:
2 | runCommand "wallpaper-blur.jpg" { } ''
3 | ${imagemagick}/bin/convert -blur 14x5 ${wallpaper} $out
4 | ''
5 |
--------------------------------------------------------------------------------
/pkgs/wallpaper.nix:
--------------------------------------------------------------------------------
1 | { fetchurl }:
2 | fetchurl {
3 | name = "wallpaper.jpg";
4 | url = "https://pbs.twimg.com/media/E9irhxhVUAUaBCr?format=jpg";
5 | hash = "sha256-Rhjj1K0FXKGzKswoLj1H0Yi/QHswzPcGW6aLMiekURA=";
6 | }
7 |
--------------------------------------------------------------------------------
/pkgs/zsh-comma.nix:
--------------------------------------------------------------------------------
1 | # Ref: https://github.com/dramforever/config/blob/4ffe106a05cf38b5f776e0b7421efef0cdb80816/home/nixenv.zsh
2 | { lib, runCommandLocal, nix }:
3 | runCommandLocal "zsh-comma" {
4 | plugin = ''
5 | typeset -g -a comma_paths
6 |
7 | ,() {
8 | setopt local_options err_return pipefail
9 | if [[ $# = 0 ]]; then
10 | printf "%s\n" $comma_paths
11 | return
12 | fi
13 | local -a ps
14 | ps=( $(nix build --json --no-link $@ | jq -r '.[].outputs[]') )
15 | ps=($^ps/bin)
16 | comma_paths+=($ps)
17 | path=($ps $path)
18 | export PATH
19 | printf "+%s paths, total %s paths\n" ''${#ps} ''${#comma_paths}
20 | }
21 |
22 | ,,() {
23 | path=(''${path:|comma_paths})
24 | comma_paths=()
25 | export PATH
26 | }
27 | '';
28 |
29 | completion = ''
30 | #compdef ,
31 | _,() {
32 | words[1]=(nix build)
33 | CURRENT+=1
34 | _nix
35 | }
36 | '';
37 |
38 | propagatedBuildInputs = [ nix.out ]; # Completion.
39 |
40 | meta.license = lib.licenses.mit;
41 |
42 | } ''
43 | mkdir -p $out/share/zsh/{comma,site-functions}
44 | cat <<<"$plugin" >$out/share/zsh/comma/comma.zsh
45 | cat <<<"$completion" >$out/share/zsh/site-functions/_,
46 | ''
47 |
--------------------------------------------------------------------------------
/secrets/ssh.yaml:
--------------------------------------------------------------------------------
1 | ssh-hosts: ENC[AES256_GCM,data:RvwsG6aIJOfNKc66vU6d++WySVOdWiK0dC9XLCNJQPoAq9rHJZSv5KV6efVOojoIDtL58tLgwEoV8xSRmgaHccHC8hnSZH3gJJeHmVx6rMGBHx/GR7ExkbXOShgxWagC92wHz2t0KHJFOFHgyWOGKKHcdJHMBCCzAyCQMuhxWl/hjejVcNRP5BY/mrbNVkUBpOuQ7p/d5lx38f8WRvAnxFY8Dmy5B0j6jsql1p9adk4xPoN0hFIgYRGXMACfpfa4DZvDHP4yq48WY1qSek3vkJ76VOwoMRbNucnuIgKz1rAY2hgff8VS5mCV7+2aWwUy093sCPEwK4tWqzz1ZeVmlpJNpQi1kV1u5cRNopjQi+oyii3ImhkPBjMgV5a21wUYvXD/1x9za1OZ+zCl+u3PnzsTDa/zA58OpxM7d8a4rd8BobKDCvx8Q7PZmDBR95Le2T9ZcP5IS8lxkBUmzdIJeROfDXh6N1MiMCC0rZTj/mqkJekxhvoUu7nc1CDyGngdcHAkOklU/Yi3SV0RJVvVYKuezRNx2C2b1l2GMSZ2QjqBXY4ElBiLVOw7yQxzqgxcot7zDjBS3jsP+2y6N3qOA0A+Rp8K7v5cTIGO6EvwHODOBildpgNA9F0CCG1scodc/7cF2DArxKjNRbxgUFDfedcCYhKsfFu8SZzvIUWfST5P5hJcVIi5DwfeaXzbBWConRnufv+hALpXtyTRjD0oe8VAzrQY1ZenPkhczkoFaT2KLjKskWAd2/g3JlscRTOXavVQMKhG/nVn3zcIWx99YcfYb65no/WF98Id7FmPVPXHX+Z5KfCdY8oenSP3U+plRQ==,iv:uXOtFKLAaI4JP2DO4y04ZQeCjXWPAq7EN3YPuTKigPo=,tag:4UqFDDuX1xV2yFbmTf9PNA==,type:str]
2 | sops:
3 | kms: []
4 | gcp_kms: []
5 | azure_kv: []
6 | hc_vault: []
7 | age:
8 | - recipient: age157zcs4687hmsd834xhvt66apf6v93ss3tt2l23x72lhtvpl69ggqeejgky
9 | enc: |
10 | -----BEGIN AGE ENCRYPTED FILE-----
11 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHd2dyOUQyU1NwOXY2ZXJJ
12 | WlNUTkNYUE9oWE1nUFhVNlUxMWRkbW10ZENvCnhpb1pHVkVrY1hGYVo0UWhLU2hV
13 | OEZ1OElWeWFsYzRzLzFqMld2cXNkV2sKLS0tIFZJbFZjcEVab1ZrNTNwQ21rNVFw
14 | dXVaMVdxN2s2dENPNWt1b1cydmdvVjQKfoRukSwy28LjPmUvWY40j8ltljGdsixU
15 | OkMe+8dGvfpzbWkbiR9FsEJCKRFtNm9dW73XZ3SPhDga3FiVWobfPQ==
16 | -----END AGE ENCRYPTED FILE-----
17 | - recipient: age1l9qly5vlx20uzrqvq8qygvcrtff64mgvqchet5uvs989upy5lugq4krj2c
18 | enc: |
19 | -----BEGIN AGE ENCRYPTED FILE-----
20 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkRk9LTDRKNmVEdVFuZHVn
21 | UTFvVW52ZkIwN3UxcUk2L1JsdEc3elpUeWljCjI1OVg3N3paSnVFSFZoOEI5STN3
22 | RW9kWU5kQXR6SGVYYllIQ1d3SEJRK3MKLS0tIEVyZkFGdmhaYjFPeDlCalFUOUFn
23 | TVd5dC9ienVsNWJwOUc0OUlCVnBYWU0KcP1Z09UvH4LsuB/+M3WGfl+Bn2cm0BKy
24 | l5DfKDCZP7g9W28ccTGBu/NqpfGpzI4H6uJpupjwMEQLi6onxOzAiQ==
25 | -----END AGE ENCRYPTED FILE-----
26 | - recipient: age14z6h0yqmuymga4kxtvc78tmpyjdt7vh72c6awml2dfxjzxch5cqqt374sn
27 | enc: |
28 | -----BEGIN AGE ENCRYPTED FILE-----
29 | YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0d2x0M2luMUpNVUNlbWVC
30 | aWZDT2dHaTBXWEJSV2JLa1QwcUQxd3BBUWxVClcwajdhbVRJdER0WC9IcDVCbHlN
31 | K2JTRzlGaU0zUkZNYmk3Y3hhTEc5Y1UKLS0tIFN6NjdXQXJIYUlIckRrazllZUY0
32 | eFJEZ0JtMVljRy9vU1VMUXBpbEt2QUUK8eF/kdt3EHkkj7y0BVM7NnEg0dpQAzS4
33 | SOFmkuuC5wsbHpxTmcPII2g+6Yq1FB3W3Tto4BP+Xra4MJB8Q+dp+w==
34 | -----END AGE ENCRYPTED FILE-----
35 | lastmodified: "2021-12-20T17:59:16Z"
36 | mac: ENC[AES256_GCM,data:66Iv2AlokQTFMI0kTOMibfu61jnKQCkYXwaLKG2tjFlKBOhcFeb+Va7mZ0P3wV1JVZd7hBrzwcM81usaCLWff8MYFoOoW4oNOdtoWegsSK1hqlYvxSHDykGmj/XkoclIAFzDb+KC2qUdg2mGo5wwPT42h6g5d4e38KPUg9U7U+s=,iv:nff2BDRG0s4A49xePWupRzO6EQCSREP+Xmc6KHHMsjA=,tag:8s3f4sueC9gPhMW36YinpQ==,type:str]
37 | pgp:
38 | - created_at: "2023-04-02T15:38:38Z"
39 | enc: |-
40 | -----BEGIN PGP MESSAGE-----
41 |
42 | wV4Dhs332B8tbXUSAQdAKqs40mpEe/m/QN/igGHey4oKTxDx+NCm45X+dsGVgzsw
43 | ZKSoLKtXZEoWYxs3RyRXQyE8YjJHeUbhLa6VXsyPWtxhxuZKHuCKYVEg/JCNA6Zh
44 | 0lEB2KseM2PqnrSzT4lA43XtRpdNasSU4xn1CRW3+w+VmX6b48qe41zvF10V0Xve
45 | J8A3WaPh65jox7sDqbbo1n+S+LdyYCubNCCoYbJ7kCgiKsI=
46 | =Mj0K
47 | -----END PGP MESSAGE-----
48 | fp: F90FFD6D585C2BA1F13DE8A97571654CF88E31C2
49 | unencrypted_suffix: _unencrypted
50 | version: 3.7.1
51 |
--------------------------------------------------------------------------------
/templates/ci-rust/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | pull_request:
4 | push:
5 | schedule:
6 | - cron: '42 1 * * *' # *-*-* 01:42:00 UTC
7 |
8 | permissions:
9 | contents: read
10 |
11 | env:
12 | RUST_BACKTRACE: full
13 | RUSTFLAGS: -Dwarnings
14 |
15 | jobs:
16 | test:
17 | timeout-minutes: 45
18 | strategy:
19 | fail-fast: false
20 | matrix:
21 | rust: [nightly, beta, stable]
22 | os: [ubuntu-latest, macos-latest, windows-latest]
23 | name: Test ${{matrix.rust}} on ${{ matrix.os }}
24 | runs-on: ${{ matrix.os }}
25 | steps:
26 | - name: Checkout
27 | uses: actions/checkout@v3
28 | - name: Install Rust
29 | uses: dtolnay/rust-toolchain@master
30 | with:
31 | toolchain: ${{ matrix.rust }}
32 | - name: Build
33 | run: cargo build --all-targets
34 | - name: Test
35 | run: cargo test
36 |
37 | clippy:
38 | name: Clippy
39 | runs-on: ubuntu-latest
40 | timeout-minutes: 45
41 | steps:
42 | - name: Checkout
43 | uses: actions/checkout@v3
44 | - name: Install Clippy
45 | uses: dtolnay/rust-toolchain@clippy
46 | - name: Clippy
47 | run: cargo clippy --all-targets
48 |
--------------------------------------------------------------------------------
/templates/ci-rust/.github/workflows/future_proof.yaml:
--------------------------------------------------------------------------------
1 | name: Future proof tests
2 | on:
3 | schedule:
4 | - cron: '42 1 * * 0' # Sun *-*-* 01:42:00 UTC
5 |
6 | permissions:
7 | contents: read
8 |
9 | env:
10 | RUST_BACKTRACE: full
11 |
12 | jobs:
13 | outdated:
14 | name: Outdated
15 | runs-on: ubuntu-latest
16 | steps:
17 | - name: Checkout
18 | uses: actions/checkout@v3
19 | - name: Install cargo-outdated
20 | uses: dtolnay/install@cargo-outdated
21 | - name: cargo-outdated
22 | run: |
23 | rm -f Cargo.lock # Ignore trivially updatable compatible versions.
24 | cargo outdated --workspace --exit-code 1
25 |
--------------------------------------------------------------------------------
/templates/rust-bin/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | result
3 | result-*
4 | Cargo.lock
5 |
--------------------------------------------------------------------------------
/templates/rust-bin/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "___"
3 | version = "0.0.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 |
--------------------------------------------------------------------------------
/templates/rust-bin/src/main.rs:
--------------------------------------------------------------------------------
1 | fn main() {}
2 |
--------------------------------------------------------------------------------
/templates/rust-criterion/benches/foo.rs:
--------------------------------------------------------------------------------
1 | use criterion::{black_box, criterion_group, criterion_main, Criterion};
2 |
3 | fn foo(c: &mut Criterion) {
4 | c.bench_function("foo", |b| {
5 | let init = 42;
6 | b.iter(|| black_box(init) * 42);
7 | });
8 | }
9 |
10 | criterion_group!(benches, foo);
11 | criterion_main!(benches);
12 |
--------------------------------------------------------------------------------
/templates/rust-lib/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | result
3 | result-*
4 |
--------------------------------------------------------------------------------
/templates/rust-lib/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "___"
3 | version = "0.0.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 |
--------------------------------------------------------------------------------
/templates/rust-lib/src/lib.rs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oxalica/nixos-config/afdeef03a861eb98c1cbf18fd471967a6884f631/templates/rust-lib/src/lib.rs
--------------------------------------------------------------------------------
/typos.toml:
--------------------------------------------------------------------------------
1 | [files]
2 | extend-exclude = [
3 | "home/modules/nvim/vimrc.vim",
4 | "my/gpg-pubkey.asc",
5 | "secrets",
6 | ]
7 |
8 | [default.extend-words]
9 | lazer = "lazer" # osu-lazer
10 | thumbnailers = "thumbnailers" # kdegraphics-thumbnailers
11 |
--------------------------------------------------------------------------------