9 votes

Dead simple cross platform home manager with flakes

8 comments

  1. vczf
    Link
    I finally managed to get home manager working on both my linux machines (non-nixos) and my macbook pro. I thought it might be worth sharing a simple template to document the approach, because I...

    I finally managed to get home manager working on both my linux machines (non-nixos) and my macbook pro. I thought it might be worth sharing a simple template to document the approach, because I could not find an example configuration to help me. I offer this template for anybody interested in getting started with home-manager.

    It is bloody amazing to be able to maintain a consistent shell environment across all my devices.

    There is actually a way to simplify the flake.nix even more, but it would require using the --impure flag to access builtins.currentSystem. I already am impure because I needmkOutOfStoreSymlink in order to configure my ~/.ssh directory, but used the more verbose approach for this template.

    1 vote
  2. [7]
    acdw
    Link
    would you say it's worth it to just use home manager?

    would you say it's worth it to just use home manager?

    1. [6]
      vczf
      Link Parent
      Yes, that way you can configure your aliases, prompt, programs, etc. one time and easily keep it in sync across machines. It makes it actually worth it to invest time in configuring a very custom...

      Yes, that way you can configure your aliases, prompt, programs, etc. one time and easily keep it in sync across machines. It makes it actually worth it to invest time in configuring a very custom terminal environment because it's so easy to set up on new machines once you have it working.

      One feature I really like is that you can declaratively configure any file you need in your home directory. Makes it easy to keep track of your dotfiles, even for things you don't install with nix.

      If I want to get my terminal up on a new machine (like a container or VM) I just clone or symlink my home-manager repo to ~/.config/home-manager , install nix, and run the command in the README.

      I don't think it's worth using NixOS as a beginner with nix. It is too aggravating when you want to install something that is unsupported and are unable to do so without packaging it yourself. But home manager with a simple flake config just to configure your dotfiles is uniquely useful.

      1 vote
      1. [5]
        acdw
        Link Parent
        awesome, thank you! do you think you could share yours? I'm curious as to what it looks like... all I can picture is basically config files wrapped in another layer of config

        awesome, thank you! do you think you could share yours? I'm curious as to what it looks like... all I can picture is basically config files wrapped in another layer of config

        1. [4]
          vczf
          Link Parent
          I can't share my whole repo since it's got some secrets. Here's my home.nix though, which is the core where I configure everything. I only take things out of home.nix and move them into their own...

          I can't share my whole repo since it's got some secrets. Here's my home.nix though, which is the core where I configure everything. I only take things out of home.nix and move them into their own files when they start getting too unwieldy inside home.nix. It's messy, though not particularly complicated.

          https://gist.github.com/crasm/59938f3364d2df6319604a5f3fb927fb

          { config, pkgs, lib, ... }:
          let
            isLinux = pkgs.stdenv.hostPlatform.isLinux;
            isDarwin = pkgs.stdenv.hostPlatform.isDarwin;
            unsupported = builtins.abort "Unsupported platform";
          
            homeDir = "${config.home.homeDirectory}";
            stuffDir =
              if isLinux then "/stuff" else
              if isDarwin then "${homeDir}/stuff" else unsupported;
            hmDir = "${stuffDir}/nix/home-manager";
          
          in
          {
            imports = [
              ./fonts.nix
              ./neovim.nix
            ];
          
            home.username = "vczf";
            home.homeDirectory =
              if isLinux then "/home/vczf" else
              if isDarwin then "/Users/vczf" else unsupported;
          
            home.stateVersion = "23.05"; # Don't change this
            programs.home-manager.enable = true;
          
          
            home.packages = with pkgs; ([
              # Common packages
              any-nix-shell
              bat
              htop
              mosh
              nixpkgs-fmt
              stow
              tree
              zsh-vi-mode
            ] ++ lib.optionals isLinux [
              # GNU/Linux packages
              nmon
              trashy
              xfsprogs
              xsel
            ]
            ++ lib.optionals isDarwin [
              # macOS packages
              gnused
            ]);
          
            home.shellAliases = {
              h = "cd ${hmDir}";
              he = "cd ${hmDir}; home-manager edit";
              hs = "home-manager switch --impure";
              userctl = "systemctl --user";
              open =
                if isLinux then "xdg-open" else
                if isDarwin then "open" else unsupported;
            };
          
            home.sessionVariables = { };
          
            xdg.configFile = {
              "nixpkgs/config.nix".text = "{ allowUnfree = true; }"; # There may be a better way to do this directly in the flake
              "paru/paru.conf" = {
                enable = isLinux;
                text = ''
                  [options]
                  CloneDir = "${stuffDir}/aur"
                '';
              };
            };
          
            programs.ssh = {
              enable = true;
              package = pkgs.openssh;
              matchBlocks = {
                "yoga" = {
                  user = "vczf";
                  identityFile = "~/.ssh/keys/yoga";
                };
                "github.com" = {
                  user = "git";
                  identityFile = "~/.ssh/keys/gh";
                };
              };
              extraOptionOverrides = {
                "AddKeysToAgent" = "yes";
              };
            };
          
            home.file = with config.lib.file; {
              # I can't link .ssh/ directly because it .ssh/config is generated by nix
              # ```
              # error: builder for [...] failed with exit code 1;
              #        last 1 log lines:
              #        > Error installing file '.ssh/config' outside $HOME
              # ```
              # ".ssh/" = {
              #   source = mkOutOfStoreSymlink "${hmDir}/ssh";
              #   recursive = true;
              # };
          
              ".ssh/keys" = {
                source = mkOutOfStoreSymlink "${hmDir}/ssh/keys";
                recursive = true;
              };
              ".ssh/authorized_keys".source = mkOutOfStoreSymlink "${hmDir}/ssh/authorized_keys";
              ".ssh/known_hosts".source = mkOutOfStoreSymlink "${hmDir}/ssh/known_hosts";
            };
          
            programs.zsh = {
              enable = true;
              enableAutosuggestions = true;
              enableSyntaxHighlighting = true;
              enableVteIntegration = true;
              autocd = true;
              # historySubstringSearch = { enable = true; };
          
              plugins = [
                # {
                #   name = "zsh-nix-shell";
                #   file = "nix-shell.plugin.zsh";
                #   src = pkgs.fetchFromGitHub {
                #     owner = "chisui";
                #     repo = "zsh-nix-shell";
                #     rev = "v0.7.0";
                #     sha256 = "0za4aiwwrlawnia4f29msk822rj9bgcygw6a8a6iikiwzjjz0g91";
                #   };
                # }
              ];
          
              oh-my-zsh = {
                enable = true;
                theme = "bira";
                # theme = "simple";
                # theme = "pure";
                plugins = [
                  "ssh-agent"
                ];
              };
              initExtra = builtins.concatStringsSep "\n" [
                (builtins.readFile "${hmDir}/zsh/nnn.sh")
                ''
                  chpwd () {
                    ls
                  }
                  any-nix-shell zsh --info-right | source /dev/stdin
                  source ${pkgs.zsh-vi-mode}/share/zsh-vi-mode/zsh-vi-mode.plugin.zsh
                ''
              ];
            };
          
            programs.git = {
              enable = true;
              lfs.enable = true;
              lfs.skipSmudge = true;
              includes = [{
                contents.user.name = "crasm";
                contents.user.email = "crasm@git.vczf.us";
              }];
            };
          
            programs.nnn = {
              enable = true;
              bookmarks = {
                h = "~";
                s =
                  if isLinux then "/stuff" else
                  if isDarwin then "~/stuff" else unsupported;
              };
            };
          
            programs.tmux = {
              enable = true;
              keyMode = "vi";
              extraConfig = ''
                bind h select-pane -L
                bind j select-pane -D
                bind k select-pane -U
                bind l select-pane -R
              '';
            };
          
            programs.direnv.enable = true;
            programs.direnv.nix-direnv.enable = true;
          }
          
          1 vote
          1. [3]
            acdw
            Link Parent
            thank you! this gives me an idea. so it looks like it's partly inserted for strings and partly a dsl?

            thank you! this gives me an idea. so it looks like it's partly inserted for strings and partly a dsl?

            1. vczf
              Link Parent
              Yep. The options can be referenced in man home-manager.nix or here: https://mipmip.github.io/home-manager-option-search/ Pretty much every supported program has an attribute for freeform text...

              Yep. The options can be referenced in man home-manager.nix or here: https://mipmip.github.io/home-manager-option-search/

              Pretty much every supported program has an attribute for freeform text configuration since not everything can be a nix option.

              1 vote