--- 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 ` 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 abuild # might need to re-login or run: su 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//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 build-users-group = nixbld max-jobs = 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