Kieran's opinionated (and probably slightly dumb) nix config
1# Kieran's Dots
2
3
4
5> [!CAUTION]
6> These dots are highly prone to change / breakage.
7>
8> ~~I am not a nix os expert (this is my first time touching nix), so I'm not sure if this will work or not. I'm just trying to get my dots up on github.~~
9>
10> After `591` days of these dots being in constant operation, many many rebuilds, and `776` commits these dots have been rock solid and I have no complaints.
11
12## The layout
13
14```
15~/dots
16├── .github/workflows # CI/CD (deploy-rs + per-service reusable workflow)
17├── dots # config files symlinked by home-manager
18│ └── wallpapers
19├── machines
20│ ├── atalanta # macOS M4 (nix-darwin)
21│ ├── ember # dell r210 server (basement)
22│ ├── moonlark # framework 13 (dead)
23│ ├── nest # shared tilde server (home-manager only)
24│ ├── prattle # oracle cloud x86_64
25│ ├── tacyon # rpi 5
26│ └── terebithia # oracle cloud aarch64 (main server)
27├── modules
28│ ├── lib
29│ │ └── mkService.nix # service factory (see Deployment section)
30│ ├── home # home-manager modules
31│ │ ├── aesthetics # theming and wallpapers
32│ │ ├── apps # app configs (ghostty, helix, git, ssh, etc.)
33│ │ ├── system # shell, environment
34│ │ └── wm/hyprland
35│ └── nixos # nixos modules
36│ ├── apps # system-level app configs
37│ ├── services # self-hosted services (mkService-based + custom)
38│ │ ├── restic # backup system with CLI
39│ │ └── bore # tunnel proxy
40│ └── system # pam, wifi
41├── packages # custom nix packages
42└── secrets # agenix-encrypted secrets
43```
44
45## Installation
46
47> [!WARNING]
48> Also to note that this configuration will **not** work if you do not change any of the [secrets](./secrets) since they are encrypted.
49
50You could install a NixOS machine, use the home-manager instructions, or use nix-darwin for macOS.
51
52### macOS with nix-darwin
53
54For macOS machines, you can use nix-darwin:
55
561. Install Nix using the determinate systems installer:
57
58```bash
59curl -fsSL https://install.determinate.systems/nix | sh -s -- install
60```
61
622. Clone the repository:
63
64```bash
65git clone git@github.com:taciturnaxolotl/dots.git
66cd dots
67```
68
693. Apply the configuration:
70
71```bash
72darwin-rebuild switch --flake .#atalanta
73```
74
75### Home Manager
76
77Install nix via the determinate systems installer
78
79```bash
80curl -fsSL https://install.determinate.systems/nix | sh -s -- install --determinate
81```
82
83then copy ssh keys and chmod them
84
85```bash
86scp .ssh/id_rsa* nest:/home/kierank/.ssh/
87ssh nest chmod 600 ~/.ssh/id_rsa*
88```
89
90and then clone the repo
91
92```bash
93git clone git@github.com:taciturnaxolotl/dots.git
94cd dots
95```
96
97and execute the machine profile
98
99```bash
100nix-shell -p home-manager
101home-manager switch --flake .#nest
102```
103
104setup atuin and import previous shell history
105
106```bash
107atuin login
108atuin import
109```
110
111### NixOS
112
113> These instructions have been validated by installing on my friend's machine ([`Nat2-Dev/dots`](https://github.com/Nat2-Dev/dots))
114
115#### Using nixos-anywhere (Recommended for remote installations)
116
117> [!WARNING]
118> This only currently works with `prattle` and `terebithia` as they have the proper disko configs setup.
119
120For remote installations (like Oracle Cloud), use [nixos-anywhere](https://github.com/nix-community/nixos-anywhere):
121
122```bash
123nix run github:nix-community/nixos-anywhere -- \
124 --flake .#prattle \
125 --generate-hardware-config nixos-facter ./machines/prattle/facter.json \
126 --build-on-remote \
127 root@<ip-address>
128```
129
130Replace `prattle` with your machine configuration and `<ip-address>` with your target machine's IP.
131
132> [!NOTE]
133> Make sure your SSH key is in the target machine's `authorized_keys` and the machine configuration has the correct network settings. The `--generate-hardware-config nixos-facter` flag will generate a comprehensive hardware report using [nixos-facter](https://github.com/numtide/nixos-facter) instead of the traditional `nixos-generate-config`.
134
135#### Using the install script
136
137```bash
138curl -L https://raw.githubusercontent.com/taciturnaxolotl/dots/main/install.sh -o install.sh
139chmod +x install.sh
140./install.sh
141```
142
143#### Post-install
144
145After first boot, log in with user `kierank` and the default password, then change it immediately:
146
147```bash
148passwd kierank
149```
150
151Move the config to your home directory and symlink:
152
153```bash
154sudo mv /etc/nixos ~/dots
155sudo ln -s ~/dots /etc/nixos
156sudo chown -R $(id -un):users ~/dots
157```
158
159Set up [atuin](https://atuin.sh/) for shell history sync:
160
161```bash
162atuin login
163atuin sync
164```
165
166## Deployment
167
168Two deploy paths: **infrastructure** (NixOS config changes in this repo) and **application code** (per-service repos).
169
170### Infrastructure
171
172Pushing to `main` here triggers `.github/workflows/deploy.yaml` which runs `deploy-rs` over Tailscale to rebuild NixOS on the target machine.
173
174```sh
175# manual deploy
176nix run 'github:serokell/deploy-rs' -- --remote-build --ssh-user kierank .
177```
178
179### Application code
180
181Each service repo has a minimal workflow calling the reusable `.github/workflows/deploy-service.yml`. On push to `main`:
182
1831. Connects to Tailscale (`tag:deploy`)
1842. SSHes as the **service user** (e.g., `cachet@terebithia`) via Tailscale SSH
1853. Snapshots the SQLite DB (if `db_path` is provided)
1864. `git pull` + `bun install --frozen-lockfile` + `sudo systemctl restart`
1875. Health check (HTTP URL or systemd status fallback)
1886. Auto-rollback on failure (restores DB snapshot + reverts to previous commit)
189
190Per-app workflow — copy and change the `with:` values:
191
192```yaml
193name: Deploy
194on:
195 push:
196 branches: [main]
197 workflow_dispatch:
198jobs:
199 deploy:
200 uses: taciturnaxolotl/dots/.github/workflows/deploy-service.yml@main
201 with:
202 service: cachet
203 health_url: https://cachet.dunkirk.sh/health
204 db_path: /var/lib/cachet/data/cachet.db
205 secrets:
206 TS_OAUTH_CLIENT_ID: ${{ secrets.TS_OAUTH_CLIENT_ID }}
207 TS_OAUTH_SECRET: ${{ secrets.TS_OAUTH_SECRET }}
208```
209
210Omit `health_url` to fall back to `systemctl is-active`. Omit `db_path` for stateless services.
211
212### mkService
213
214`modules/lib/mkService.nix` standardizes service modules. A call to `mkService { ... }` provides:
215
216- Systemd service with initial git clone (subsequent deploys via GitHub Actions)
217- Caddy reverse proxy with TLS via Cloudflare DNS and optional rate limiting
218- Data declarations (`sqlite`, `postgres`, `files`) that feed into automatic backups
219- Dedicated system user with sudo for restart/stop/start (enables per-user Tailscale ACLs)
220- Port conflict detection, security hardening, agenix secrets
221
222Adding a new service: create a module in `modules/nixos/services/`, enable it in `machines/terebithia/default.nix`, and add a deploy workflow to the app repo. See `modules/nixos/services/cachet.nix` for a minimal example.
223
224### Secrets (agenix)
225
226Secrets are encrypted in `secrets/*.age` and declared in `secrets/secrets.nix`. Referenced as `config.age.secrets.<name>.path` — decrypted at activation time to `/run/agenix/`.
227
228```sh
229cd secrets && agenix -e myapp.age # create/edit a secret
230```
231
232## Backups
233
234Services are automatically backed up nightly using restic to Backblaze B2. Backup targets are auto-discovered from `data.sqlite`/`data.postgres`/`data.files` declarations in mkService modules.
235
236The `atelier-backup` CLI provides an interactive TUI for managing backups:
237
238```bash
239sudo atelier-backup # Interactive menu
240sudo atelier-backup status # Show backup status
241sudo atelier-backup restore # Restore wizard
242sudo atelier-backup dr # Disaster recovery
243```
244
245See [modules/nixos/services/restic/README.md](modules/nixos/services/restic/README.md) for setup and usage.
246
247## some odd things
248
249for helix if you want the grammar to work you must run the following as per [this helix discussion](https://github.com/helix-editor/helix/discussions/10035#discussioncomment-13852637)
250
251```bash
252hx -g fetch
253hx -g build
254```
255
256## Screenshots
257
258<details>
259 <summary>I've stuck the rest of the screenshots in a spoiler to preserve space</summary>
260<br/>
261
262**Last updated: 2024-12-27**
263
264
265
266
267
268
269
270
271</details>
272
273## Credits
274
275Thanks a bunch to the following people for their dots, configs, and general inspiration which i've shamelessly stolen from:
276
277- [NixOS/nixos-hardware](https://github.com/NixOS/nixos-hardware)
278- [hyprland-community/hyprnix](https://github.com/hyprland-community/hyprnix)
279- [spikespaz/dotfiles](https://github.com/spikespaz/dotfiles)
280- [Misterio77/nix-starter-configs](https://github.com/Misterio77/nix-starter-configs)
281- [mccd.space install guide](https://mccd.space/posts/git-to-deploy/)
282- [disco docs](https://github.com/nix-community/disko/blob/master/docs/quickstart.md)
283- [XDG_CONFIG_HOME setting](https://github.com/NixOS/nixpkgs/issues/224525)
284- [Daru-san/spicetify-nix](https://github.com/Daru-san/spicetify-nix)
285- [agenix](https://nixos.wiki/wiki/Agenix)
286- [wpa_supplicant env file docs](https://search.nixos.org/options?show=networking.wireless.environmentFile&from=0&size=50&sort=relevance&type=packages&query=networking.wireless)
287- [escaping nix variables](https://www.reddit.com/r/NixOS/comments/jmlohf/escaping_interpolation_in_bash_string/)
288- [nerd fonts cheat sheet](https://www.nerdfonts.com/cheat-sheet)
289- [setting the default shell in nix](https://www.reddit.com/r/NixOS/comments/z16mt8/cant_seem_to_set_default_shell_using_homemanager/)
290- [hyprwm/contrib](https://github.com/hyprwm/contrib)
291- [gtk with home manager](https://hoverbear.org/blog/declarative-gnome-configuration-in-nixos/)
292- [setting up the proper portals](https://github.com/NixOS/nixpkgs/issues/274554)
293- [tuigreet setup](https://github.com/sjcobb2022/nixos-config/blob/29077cee1fc82c5296908f0594e28276dacbe0b0/hosts/common/optional/greetd.nix)
294
295## 📜 License
296
297The code is licensed under `MIT`! That means MIT allows for free use, modification, and distribution of the software, requiring only that the original copyright notice and disclaimer are included in copies. All artwork and images are copyright reserved but may be used with proper attribution to the authors.
298
299<p align="center">
300 <img src="https://raw.githubusercontent.com/taciturnaxolotl/carriage/master/.github/images/line-break.svg" />
301</p>
302
303<p align="center">
304 <i><code>© 2025-present <a href="https://github.com/taciturnaxolotl">Kieran Klukas</a></code></i>
305</p>
306
307<p align="center">
308 <a href="https://infra.dunkirk.sh"><img src="https://infra.dunkirk.sh/badge?style=for-the-badge&colorA=363a4f&colorB=b7bdf8"/></a>
309 <a href="https://github.com/taciturnaxolotl/dots/blob/master/LICENSE.md"><img src="https://img.shields.io/static/v1.svg?style=for-the-badge&label=License&message=MIT&logoColor=d9e0ee&colorA=363a4f&colorB=b7bdf8"/></a>
310</p>