bitpoll-nix/memory-bank/systemPatterns.md

5.6 KiB

System Patterns: Bitpoll Nix Flake

Architecture Overview

Flake Structure

bitpoll-nix/
├── flake.nix              # Main flake definition
├── flake.lock             # Pinned dependencies
├── example-configuration.nix  # Usage example
└── memory-bank/           # Documentation

Key Components

1. Package Definition (bitpoll)

  • Source: Fetched from GitHub (fsinfuhh/Bitpoll)
  • Build Process: Standard derivation with Python environment
  • Dependencies: Comprehensive Python package set
  • Outputs: Executable scripts and shared files

2. NixOS Module (nixosModules.bitpoll)

  • Service Configuration: Systemd service definition
  • User Management: Dedicated bitpoll user/group
  • Security Hardening: Comprehensive systemd restrictions
  • Data Management: Proper directory permissions

3. Applications (apps)

  • bitpoll-server: Main web server application
  • bitpoll-manage: Django management commands

Technical Patterns

Dependency Management Pattern

# Python environment with comprehensive packages
pythonEnv = pkgs.python3.withPackages (ps: with ps; [
  # Core Django
  django
  # Calendar handling
  caldav icalendar python-dateutil pytz
  # Security
  cryptography django-encrypted-model-fields
  # Additional packages via pip in postInstall
]);

Key Decisions:

  • Use python3.withPackages for core dependencies
  • Install missing packages via pip in postInstall
  • Separate PYTHONPATH management for proper module resolution

Configuration Management Pattern

# Generate settings_local.py at build time
settingsLocal = pkgs.writeText "settings_local.py" ''
  import os
  import secrets
  
  SECRET_KEY = os.environ.get('BITPOLL_SECRET_KEY', secrets.token_urlsafe(50))
  # ... additional settings
'';

Key Decisions:

  • Build-time configuration generation
  • Environment variable override support
  • Secure defaults with runtime key generation
  • Production-ready database and static file paths

Service Architecture Pattern

systemd.services.bitpoll = {
  # Service definition
  preStart = ''
    # Database migrations
    # Static file collection
    # Permission management
  '';
  
  serviceConfig = {
    # Security hardening
    # User isolation
    # Resource restrictions
  };
};

Key Decisions:

  • Automatic database migrations in preStart
  • Comprehensive security hardening
  • Proper data directory management
  • Graceful restart handling

Design Patterns

1. Layered Configuration

  • Build-time: Static configuration in settings_local.py
  • Deploy-time: NixOS module options
  • Runtime: Environment variable overrides

2. Security-First Design

  • Dedicated system user (bitpoll:bitpoll)
  • Restricted filesystem access
  • No new privileges
  • Private temporary directories
  • Protected system directories

3. Data Persistence Strategy

  • Single data directory: /var/lib/bitpoll
  • Subdirectories: static/, media/, database file
  • Proper ownership and permissions
  • Backup-friendly structure

4. Development vs Production

  • Development: nix develop shell with tools
  • Production: Hardened systemd service
  • Testing: Direct package execution
  • Management: Dedicated management commands

Component Relationships

Build Dependencies

flake.nix
├── nixpkgs (NixOS 25.05)
├── flake-utils (cross-platform)
└── bitpoll source (GitHub)

Runtime Dependencies

bitpoll package
├── Python environment
│   ├── Django ecosystem
│   ├── Calendar libraries
│   └── Security libraries
├── System libraries
│   ├── OpenLDAP
│   └── Cyrus SASL
└── Generated configuration

Service Dependencies

systemd service
├── network.target (after)
├── bitpoll package
├── data directory
└── optional secret files

Critical Implementation Paths

1. Package Build Path

  1. Fetch Bitpoll source from GitHub
  2. Create Python environment with core packages
  3. Generate settings_local.py configuration
  4. Install additional packages via pip
  5. Create wrapper scripts with proper PYTHONPATH
  6. Set up executable permissions

2. Service Deployment Path

  1. Create bitpoll user and group
  2. Initialize data directory with proper permissions
  3. Run database migrations
  4. Collect static files
  5. Compile message translations
  6. Start systemd service

3. Configuration Resolution Path

  1. Build-time defaults in settings_local.py
  2. NixOS module option overrides
  3. Environment variable overrides
  4. Secret file content injection

Error Handling Patterns

Build-time Errors

  • Missing dependencies → Comprehensive package list
  • Python path issues → Explicit PYTHONPATH management
  • Permission errors → Proper build environment setup

Runtime Errors

  • Database issues → Automatic migration in preStart
  • Permission errors → Proper user/group setup
  • Configuration errors → Clear error messages and validation

Service Errors

  • Startup failures → Restart policy with backoff
  • Resource exhaustion → systemd resource limits
  • Security violations → Comprehensive hardening rules

Performance Considerations

Build Performance

  • Pinned dependencies for reproducible builds
  • Efficient Python environment construction
  • Minimal rebuild triggers

Runtime Performance

  • Optimized Django settings
  • Proper static file serving
  • Database connection management
  • Resource-constrained systemd service

Memory Management

  • Python environment isolation
  • Proper garbage collection
  • systemd memory limits
  • Efficient static file caching