aboutsummaryrefslogtreecommitdiff
path: root/content/posts/2025-10.18-local-setup.md
blob: dae4761ffe25d22df85ce8935d50a4caf5acd1aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
---
layout: post
title: "Notes on getting my local setup up to speed"
date: 2025-10-18
lastmod: 2025-10-18
tags: ['alpine', 'nix']
---

Before we get to the actual setup, I'll first share some background on how I
arrived at the solution I'm currently using. If you want to go to the actual
steps jump to [provisioning](#provisioning).

# Git

One of the many chores in my day to day digital life is keeping the
configurations between my home and work machines synced and tidy. I tried
chezmoi[^1] at some point but it didn't stick (I don't recall why as it was many
years ago). After some trial and error I have settled on using simple git
repository in my home folder which I used for many years. The setup would be
like:

```bash
cd $HOME
git init
echo "*" > .gitignore
```

And for every new file I wanted to keep track I'd add it  by `git add -f <FILE>`
and once I'm on a new computer I'd git clone the repository on home folder to
get configuration in their correct place.

That repository contains all my essential configuration; shell files (.profile,
fish configuration), applications (waybar, git, niri), my email configuration
(aerc, maildir, notmuch), and yes, some of those have secrets stored in plain
text (in a private repository, of course 😅).

However that approach has some shortcomings when the configuration between
computers differ. For example I can't simply commit my mail connection
configuration (`aerc/accounts.conf`) since I have one for work with corporate
email and one on my home machine with my private email as they would conflict.

# Nix to rescue

Now it comes Nix to the rescue! Or more specifically home-manger[^2].

It all started at work where we had expanded our nix usage as a way to share
resource between repositories (e.g.: linter configuration, required binaries to
run tests). This daily exposure helped me to better understand its capabilities
and it gradually started to grow with me.

So naturally I have gravitated toward home-manger as way to have a global
configuration for nix without having to use nixos, and the more I learned the
more I saw the potential to use as my local configuration. After a couple of
months gradually migrating my setup, I've now moved everything over to
home-manager.

Besides just dotfiles managing home-mamager allows me to supplement my setup
with binaries that are not available on latest alpine. So lets share some
details how I'm setting up home manger. Here[^7] is my full configuration
repository for reference which runs on flake mode[^8]. I won't go into every
details of all those files. You're better off following a dedicated guide on nix
for that, but I'll share some key points.

Looking at `flake.nix` we have two hostnames/profiles; home and work.

```nix
    "gabrielgio@workstation.lan" = home-manager.lib.homeManagerConfiguration {
        inherit pkgs;

        extraSpecialArgs = {
          inherit inputs;
          git = {
            name = "Gabriel A. Giovanini";
            email = "g.arakakigiovanini@gridx.de";
          };
        };

        modules = [
          ./home.nix
          ./secrets/gridx/gridx.nix
        ];
      };
      "gabrielgio@homestation.lan" = home-manager.lib.homeManagerConfiguration {
        inherit pkgs;

        extraSpecialArgs = {
          inherit inputs;
          git = {
            name = "Gabriel A. Giovanini";
            email = "mail@gabrielgio.me";
          };
        };

        modules = [
          ./home.nix
        ];
      };
```

Both inherit the base packages and share the same core configuration on
`home.nix`, which contains shared dotfiles and packages. While you won't be able
to see the contents for obvious reasons, this file includes work related tools,
terraform linter, awscli2, internal tooling and much more.

Now that extra git configuration is used to configure the proper git
configuration for each profiles. That later[^9] is used to set the jj config
files with the correct values.

```nix
{
  pkgs,
  inputs,
  git,
  ...
}: let
  tomlFormat = pkgs.formats.toml {};
in {
  xdg.configFile."jj/config.toml".source = tomlFormat.generate "config.toml" {
    user = {
      name = git.name;
      email = git.email;
    };
    ...
}
```

### Git crypt

I use git-crypt[^10] to be able so share secrets between machines and still be
able to publicly share most of my configuration.

## Why not nix-os?

Pretty much because I like alpine. It is a simple, small and because of that,
the entire distro fits on my head[^4]. APK is straightforward to understand and
build yourself[^3]. OpenRC follows a simple model that's easy to make sense of
and dead simple to configure. I run it as my home and work computer as well as
my server (even running on diskless mode). It gets out of my way, and I haven't
seen any major issues even on major upgrades. 

Also there's something about having 12 version of glibc installed that just does
not sit well with me. (some could argue I have felt for the sunk cost fallacy
but I will deny it!)

# Provisioning {#provisioning}

I have recently formatted my home computer and as always I forgot to take notes
so as ~~punishiment~~ exercise, I'll setup a VM from scratch to validate all
the steps are correct. In the end it should be a couple steps only.

Similar to my other post[^5] we will be using qemu. First create the disk:

```bash
qemu-img create -f qcow2 var.cow2 30G
```

Later go to alpine and download the latest image for virtual[^6].

Now we can start VM with:

```bash
qemu-system-x86_64 \
    -machine accel=kvm \
    -display gtk \
    -smp $(nproc) \
    -m 2048 \
    -cdrom alpine-virt-3.22.2-x86_64.iso \
    -drive file=var.cow2,if=virtio
```

Now run the classic `setup-alpine` then reboot and run `setup-desktop sway` and
`setup-devd udev`.

## Niri for 3.22 and bonus building APKBUILD

Now there is niri. On alpine it is already on community folder but it is not
available on 3.22. This means I need to setup APK building to build that
package. This approach is actually easier than build from source code directly,
since APKBUILD takes care of all development dependencies.

```bash
# make sure you have community repository enabled on /etc/apk/repositories
doas apk add git alpine-sdk
addgroup <USER> abuild # might need to re-login or run: su <USER>
abuild-keygen -a -i
git clone --depth 1 https://gitlab.alpinelinux.org/alpine/aports.git
cd aports/community/niri
abuild -r
```

Depending on your system configuration it will take some time to build but at
the end there will be a new folder `$HOME/packages` which contains the result of
the build. Add it to your `/etc/apk/repositories`.

```bash
echo "/home/<USER>/packages/community" >> /etc/apk/repositories
apk add -U niri
```


To continue, here are the basic packages I typically install. I maintain a
shared list of common packages that can all be installed with a single command:

```bash
curl https://artifacts.gabrielgio.me/world | xargs -I{} apk add {}
```

## Getting home-manager off the ground

Before we do anything with nix make sure you have `nix-daemon` running and your
user added to `/etc/nix/nix.conf`

```bash
allowed-users = @nix <USERNAME>
build-users-group = nixbld
max-jobs = <CPU_COUNT>
extra-nix-path = nixpkgs=flake:nixpkgs
experimental-features = nix-command flakes
```

Then:

```bash
rc-service nix-daemon restart
```

Clone home-manager repository:

```bash
cd .config
git clone https://git.gabrielgio.me/home-manager
```

Now run the shell with nh utility inside of the cloned folder:

```bash
nix shell nixpkgs#nh
# inside of the shell run:
nh home switch .
```

Now on the home folder we should see .profile linked `ls -lha $HOME`. Once here
exit tty1 and log in again and you should see niri. After that I have to add ssh
and pgp keys and I'm set.

[^1]: https://github.com/twpayne/chezmoi
[^2]: https://github.com/nix-community/home-manager
[^3]: https://apkdoc.gabrielgio.me/
[^4]: https://drewdevault.com/2021/05/06/Praise-for-Alpine-Linux.html
[^5]: https://gabrielgio.me/posts/2023-04-30-using-data-mode-alpine/
[^6]: https://alpinelinux.org/downloads/
[^7]: https://git.gabrielgio.me/home-manager/tree/
[^8]: https://nix-community.github.io/home-manager/index.xhtml#ch-nix-flakes
[^9]: https://git.gabrielgio.me/home-manager/tree/jj.nix
[^10]: https://github.com/AGWA/git-crypt