This repository contains NixOS, nix-darwin, and Home Manager configurations in Nix. You are a sysadmin managing server configurations and deployments.
Can use deploy for both local and remote hosts
deploy -s .#ryu # Desktop (x86_64-linux)
deploy -s .#tako # Server (x86_64-linux)
deploy -s .#tsuba # Raspberry Pi (aarch64-linux)
deploy -s .#kuro # MacBook M4 Pro (aarch64-darwin)
deploy -s .#shiro # Mac Mini M4 (aarch64-darwin)Linux (NixOS):
deploy -s .#ryu
deploy -s .#tako
deploy -s .#tako --builders '' --cores 32 # with no other builders and 32 cores
deploy -s .#ryu --max-jobs 4 --cores 32 # use 32 cores and 4 parallel derivations
sudo nixos-rebuild test --fast --flake . # Test without activation
sudo nixos-rebuild switch --rollback --flake . # RollbackmacOS (nix-darwin):
deploy -s .#kuro
deploy -s .#shiro
sudo nix-darwin test --fast --flake .NEVER use nix flake check — it runs 715+ checks and is too slow. Always validate with build commands:
nixos-rebuild build --flake . # Validate NixOS config (builds current host)
darwin-rebuild build --flake . # Validate nix-darwin config (builds current host)
alejandra fmt . # Format all files
alejandra fmt <file>.nix # Format single filepython3 ./scripts/list-host-config.py . # Table of system + HM programs & services per hostflake.nix- Main entry point, device definitionsnixos/- NixOS machine configs (ryu, tako, tsuba)darwin/- macOS machine configs (kuro, shiro)home/- Home Manager modules (programs/, services/, apps/)modules/- Custom modules (nixos/, darwin/, home/)secrets/- SOPS encrypted secretsoverlays.nix,deploy.nix,sops.nix,stylix.nix- Config files
File Structure:
{inputs, config, pkgs, lib, device, ...}: {
# Configuration here
}Imports:
- Order:
inputs,config,pkgs,lib,device, custom params,... - Use set destructuring for clarity
Formatting:
- Use
alejandraformatter (run before committing) - 2-space indentation
- Trailing commas in lists and attribute sets
Naming Conventions:
- Files: lowercase-with-hyphens (e.g.,
my-module.nix) - Attributes: camelCase (e.g.,
enableMyFeature) - Functions: camelCase (e.g.,
mkDevice) - Constants: UPPER_SNAKE_CASE (e.g.,
API_KEY) - Device names: lowercase (e.g.,
ryu,tako)
Let Expressions:
with lib; let
cfg = config.programs.myProgram;
in {
options = { ... };
config = mkIf cfg.enable { ... };
}Conditionals:
- Use
mkIffor config options - Use
lib.optionalAttrsfor attribute sets - Use
lib.optionalsfor lists
Simple Package Module:
{pkgs, ...}: {
home.packages = [pkgs.myPackage];
}Program Configuration Module:
{config, pkgs, lib, ...}:
with lib; let
cfg = config.programs.myProgram;
in {
options.programs.myProgram = {
enable = mkEnableOption "myProgram";
};
config = mkIf cfg.enable {
home.packages = [pkgs.myProgram];
};
}Device-Specific Logic:
home.packages = lib.optionals device.isLinux [pkgs.linuxPackage]
++ lib.optionals device.isDarwin [pkgs.macPackage];
sessionVariables.BROWSER = if device.isDarwin then "open" else "xdg-open";- NEVER create markdown files unless explicitly requested
- DO NOT add shell scripts - use Nix expressions
- All configurations must use Nix expressions when possible
- Follow existing naming conventions and directory structure
- Create custom application entries in
~/.local/share/applications/{appname}.desktop - GUI / gaming apps go to
nixos/ryu/(apps/ or games/) — never to servers (tako,tsuba). Servers are headless and must not pull in desktop/gaming packages. - Troubleshooting steps go in
TROUBLESHOOTING.md— never inREADME.mdor other docs. Append a new##section per issue with symptom and fix.
- Secrets are managed with SOPS in
secrets/directory - Encrypted secrets in
secrets/directory - Configuration in
.sops.yaml - Access via
config.sops.secrets."secret/value".pathThe path is the file that containsfoo: bar: somesecret
somesecret - Add new secrets using
sops setExampleThis will add a randomly generated secret to the sops file NOTE: You MUST NEVER decrypt the secrets/secrets.yaml file NOTE: You MUST NEVER generate secrets manually and then put them in the file later. It should ALWAYS be a single commandopenssl rand -hex 32 | tr -d '\n' | jq -sR | sops set --value-stdin secrets/secrets.yaml '["foo"]["bar"]'
- NEVER use systemd shell scripts to generate secret files — use
sops.templatesto render the file andsystemd.tmpfiles.ruleswithC+to copy it into placesops.templates."foo-config.json".content = builtins.toJSON { api_key = config.sops.placeholder."foo/api_key"; }; systemd.tmpfiles.rules = [ "C+ /var/lib/foo/config.json 0644 root root - ${config.sops.templates."foo-config.json".path}" ];
- If a service takes a file as environmentFile then define sops templates as such
and use them like so
sops.templates = { "FOO_VARS.env".content = '' FOO_API_KEY=${config.sops.placeholder."foo/api_key"} FOO_USER_NAME=${config.sops.placeholder."foo/username"} ''; };
If they don't take environmentFile as part of settings thenservices.foo.settings.environmentFile = config.sops.templates."opencode-web.env".path;
systemd.services.foo = { serviceConfig = { EnvironmentFile = config.sops.templates."FOO_VARS.env".path; }; };
just add foo home/apps # Creates home/apps/foo.nix and adds import
just add bar home/programs # Creates home/programs/foo.nix and adds importcfcli add --type A foobar.bazbar.biz 100.102.64.19- Determine location:
modules/nixos/,modules/darwin/, ormodules/home/ - Create file with proper structure
- Add to
modules/default.niximports
Devices are defined in flake.nix using mkDevice. Properties available:
device.isLinux,device.isDarwin,device.isArmdevice.isServer,device.hasGui,device.isDesktopLinuxdevice.name,device.user,device.home
- Use
mkIfto conditionally enable configurations - Handle both Linux and macOS cases when adding cross-platform features
- Build first:
just buildornixos-rebuild build --flake . - Check for errors with
--show-traceflag
When adding a new fetch source in the overlay, set hash = lib.fakeHash; first, run the build, and copy the 'got:' hash from the error. Do not prefetch manually.
home/is for shared/cross-host config; host-specific apps (especially gaming/GUI) belong under the host directory (e.g.,nixos/ryu/).- Distinguish gaming/GUI configs from headless/server configs.