Neovim on NixOS: Keep Your Config in Git and Let LazyVim Save Settings

Use Home Manager for your Neovim configuration, with two writable files that save LazyVim extras and plugin versions back into your repo.

On this page

This can be a pain point to use Neovim with LazyVim declaratively. One of the major reason is LazyVim can write back configurations, which you will need to capture it back in your repo.

I keep my Neovim configuration in my NixOS repo. Rebuild the workstation, and Home Manager puts the files in place again.

But LazyVim also saves things from inside the editor. Enable an extra, or update plugins, and it writes a JSON file. Those writes need somewhere writable. The Nix store is read-only.

I am aware of the Nixvim (opens in a new tab). It is super simplified and controlled. But I need to change declarations each time I need to change LazyVim config.

My setup gives those two files writable links back to the repo. I can use LazyVim normally, then review what changed with git diff.

TL;DR

  • Keep your Lua configuration in app-configs/nvim/. This is actual layout of my nix repo directory.
  • Keep lazyvim.json and lazy-lock.json in app-configs/nvim-state/.
  • Let Home Manager link the Lua files normally, and give those two JSON files writable links.
  • You need to commit nix repo changes once it is done via Neovim, it does not automatically commit or push anything.

Before you start

Here, we will install Neovim and set up LazyVim.

Use a terminal with true-color support, such as Ghostty or Kitty.

The examples use ~/git-projects/nixos-config, a Home Manager module called home.nix, and a flake host called nixos. Replace the repo path and host name with yours throughout. Start with a clean Git working tree and close Neovim.

PartManaged by
Neovim executable and command-line toolsNixOS packages
Lua settings, keymaps and plugin declarationsHome Manager, from the repo
Selected LazyVim extras (lazyvim.json)LazyVim, through a writable link
Plugin revisions (lazy-lock.json)lazy.nvim, through a writable link
Downloaded plugins, caches and editor historyNormal user data outside Git

The repo records your configuration and plugin revisions without packaging every plugin through Nix. Plugin installation still needs downloads, and NixOS generations do not roll back these writable files.

How my NixOS repo is laid out (partial view):

 nixos-config
├──  app-configs
│ ├──  nvim 👈 this one is the declaration
│ ├──  nvim-state 👈 this one coming back from the lazyvim config
├──  modules
├──  recovery
├──  configuration.nix 👈
├──  flake.lock
├──  flake.nix
├──  hardware-configuration.nix
├──  home.nix 👈
├──  packages.nix
├──  shell.nix

I use the 👈 marker to show in the list above, which files to touch.

1. Declare Neovim and its tools

In configuration.nix, append these packages to your existing environment.systemPackages list. If your Neovim is inside packages.nix, keep them there instead. Each package in one place.

configuration.nix
environment.systemPackages = with pkgs; [
neovim
git
curl
ripgrep
fd
fzf
lazygit
gcc
gnumake
unzip
tree-sitter
];

Keep your other packages. This assumes the module already accepts pkgs. Neovim is the editor; LazyVim is a ready-made configuration that adds plugins, completion and useful defaults. The other packages provide search, downloads and build tools.

LazyVim currently requires Neovim 0.11.2 or newer (opens in a new tab). A Nerd Font is optional for its icons. Select one in your terminal if you already have it.

2. Put the LazyVim starter in your repo

The commands below create new folders. If you already have repo-managed Neovim files, stop and merge the pattern into those instead.

From your repo root, create a backup directory outside Git:

Terminal window
cd ~/git-projects/nixos-config
backup="$HOME/nvim-backup-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup"
if [ -e ~/.config/nvim ]; then
cp -RL ~/.config/nvim "$backup/nvim"
fi
echo "$backup"

Keep that printed path, and use the same terminal for the remaining commands. Now get the official LazyVim starter (opens in a new tab):

Terminal window
mkdir -p app-configs/nvim-state
git clone https://github.com/LazyVim/starter app-configs/nvim
mv app-configs/nvim/.git "$backup/starter-git"

Moving the starter’s Git metadata aside lets your own repo track the files. Keep plugin revisions and extras in the separate writable folder:

Terminal window
if [ -f app-configs/nvim/lazyvim.json ]; then
mv app-configs/nvim/lazyvim.json app-configs/nvim-state/
else
printf '{}\n' > app-configs/nvim-state/lazyvim.json
fi
printf '{}\n' > app-configs/nvim-state/lazy-lock.json

The empty lockfile is for this fresh installation. LazyVim will populate it on first startup. If you are migrating an existing LazyVim setup, copy your own Lua files and both existing JSON files instead so you retain your settings and plugin versions.

In home.nix, add config to the existing module arguments if it is missing. Keep your other arguments:

home.nix
{ config, pkgs, ... }:

Add these assignments inside the existing module body. Replace any old declarations managing these same Neovim paths:

home.nix
home.file.".config/nvim" = {
source = ./app-configs/nvim;
recursive = true;
};
home.file.".config/nvim/lazyvim.json".source =
config.lib.file.mkOutOfStoreSymlink
"${config.home.homeDirectory}/git-projects/nixos-config/app-configs/nvim-state/lazyvim.json";
home.file.".config/nvim/lazy-lock.json".source =
config.lib.file.mkOutOfStoreSymlink
"${config.home.homeDirectory}/git-projects/nixos-config/app-configs/nvim-state/lazy-lock.json";

recursive = true links the individual configuration files. mkOutOfStoreSymlink points to a writable file in your checkout instead of an immutable copy in the Nix store. Use the string path shown here for those two files, not a relative Nix path such as ./app-configs/nvim-state/lazyvim.json.

Keep the checkout at that location. Moving it will break the writable links until you update these paths and rebuild.

4. Build and start Neovim

Stage the new files so a Git-backed flake can see them, then build without activating. If your package list is in packages.nix, use that filename instead of configuration.nix in both git add commands:

Terminal window
git add configuration.nix home.nix app-configs/nvim app-configs/nvim-state
sudo nixos-rebuild build --flake .#nixos

If the build fails, fix it before continuing. After it passes, move the old live directory aside so Home Manager can create its links:

Terminal window
if [ -e ~/.config/nvim ]; then
mv ~/.config/nvim "$backup/nvim-before-links"
fi
sudo nixos-rebuild switch --flake .#nixos

This avoids overwriting existing Neovim files. My own configuration also uses force = true on the two JSON declarations, but the backup-and-move step makes that unnecessary here.

Check the final destinations:

Terminal window
readlink -f ~/.config/nvim/lazyvim.json
readlink -f ~/.config/nvim/lazy-lock.json

Both should end in your checkout’s app-configs/nvim-state/, each with its matching filename. If they resolve into /nix/store, stop and check the declarations before changing extras.

If you used Neovim before with a different setup, move ~/.local/share/nvim, ~/.local/state/nvim and ~/.cache/nvim into your backup directory before this first launch. Those folders can contain old plugins and sessions.

Open nvim and let the first plugin installation finish. Run :LazyHealth to check the installation. On NixOS, install any missing language tools through your package list or a project development shell. Mason downloads are not guaranteed to run on NixOS.

5. Save a setting back into Git

Inside Neovim, run :LazyExtras, and press x on an extra you want to enable. Restart Neovim when prompted. Then, from your repo:

Terminal window
git diff HEAD -- app-configs/nvim-state/lazyvim.json

You should see the changed extras selection. Plugin updates can also change lazy-lock.json. lazy.nvim recommends keeping that lockfile in version control (opens in a new tab).

Review both files before saving the change in Git:

Terminal window
git diff HEAD -- app-configs/nvim-state/
git add configuration.nix home.nix app-configs/nvim app-configs/nvim-state
git commit -m "feat(neovim): track config and writable LazyVim state"

On my workstation, I verified the live links point into the repo. The earlier setup check also exercised LazyVim’s JSON save function and recorded a Git change. The interactive toggle above is your check that it works in your own editor.

Everyday changes

Edit Lua settings in app-configs/nvim/, then rebuild to apply them. Extras and plugin updates save straight into the two linked JSON files, so those changes need a Git review rather than another rebuild.

To undo an unwanted plugin update, close Neovim, restore the last committed lockfile, then reopen the editor and run :Lazy restore:

Terminal window
git restore --source=HEAD --staged --worktree -- app-configs/nvim-state/lazy-lock.json

That discards uncommitted lockfile changes. The restore command (opens in a new tab) installs the plugin revisions recorded there.

To cancel the whole setup, restore your previous package list and home.nix declarations and rebuild. Move the new ~/.config/nvim directory aside, then copy your saved nvim backup back into ~/.config/ if you had one. Restore any data folders you moved too.

Keep this writable-link trick limited to files you have checked. Some applications replace files in a way that breaks symlinks. For these two LazyVim files, it lets me keep the settings I change in the editor beside the configuration that rebuilds it.

Did this help? or maybe you have a better way to do it. Let me know.

Comments

In this series: Building My NixOS Workstation

10 published posts

View series →
  1. Moving into Niri & DankMaterialShell in NixOS
  2. Install the ChatGPT and Codex Desktop App Declaratively on NixOS
  3. How I Run Affinity V2 on NixOS with affinity-nix
  4. Use Elgato Wave:3 on Linux with Noise Reduction, EQ, Compression and a Virtual Microphone
  5. Install Vicinae on NixOS with a Modular Niri Setup
  6. 5 Best Terminal Tools for NixOS: My Zsh Setup and Wrappers
  7. Moving from Niri and DMS to Noctalia v5 on NixOS
  8. Distrobox on NixOS: Declare an Ubuntu Toolbox and Its Zsh Setup
  9. Keep NixOS Secrets in Git with agenix: A Step-by-Step Guide
  10. Neovim on NixOS: Keep Your Config in Git and Let LazyVim Save Settings
← All posts

Type to search the published collection.