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

13 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.

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";
    };

    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, import-tree, stylix, hyprland, zen-browser, ... }:
    let
      system = "x86_64-linux";
      flakeRoot = self;
    in {
      nixosConfigurations = {
        traveldroid = nixpkgs.lib.nixosSystem {
          inherit system;

          modules = [
            ./generated/hosts/traveldroid/host.nix
          ];

          specialArgs = {
            inherit flakeRoot;
            inherit home-manager import-tree stylix hyprland zen-browser;
          };
        };
      };
    };
}

generated/hosts/traveldroid/host.nix

{ lib, config, pkgs, flakeRoot, import-tree, home-manager, ... }:

let
  hostname = "traveldroid";

  modulesPath = "${flakeRoot}/generated/modules/${hostname}";
  usersPath   = "${flakeRoot}/generated/users";

  hostModules = import-tree modulesPath;
  globalUsers = import-tree usersPath;

  allModules = hostModules.imports ++ globalUsers.imports;

in
{
  #################################
  # Core system config
  #################################

  networking.hostName = hostname;
  system.stateVersion = "26.05";

  #################################
  # Imports
  #################################

  imports =
    [
      ./boot.nix
      ./hardware-configuration.nix

      # REQUIRED for Home Manager
      home-manager.nixosModules.home-manager
    ]
    ++ allModules;

  #################################
  # Home Manager integration
  #################################

  home-manager.useGlobalPkgs = true;
  home-manager.useUserPackages = true;
}

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";
}

Following are the imported modules

generated/modules/traveldroid/desktop

generated/modules/traveldroid/desktop/wayland.nix

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

{
  #################################
  # Core Wayland packages
  #################################
  environment.systemPackages = with pkgs; [
    wayland
    wl-clipboard      # optional but commonly used for copy/paste
  ];

  #################################
  # Optional: enable graphics stack
  #################################
  hardware.opengl.enable = true;

  #################################
  # Optional session variables for Wayland
  #################################
  environment.sessionVariables = {
    # Forces some apps to use Wayland
    NIXOS_OZONE_WL = "1";
  };
}

generated/modules/traveldroid/desktop/stylix.nix

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

let
  # Determine the default username from host config
  username = config.defaultUser or "henrov";

  moduleName = "stylix";
  assetPath  = "${flakeRoot}/assets/system/conf/${moduleName}";

  # Read all files in the asset directory
  programFiles = builtins.readDir assetPath;

  files = lib.genAttrs (builtins.attrNames programFiles) (name: {
    source = "${assetPath}/${name}";
  });

  # Optional stylix.conf
  stylixConfFile = "${assetPath}/stylix.conf";
  stylixConf =
    if builtins.pathExists stylixConfFile
    then builtins.readFile stylixConfFile
    else "";

  # Cursor defaults
  cursorName = "phinger-cursors-light";
  cursorSize = 24;
in
{
  ############################
  # System-level packages
  ############################
  environment.systemPackages = [
    pkgs.feh
    pkgs.st
  ];

  ############################
  # Home Manager user config
  ############################
  _module.args.hmUsers = {
    ${username} = {

      # Map all config files into ~/.config/stylix/
      xdg.configFile =
        lib.mapAttrs' (name: value: {
          name = "${moduleName}/${name}";
          value = { inherit (value) source; };
        }) files;

      # Environment variables for the session
      home.sessionVariables = {
        STYLIX_CONF      = "$HOME/.config/stylix/stylix.conf";

        XCURSOR_THEME    = cursorName;
        XCURSOR_SIZE     = toString cursorSize;
        HYPRCURSOR_THEME = cursorName;
        HYPRCURSOR_SIZE  = toString cursorSize;
      };
    };
  };
}

generated/modules/traveldroid/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."
      '
    '';
  };
}