System Architecture
This document describes the architecture and organization of the NixOS dotfiles configuration.
Overview
This is a NixOS flake-based configuration for a homelab server providing: - Static website hosting across multiple domains - Documentation hosting - Monitoring and system management - Secure remote access via SSH and Tailscale - Tor relay services
Repository Structure
dotfiles/
├── flake.nix # Flake entry point and outputs
├── flake.lock # Locked dependency versions
├── Makefile # Build and deployment shortcuts
│
├── hosts/ # Host-specific configurations
│ └── homelab/
│ ├── default.nix # Main host configuration
│ ├── hardware.nix # Hardware-specific settings
│ └── services.nix # Host-specific services (nginx virtualhosts)
│
├── modules/ # Reusable NixOS modules
│ ├── system/ # System-level modules
│ │ ├── packages.nix # System-wide packages
│ │ ├── shell.nix # Shell configuration (zsh, bash)
│ │ ├── security.nix # SSH and security settings
│ │ ├── monitoring.nix # Monitoring services (netdata)
│ │ └── assertions.nix # Configuration validation
│ │
│ ├── services/ # Service modules
│ │ ├── nginx.nix # Nginx base configuration
│ │ ├── tailscale.nix # Tailscale VPN
│ │ └── tor.nix # Tor relay
│ │
│ ├── users/ # User account modules
│ │ ├── root.nix # Root user configuration
│ │ ├── cypl0x.nix # Primary user
│ │ └── wap.nix # Work account
│ │
│ └── web/ # Web-related helpers
│ └── nginx-helpers.nix # Reusable nginx functions
│
├── home/ # Home Manager configurations
│ ├── common.nix # Shared home-manager config
│ ├── cypl0x.nix # User-specific config
│ ├── wap.nix # Work user config
│ ├── root.nix # Root user home config
│ └── shell/ # Shell configurations
│ ├── zsh/ # Zsh specific files
│ ├── starship.toml # Starship prompt config
│ └── tmux.conf # Tmux configuration
│
├── web/ # Web content and builders
│ ├── docs.nix # Documentation builder
│ ├── static/ # Static website files
│ └── docs/ # Documentation markdown
│
├── ssh-keys/ # SSH public keys
│ └── homelab.pub # Server SSH key
│
└── docs/ # Project documentation
├── DEPLOYMENT.md # Deployment guide
├── ARCHITECTURE.md # This file
└── NGINX.md # Nginx documentation
Module Organization
System Modules
(modules/system/)
Purpose: System-level configuration that affects all users
- packages.nix: Defines system-wide packages (CLI tools, development tools, AI tools)
- shell.nix: Configures default shell (zsh) and shell environment
- security.nix: SSH daemon configuration, security policies
- monitoring.nix: System monitoring services (netdata)
- assertions.nix: Validates configuration correctness at build time
Service Modules
(modules/services/)
Purpose: Individual service configurations
- nginx.nix: Base nginx configuration with security headers, ACME setup
- tailscale.nix: Tailscale VPN for secure remote access
- tor.nix: Tor relay configuration
User Modules
(modules/users/)
Purpose: User account definitions
- Defines user accounts with home directories
- Configures SSH authorized keys
- Sets user-specific settings
Web Modules
(modules/web/)
Purpose: Web-related helper functions and configurations
- nginx-helpers.nix: Provides reusable functions for
nginx configuration
mkVirtualHost: Creates virtualhost with common settingsmkMultiDomainVirtualHosts: Generates virtualhosts for multiple TLDs- Security header templates (strict and permissive CSP)
- Caching configuration helpers
Home Manager Integration
Home Manager manages user-specific configurations:
Common Configuration
(home/common.nix)
Shared across all users: - Git configuration - Shell setup (zsh, starship, tmux) - Editor preferences - Shell aliases and functions
User-Specific Configuration
Each user imports common.nix and overrides as needed: -
cypl0x.nix: Primary user with personal git config -
wap.nix: Work account with work email -
root.nix: Root user with minimal config
Data Flow
Build Process
flake.nix
│
├─→ nixosConfigurations.homelab
│ │
│ ├─→ hosts/homelab/default.nix
│ │ │
│ │ ├─→ System Modules (modules/system/*)
│ │ ├─→ Service Modules (modules/services/*)
│ │ ├─→ User Modules (modules/users/*)
│ │ └─→ hosts/homelab/services.nix
│ │
│ └─→ home-manager.nixosModules.home-manager
│ │
│ ├─→ home/cypl0x.nix
│ ├─→ home/wap.nix
│ └─→ home/root.nix
│
└─→ Checks (statix, deadnix, formatting)
Nginx Configuration Flow
modules/services/nginx.nix (base config + security headers)
│
└─→ hosts/homelab/services.nix
│
├─→ imports modules/web/nginx-helpers.nix
│
└─→ generates virtualHosts using:
├─→ mkMultiDomainVirtualHosts (main domains)
└─→ mkMultiDomainVirtualHosts (docs subdomains)
Design Patterns
1. Module Composition
Modules are composed hierarchically: - Base configuration in
modules/ - Host-specific overrides in hosts/ -
User-specific in home/
2. DRY (Don’t Repeat Yourself)
Using helper functions to avoid duplication: - Nginx helpers generate multiple similar virtualhosts - Common home-manager config shared across users - Reusable security header templates
3. Separation of Concerns
Each module has a single responsibility: - Services configured independently - System and user configuration separated - Web content separate from web server config
4. Configuration Validation
Assertions module validates: - Required services are configured correctly - Dependencies are met (e.g., nginx → ACME) - Security best practices are followed
Key Technologies
NixOS Flakes
- Declarative: Entire system described in Nix code
- Reproducible: Locked dependencies ensure consistent builds
- Atomic: Updates are atomic, easy to rollback
- Composable: Modular design allows easy reuse
Home Manager
- User Environment: Manages dotfiles and user packages
- Unified Configuration: Same language (Nix) for system and user config
- Version Control: User config tracked in git
Services
- Nginx: High-performance web server with automatic SSL
- ACME: Automatic SSL certificate management
- Tailscale: Mesh VPN for secure access
- Netdata: Real-time performance monitoring
- Tor: Privacy-focused relay node
Security Architecture
Layers of Security
- Network Layer
- Firewall with minimal open ports (22, 80, 443, 9001)
- Tailscale for secure remote access
- Application Layer
- Nginx with security headers (CSP, HSTS, etc.)
- Strict Content Security Policy
- SSL/TLS enforcement
- Access Control
- SSH key-only authentication
- Root login restricted
- Separate user accounts
- Monitoring
- Netdata for performance monitoring
- Systemd journal for centralized logging
Security Headers
Applied globally via modules/services/nginx.nix: -
X-Frame-Options: SAMEORIGIN - X-Content-Type-Options: nosniff -
Strict-Transport-Security (HSTS) - Content-Security-Policy (CSP) -
Permissions-Policy - Cross-Origin policies
Extensibility
Adding a New Service
- Create module in
modules/services/newservice.nix - Import in
hosts/homelab/default.nix - Configure service-specific settings
- Add firewall rules if needed
- Add assertions for validation
Example:
# modules/services/newservice.nix
{config, lib, ...}: {
services.newservice = {
enable = true;
# ... configuration
};
networking.firewall.allowedTCPPorts = [ 8080 ];
}Adding a New User
- Create user module in
modules/users/newuser.nix - Create home config in
home/newuser.nix - Import both in
hosts/homelab/default.nixandflake.nix - Add SSH key to
ssh-keys/
Adding a New Domain
Using the nginx helpers:
# In hosts/homelab/services.nix
services.nginx.virtualHosts =
nginxHelpers.mkMultiDomainVirtualHosts {
name = "newdomain";
tlds = ["com" "net" "org"];
root = "/var/www/newdomain";
enableCaching = true;
};Build and Deployment
Local Build
make build # Build configuration
make switch # Build and activate
make vm # Test in virtual machineRemote Deployment
nixos-rebuild switch --flake .#homelab \
--target-host user@host \
--build-host localhostCI/CD Integration
The flake includes checks for: - statix: Nix linting - deadnix: Dead code detection - alejandra: Code formatting
Run via:
nix flake checkPerformance Considerations
Build Optimization
- Flake inputs locked for consistent builds
- Local builds cached by Nix
- Binary cache for common packages
Runtime Optimization
- Nginx caching for static assets (1 year for images, 1 hour for HTML)
- Gzip compression enabled
- Optimized buffer sizes and timeouts
Resource Usage
Typical resource usage: - RAM: ~512MB baseline + services - Disk: ~5GB for NixOS + packages - CPU: Minimal when idle
Monitoring and Observability
Metrics
- Netdata: Real-time performance graphs
- CPU, memory, disk usage
- Network traffic
- Service health
Logs
- journalctl: Centralized logging
- Service-specific logs:
journalctl -u nginx - System logs:
journalctl -xe - Follow mode:
journalctl -f
- Service-specific logs:
Alerting
Currently manual monitoring. Consider adding: - Email notifications for service failures - Disk space alerts - Certificate expiry warnings
Future Improvements
Potential enhancements:
- Automated backups: Implement automatic backup to remote storage
- Secret management: Use agenix or sops-nix for secrets
- CI/CD: Automatic deployment on git push
- Monitoring alerts: Email/webhook notifications
- Additional services: Database, container orchestration
- High availability: Load balancing, failover
- Development environments: Per-project dev shells
Related Documentation
- DEPLOYMENT.md - Deployment procedures
- SECURITY.md - Security policies and procedures
- NGINX.md - Web server configuration
- README.md - Quick start guide