bitpoll-nix/memory-bank/systemPatterns.md

211 lines
5.6 KiB
Markdown

# 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
```nix
# 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
```nix
# 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
```nix
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