A modular, flake-based NixOS configuration for personal systems with declarative disk management, secrets handling, and home-manager integration.
# Build without switching
just build
# Build and switch to new configuration
just switch
# Update flake inputs
just update
# See all available commands
just --listnix-system/
├── flake.nix # Flake definition with inputs and outputs
├── flake.lock # Locked flake dependencies
├── justfile # Task automation (like Makefile)
├── modules/ # Reusable NixOS modules
│ ├── system/ # Core system configs
│ ├── desktop/ # Desktop environments
│ ├── services/ # System services
│ ├── users/ # User management
│ ├── packages/ # Package collections
│ └── hardware/ # Hardware profiles
├── home/ # Home-manager configs
│ ├── profiles/ # Complete user profiles
│ └── programs/ # Program configurations
├── hosts/ # Host-specific configs
│ ├── desktop/ # Desktop machines
│ └── servers/ # Server machines
└── secrets/ # Encrypted secrets (agenix)
| Host | Type | Description |
|---|---|---|
oddship-thinkpad-x1 |
Desktop | Primary workstation with GNOME, development tools |
oddship-ux303 |
Server | Laptop running as server, WiFi enabled |
oddship-beagle |
Server | Basic server configuration |
oddship-web |
Server | Hetzner VPS - Caddy web server with Cloudflare DNS-01 |
- Modular Design: Reusable modules for easy configuration composition
- Flakes: Reproducible builds with locked dependencies
- Disko: Declarative disk partitioning
- Agenix: Encrypted secrets management
- Home-Manager: User environment management
- Printing: CUPS with Epson driver support and auto-discovery
- Just: Simple task automation
common.nix- Base system configurationboot.nix- Bootloader setupnetworking.nix- Network configuration
gnome.nix- GNOME desktop environment
openssh.nix- SSH serverdesktop.nix- Desktop services (audio, VPN, sync, printing)development.nix- Development tools (Docker, Steam)
desktop.nix- Desktop applicationsdevelopment.nix- Development tools
See modules/README.md for detailed documentation.
User-specific configurations including:
- Shell environment (zsh with oh-my-zsh)
- Terminal emulators (Kitty, Ghostty)
- Development tools (Neovim, Git)
- GNOME customization
See home/README.md for details.
This repo supports automated infrastructure provisioning with OpenTofu (Terraform fork) for cloud servers.
# Enter development shell (provides tofu, just, jq, agenix)
nix develop1. Encrypt API Tokens (one-time setup):
cd secrets
# Hetzner API token (64 characters)
echo -n "your-64-char-hetzner-token" | agenix -e hetzner-api-token.age
# Cloudflare API token (40 characters)
echo -n "your-cloudflare-token" | agenix -e cloudflare-api-token.age2. Provision Infrastructure:
# Initialize OpenTofu
just tofu-init
# Review planned changes
just tofu-plan
# Apply infrastructure (creates VPS, DNS records, firewall)
just tofu-apply
# Get server IP
just tofu-ip3. Bootstrap NixOS (automated - gets IP from terraform):
# Install NixOS on the server (wipes existing OS!)
just bootstrap oddship-webThis will:
- Auto-fetch server IP from terraform outputs
- Ask for confirmation before wiping
- Install NixOS via nixos-anywhere
- Reboot into NixOS
4. Deploy Updates (after initial bootstrap):
# Deploy configuration changes
just deploy oddship-web1. Add to terraform/main.tf:
resource "hcloud_server" "api" {
name = "oddship-api"
server_type = "cpx11"
# ... rest of config ...
}
output "api_server_ip" {
value = hcloud_server.api.ipv4_address
}2. Add to flake.nix:
nixosConfigurations."oddship-api" = nixpkgs.lib.nixosSystem {
# ... configuration ...
};3. Deploy:
just tofu-apply # Provision VPS
just bootstrap oddship-api # Install NixOS (auto-gets IP!)If you have a server IP but no terraform:
# Bootstrap with manual IP
just bootstrap-manual oddship-web root@167.235.62.179
# Deploy updates with manual IP
just deploy-manual oddship-web rhnvrm@167.235.62.179# Destroy all infrastructure (CAREFUL!)
just tofu-destroy- Boot NixOS installer
- Partition disks according to your disko configuration
- Clone this repository:
git clone https://github.com/oddship/nix-system.git cd nix-system - Install:
sudo nixos-install --flake .#hostname
# Deploy to remote host
just deploy hostname root@ip-address
# Or use nixos-anywhere for fresh installation
nix run github:nix-community/nixos-anywhere -- --flake .#hostname --target-host root@ip-addressSecrets are managed using agenix:
# Edit a secret
agenix -e secrets/secret-name.age
# Reference in configuration
config.age.secrets.secret-name.path# Check configuration for errors
just check
# Show diff before switching
just diff
# Rollback to previous generation
just rollback
# Garbage collect old generations
just clean# Open Nix REPL with flake
just repl
# Search for packages
just search package-name
# Format all Nix files
just fmt# Print a file
lp filename
# Check print queue
lpstat -o
# Open CUPS web interface
firefox http://localhost:631
# GUI printer configuration
system-config-printer# Create a new module
just new-module category name-
Create host directory:
mkdir -p hosts/desktop/newhostname
-
Add configuration files:
configuration.nix- Main system confighardware-configuration.nix- Hardware-specific configdisko-config.nix- Disk layout (if using disko)
-
Add to
flake.nix:nixosConfigurations."newhostname" = nixpkgs.lib.nixosSystem { inherit system; specialArgs = { inherit inputs; }; modules = commonModules ++ [ ./hosts/desktop/newhostname/configuration.nix ]; };
-
Import relevant modules in the host configuration
- Keep modules focused and single-purpose
- Use
mkDefaultfor overridable defaults - Document module options and usage
- Test changes with
just checkbefore committing
This configuration is personal but feel free to take inspiration from it.