Files
nixos/Droidnix/README.org
T
2026-03-23 16:17:57 +00:00

12 KiB
Raw Blame History

Droidnix: A Dendritic NixOS + Home Manager Configuration NixOS Configuration Structure

Introduction   intro

What is Droidnix

Droidnix is a modular, declarative NixOS + Home Manager configuration system. It allows users to choose between Hyprland and Mangowc as their window manager, with shared and WM-specific configurations managed via Emacs Org and Nix Flakes. The project is designed for reproducibility, maintainability, and cross-machine compatibility.

Installed components:

Core
Hyprland
Mangowc

Goals, project Structure, import hierarchy

This project uses a modular NixOS configuration with Hyprland and MangoWC support, designed for literate programming and cross-device reusability. The Droidnix repository is organized into two main parts:

  1. .assets/: Static, non-generated files (e.g., configs, scripts, themes).
  2. Generated folders (system, hyprland, mangowc): NixOS and Home Manager configurations, generated from Org files.

Root Level

  • flake.nix is the entry point and imports:

    • generated/assets/
    • generated/<host>/modules/
    • generated/hosts/

Generated Structure

The generated/ directory contains all generated configurations, divided into three main groups: system, hyprland, and mangowc.

First Setup

  1. Clone this repository.
  2. Run the setup script: ./setup_droid.
  3. Edit .assets/system/conf/base.conf to choose your window manager (wm = "hyprland" or wm = "mangowc").
  4. Tangle this Org file to generate Nix configurations: C-c C-v t in Emacs or use this: emacs README.org --batch -f org-babel-tangle && emacs --batch --eval "(setq org-html-htmlize-output-type nil)" README.org -f org-html-export-to-html
  5. Build and switch: sudo nixos-rebuild switch --flake .#<hostname>.

The Assets Folder   assets

The .assets/ folder contains all static files, such as configs, scripts, and themes. These files are not generated and can be edited directly.

Module boilerplate look like this   code

generated/boilerplate.nix

{ lib, config, pkgs, _module, ... }:

let
  username = config.defaultUser or "henrov";
in {
  # System packages / options
  environment.systemPackages = [ pkgs.feh pkgs.waybar ];

  # Home Manager contribution
  _module.args.hmUsers = lib.mkIf true {
    ${username} = {
      home.file = {
        ".config/waybar/config"  = { source = ./waybar/config; };
        ".config/waybar/style.css" = { source = ./waybar/style.css; };
      };
    };
  };
}

The Actual Code   code

This section contains the Org blocks for tangling Nix code into the generated folders.

flake.nix

The Nix flake definition for Droidnix.

{
  description = "Droidnix: A dendritic NixOS + Home Manager configuration";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";

    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    flake-parts.url = "github:hercules-ci/flake-parts";
    import-tree.url = "github:vic/import-tree";

    stylix = {
      url = "github:nix-community/stylix";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    zen-browser = {
      url = "github:youwen5/zen-browser-flake";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    hyprland.url = "github:hyprwm/Hyprland";
  };

  outputs = { self, nixpkgs, home-manager, flake-parts, import-tree, stylix, hyprland, zen-browser, ... }:
    let
      systems = ["x86_64-linux"];
    in
    lib.flattenTree (map (system:
      let
        pkgs = import nixpkgs { inherit system; };
        flakeRoot = self;
        hmModules = home-manager.lib.hmModules;
      in {
        nixosConfigurations = {
          traveldroid = flake-parts.lib.mkFlakeModule {
            inherit pkgs;
            modules = [ ./hosts/traveldroid.nix ];
            extraArgs = { inherit flakeRoot; };
          };
        };

        homeManagerConfigurations = {
          traveldroid = hmModules.makeModuleSet { inherit pkgs flakeRoot; };
        };
      }
    ) systems);
}

generated/hosts/traveldroid/traveldroid.nix

{ lib, config, pkgs, inputs, ... }:

let
  hostname    = "traveldroid";
  modulesPath = ./generated/modules/${hostname};
  usersPath   = ./generated/users;

  # Import all host-specific modules recursively (not evaluated yet)
  hostModules = inputs.import-tree modulesPath;

  # Import all global users
  globalUsers = inputs.import-tree usersPath;

  # Collect all Home Manager user attrsets from host modules + global users
  hmUsersList =
    map (m: m._module.args.hmUsers or {}) (hostModules.imports ++ globalUsers.imports);

in
{
  #################################
  # Core system config
  #################################
  networking.hostName = traveldroid;
  system.stateVersion  = "26.05";

  #################################
  # Enable Home Manager
  #################################
  programs.home-manager.enable = true;

  #################################
  # Module imports
  #################################
  imports =
    [
      ./boot.nix
      ./hardware-configuration.nix
    ]
    ++ hostModules.imports
    ++ globalUsers.imports;

  #################################
  # Home Manager aggregation
  #################################
  home-manager.users = lib.mkMerge hmUsersList;
}

generated/hosts/traveldroid/hardware-configuration.nix

  1. Boot into NixOS Live ISO or your installed system.
  2. Open a terminal.
  3. Run: <code>sudo nixos-generate-config root /mnt</code> (Omit root /mnt if already running NixOS.)
{
  hostname,
  pkgs,
  lib,
  modulesPath,
  user,
  config,
  ...
}:
{
  imports = [
    # (modulesPath + "/installer/scan/not-detected.nix")
    #../../hardware/hardware.nix
  ];

  boot.initrd.availableKernelModules = [
    "xhci_pci"
    "nvme"
    "usb_storage"
    "sd_mod"
    "rtsx_usb_sdmmc"
  ];
  boot.initrd.kernelModules = [ ];
  boot.kernelModules = [ "kvm-intel" ];
  boot.extraModulePackages = [ ];

  fileSystems."/" = {
    device = "/dev/disk/by-uuid/69433a14-fbaf-401b-af85-cd1bbf02b4e2";
    fsType = "ext4";
  };

  fileSystems."/boot" = {
    device = "/dev/disk/by-uuid/811D-0676";
    fsType = "vfat";
    options = [
      "fmask=0077"
      "dmask=0077"
    ];
  };

  swapDevices = [
    { device = "/dev/disk/by-uuid/b6c557c2-7682-460b-a5e7-8f6f2f429a3a"; }
  ];

  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
  hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

generated/hosts/traveldroid/boot.nix

{ pkgs, config, lib, flakeRoot, ... }:

{
  ############################
  # Bootloader (GRUB)
  ############################
  boot.loader = {
    grub = {
      enable = true;
      efiSupport = true;
      devices = [ "nodev" ]; # pas aan naar je echte EFI-device indien nodig
      useOSProber = true;
      timeout = 5;
    };
  };

  ############################
  # Kernel / boot settings
  ############################
  boot.kernelPackages = pkgs.linuxPackages_latest;

  boot.kernelParams = [
    "quiet"
    "splash"                 # REQUIRED for Plymouth
    "udev.log_level=3"
    "rd.systemd.show_status=false"
  ];

  boot.consoleLogLevel = 0;
  boot.supportedFilesystems = [ "ntfs" ];

  ############################
  # Plymouth
  ############################
  boot.plymouth = {
    enable = true;
    theme = "rings";

    themePackages = [
      (pkgs.adi1090x-plymouth-themes.override {
        selected_themes = [ "rings" ];
      })
    ];
  };

  boot.initrd.systemd.enable = true;

  ############################
  # Clean state
  ############################
  # Remove any old theme environment.etc symlinks
  #environment.etc = lib.mkForce {};
  system.stateVersion = "26.05";
}

Let's define the core of the system

Nix itself

generated/traveldroid/todo/system/nix.nix

{ lib, config, ... }:

{
    nix.settings = {
      experimental-features = [ "nix-command" "flakes" ];
      download-buffer-size = 536870912; # 512 MB
      cores = 2;
      max-jobs = 1;
    };
}

User stuff

generated/users/henrov.nix

This is the default user, just search and replace henrov another name if you want to change

{ lib, config, pkgs, ... }:

let
  username = "henrov";
in
{
  #################################
  # NixOS system user
  #################################
  users.users.${username} = {
    isNormalUser = true;
    home = "/home/${username}";
    hashedPassword = "$6$S7iShgBxB.77CwmP$i0njK.2r3OL5UEvgZbmwZ0rnpZ4QyJcv8p9uCmJ4AiVPSMXkQkIwMLzyAOnJ0q8.tPLIp/7EquEIZeK8qbmgw/";
    extraGroups = [ "wheel" "networkmanager" ];
  };

  #################################
  # Home Manager user definition
  #################################
  _module.args.hmUsers = {
    ${username} = {
      # Minimal required
      home.username      = username;
      home.homeDirectory = "/home/${username}";
      home.stateVersion  = "26.05";

      # Add user-specific packages here
      home.packages = [
      ];

      # Add user dotfiles, session variables, etc. here if needed
      home.file = {
        # Example:
        # ".bashrc" = { source = /path/to/bashrc; };
      };
    };
  };
}

generated/users/copy_2_home.nix

This copies stuff to the user home-folder

{ config, pkgs, lib, flakeRoot, ... }:

let
  username  = config.users.users.defaultUser or "henrov";
  homeDir   = "/home/${username}";
  assetPath = "${flakeRoot}/assets/copy_2_home";
in
{
  environment.systemPackages = [ pkgs.rsync ];

  systemd.services.copyAssets = {
    description = "Copy assets to ${username}'s home directory";
    wantedBy = [ "multi-user.target" ];

    # oneshot service runs once at boot
    serviceConfig.Type = "oneshot";

    # Always use /bin/sh -c for multi-line commands
    serviceConfig.ExecStart = ''
      /bin/sh -c '
        echo "Copying assets from ${assetPath} to ${homeDir} ..."

        if [ ! -d "${assetPath}" ]; then
          echo "ERROR: ${assetPath} does not exist"
          exit 1
        fi

        mkdir -p "${homeDir}"
        chown ${username}:${username} "${homeDir}"

        ${pkgs.rsync}/bin/rsync -a --no-owner --no-group "${assetPath}/" "${homeDir}/"

        echo "Done copying assets."
      '
    '';
  };
}