I’ve been using NixOS since October 2025. I’ll be honest: I’m still very much a beginner, so if you see me doing something “the wrong way,” I am more than happy to be corrected! To keep my head above water, I’ve been living by the NixOS & Flakes Book.
The Config Migration
At first, I kept my NixOS config in the standard /etc/nixos/ directory. But as a developer, I wanted to keep it in a GitHub repository, and managing a Git repo inside /etc is… a bit of a headache.
After some YouTube rabbit holes, I learned the secret: you can put your config anywhere as long as you use the right command. I moved everything to my neko-dotfiles repository. Now, I run my updates like this:
sudo nixos-rebuild switch --flake .#neko-desktop --show-trace
Where does neko-desktop come from?
For a while, I thought this command was just looking at the hostname I set in my configuration.nix. While I do have networking.hostName = "neko-desktop"; defined there, the #neko-desktop in the command actually refers to the output name defined in my flake.nix.
Looking at my flake.nix, you can see how this is structured:
outputs = { nixpkgs, home-manager, agenix, ... }@inputs:
let
system = "x86_64-linux";
in
{
nixosConfigurations = {
# This is what the '#' in the command refers to!
neko-desktop = nixpkgs.lib.nixosSystem {
modules = [
./hosts/desktop/configuration.nix
home-manager.nixosModules.home-manager
# ... other modules
];
};
# laptop
# TODO
neko-laptop = nixpkgs.lib.nixosSystem {
modules = [ ./hosts/laptop/configuration.nix ];
};
};
};
The name you choose there is what nixos-rebuild looks for. It’s small but important distinction when you start managing multiple machines (like a desktop and a laptop) from the same flake!
The 2GB RAM Struggle: NixOS vs. My Laptop
You might notice a # TODO in my laptop configuration. Here’s the reality: my laptop only has 2GB of RAM.
In my experience, NixOS really needs about 4GB of RAM to rebuild successfully, especially when evaluating complex flakes and Home Manager modules. Whenever I try to build on the laptop, it hits a wall. Because of this, my laptop setup is currently on hold. Until I can upgrade to a better machine, I’m sticking with Void Linux on that device (but that’s a story for a different blog post!).
From there, I dived into Home Manager and used a mix of Google, YouTube, the NixOS Discourse, Wikis, and AI tools to find my way. My configs started out messy (okay, they are still messy), but it’s a functional mess!
The Organization Breakthrough: Abstracting with default.nix
As my configuration grew, my files became massive. At first, my Hyprland config was one giant, intimidating file. While browsing other people’s GitHub repositories, I noticed a much cleaner pattern: using default.nix to abstract the code.
I converted my hyprland into a directory structure like this:
hyprland/default.nixhyprland/autostart.nixhyprland/environment.nixhyprland/keybinds.nixhyprland/rules.nixhyprland/settings.nix
My default.nix now acts as a “traffic controller,” importing all the specific pieces. Now instead of scrolling through 300 lines of code to find a single shortcut, I just open keybinds.nix. It makes the whole system much easier to maintain and reason about.
{ ... }:
{
imports = [
./environment.nix
./settings.nix
./autostart.nix
./keybinds.nix
./rules.nix
./group.nix
../shell/scripts.nix
];
wayland.windowManager.hyprland = {
enable = true;
xwayland.enable = true;
};
}
The Editor Shift: Helix vs. Neovim
Since moving to NixOS, I’ve found myself switching to Helix as my daily driver. The reason is simple: Helix is much easier to configure the “NixOS way”. Since Helix comes with most features built-in, configuring it via Home Manager is clean and straightforward.
However, I haven’t abandoned Neovim. I’ve transitioned to AstroNvim, and I use a clever Nix trick to manage it. Instead of a traditional alias, I use writeShellApplication to create a custom wrappers that set the NVIM_APPNAME environment variable.
This allows me to keep my AstroNvim config in ~/.config while launching it easily through Nix-defined commands like av (for terminal) or ad (for Neovide)
# modules/home-manager/neovim/astronvim.nix
{ pkgs, ... }:
{
home.packages = [
(pkgs.writeShellApplication {
name = "av";
runtimeInputs = [ pkgs.neovim ];
text = ''
export NVIM_APPNAME="astronvim-v5"
exec ${pkgs.neovim}/bin/nvim "$@"
'';
})
(pkgs.writeShellApplication {
name = "ad";
runtimeInputs = [ pkgs.neovide ];
text = ''
export NVIM_APPNAME="astronvim-v5"
exec ${pkgs.neovide}/bin/neovide "$@"
'';
})
];
}
My Home Manager profile now imports everything neatly, keeping my terminal, shell, and multiple editors (I even have Emacs, Kakoune, and Vim in there!) organized:
# modules/home-manager/profiles/desktop.nix
{ pkgs, ... }:
{
imports = [
../helix
../neovim/astronvim.nix
../emacs.nix
../shell/fish
# ... and many more
];
home.sessionVariables = {
EDITOR = "${pkgs.helix}/bin/hx";
VISUAL = "${pkgs.helix}/bin/hx";
};
}
The Wall: IntelliJ and Android Studio
NixOS is great until you try to install a heavy IDE. Installing IntelliJ Community Edition was a struggle because it has many dependencies that conflict with the “Nix way” of doing things. I tried the Flatpak version, but ultimately, I decided to just dual-boot my PC to Windows when I need to use IntelliJ properly.
Flutter was another challenge. I learned that setting up a mobile dev environment on NixOS is quite a quest. I found out about nix-ld, which is necessary to get Android Studio and its binaries running correctly. My setup is currently “held together with duct tape”—if it works, I’m definitely not touching it again because I don’t want to break it!
I’ve also started “nixifying” my environment further. I created some Raku scripts for my work, and I eventually learned I could put Raku code directly inside a Nix file. It’s a weird but powerful way to live.
Productivity Tools: TickTick vs. Super Productivity
I’ve used TickTick for a long time, but I recently discovered an open-source app called Super-Productivity. I really wanted to switch, but the sync between the app and my phone was unreliable. I tried the AppImage and it worked, but it didn’t feel like the “NixOS way.” For now, I’m sticking with TickTick.
My Android Studio & Flutter Setup
If you’re struggling to get Android Studio and Flutter running on NixOS, here is the setup that finally worked for me.
1. Enabling ADB
In my configuration.nix (or a dedicated Android module), I enable ADB and use an activation script to symlink the Nix-provided ADB into the Android SDK folder. This prevents Android Studio from complaining about missing or incompatible ADB binaries.
# modules/nixos/development/android.nix
{ ... }:
{
nixpkgs.config.android_sdk.accept_license = true;
programs.adb.enable = true;
system.userActivationScripts = {
stdio = {
text = ''
rm -f ~/Android/Sdk/platform-tools/adb
ln -s /run/current-system/sw/bin/adb ~/Android/Sdk/platform-tools/adb
'';
};
};
}
2. The Magic of nix-ld
To run the various non-Nix binaries that Flutter and Android Studio depend on, I enabled nix-ld with the necessary libraries:
# modules/nixos/development/nix-ld.nix
{ pkgs, ... }:
{
programs.nix-ld.enable = true;
programs.nix-ld.libraries = with pkgs; [
zlib
stdenv.cc.cc.lib
ncurses5
libGL
libpulseaudio
];
}
3. Home Manager Configuration
Then, I define my packages and session variables in Home Manager:
{ pkgs, ... }:
{
home.packages = with pkgs; [
android-studio
android-tools
gradle
jdk17
flutter
ninja
pkg-config
mesa-demos
];
home.sessionVariables = {
CHROME_EXECUTABLE = "${pkgs.vivaldi}/bin/vivaldi";
ANDROID_HOME = "$HOME/Android/Sdk";
ANDROID_SDK_ROOT = "$HOME/Android/Sdk";
JAVA_HOME = "${pkgs.jdk17.home}";
};
}
4. Pro-Tip: Finding the Flutter SDK Path
On NixOS, the Flutter SDK is wrapped and buried in the /nix/store. If you need the root directory for your IDE or scripts, use this command:
dirname $(dirname $(readlink -f $(which flutter)))
What it does: It finds the flutter binary, resolves all symlinks to the actual store path, and strips away /bin/flutter to give you the SDK root.
Lessons Learned
After a few months in the rabbit hole, here are my main takeaways for anyone starting out:
Don’t fight the
/etc/nixosdefault: Move your config to a user folder and use Flakes as soon as possible. It makes managing your GitHub repo much easier.AI is a great tour guide, but check the map: AI tools are amazing for finding Nix syntax, but always cross-reference with the NixOS Wiki or Discourse, as Nix syntax changes fast.
nix-ldis your best friend: If you are a dev using pre-compiled binaries (like VS Code extensions or Android tools), you almost certainly need nix-ld enabled to save your sanity.Accept the “Functional Mess”: Your first Nix config won’t be elegant. It will be full of “stolen” code from other people’s dotfiles. That’s okay! Get it working first, then optimize later.
Dual-booting isn’t “failing”: If an IDE like IntelliJ is giving you a 5-hour headache on Nix, it’s okay to just use Windows/Standard Linux for that specific task while you learn.
Final Thoughts
NixOS is a steep learning curve, but the ability to reproduce my entire system from a few files is worth the struggle. If you have any tips on how to clean up a messy flake, let me know! Check out my full configuration here: neko-dotfiles
Support my Journey
If you enjoyed this post and want to support my descent into Linux madness, you can find me here:
Every bit of support helps keep the nix-builds running!