Add initial Bitpoll Nix flake and example configuration
This commit is contained in:
		
							parent
							
								
									1b58a0ded8
								
							
						
					
					
						commit
						8de81ea2ab
					
				
					 4 changed files with 631 additions and 0 deletions
				
			
		
							
								
								
									
										186
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,186 @@
 | 
			
		|||
# Bitpoll Nix Flake
 | 
			
		||||
 | 
			
		||||
This repository provides a Nix flake for [Bitpoll](https://github.com/fsinfuhh/Bitpoll), a web application for scheduling meetings and general polling.
 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
 | 
			
		||||
- ✅ **Nix Flake**: Uses NixOS 25.05 with pinned dependencies
 | 
			
		||||
- ✅ **Bitpoll Package**: Builds Bitpoll from the current master commit (4a3e6a5)
 | 
			
		||||
- ✅ **NixOS Service**: Complete systemd service configuration
 | 
			
		||||
- ✅ **Data Storage**: All data stored in `/var/lib/bitpoll` as requested
 | 
			
		||||
- ✅ **Security**: Proper user isolation and security hardening
 | 
			
		||||
- ✅ **Cross-platform**: Works on Linux and macOS
 | 
			
		||||
 | 
			
		||||
## Quick Start
 | 
			
		||||
 | 
			
		||||
### 1. Using the Package Directly
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# Run Bitpoll development server
 | 
			
		||||
nix run git+https://git.s1q.dev/phg/bitpoll-nix
 | 
			
		||||
 | 
			
		||||
# Run management commands
 | 
			
		||||
nix run git+https://git.s1q.dev/phg/bitpoll-nix#bitpoll-manage -- migrate
 | 
			
		||||
nix run git+https://git.s1q.dev/phg/bitpoll-nix#bitpoll-manage -- createsuperuser
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 2. Using as a NixOS Service
 | 
			
		||||
 | 
			
		||||
Add this flake to your NixOS configuration:
 | 
			
		||||
 | 
			
		||||
```nix
 | 
			
		||||
{
 | 
			
		||||
  inputs = {
 | 
			
		||||
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
 | 
			
		||||
    bitpoll.url = "git+https://git.s1q.dev/phg/bitpoll-nix";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  outputs = { self, nixpkgs, bitpoll }: {
 | 
			
		||||
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
 | 
			
		||||
      system = "x86_64-linux";
 | 
			
		||||
      modules = [
 | 
			
		||||
        bitpoll.nixosModules.default
 | 
			
		||||
        {
 | 
			
		||||
          services.bitpoll = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            port = 8080;
 | 
			
		||||
            host = "0.0.0.0";
 | 
			
		||||
            allowedHosts = [ 
 | 
			
		||||
              "bitpoll.example.com" 
 | 
			
		||||
              "localhost" 
 | 
			
		||||
              "127.0.0.1" 
 | 
			
		||||
            ];
 | 
			
		||||
          };
 | 
			
		||||
          
 | 
			
		||||
          # Open firewall port
 | 
			
		||||
          networking.firewall.allowedTCPPorts = [ 8080 ];
 | 
			
		||||
        }
 | 
			
		||||
      ];
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then rebuild your system:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
sudo nixos-rebuild switch --flake .#myhost
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 3. Development Environment
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# Enter development shell
 | 
			
		||||
nix develop git+https://git.s1q.dev/phg/bitpoll-nix
 | 
			
		||||
 | 
			
		||||
# Or clone and develop locally
 | 
			
		||||
git clone https://git.s1q.dev/phg/bitpoll-nix
 | 
			
		||||
cd bitpoll-nix
 | 
			
		||||
nix develop
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Configuration Options
 | 
			
		||||
 | 
			
		||||
The NixOS service provides the following configuration options:
 | 
			
		||||
 | 
			
		||||
```nix
 | 
			
		||||
services.bitpoll = {
 | 
			
		||||
  enable = true;                    # Enable the service
 | 
			
		||||
  port = 8000;                      # Port to listen on (default: 8000)
 | 
			
		||||
  host = "127.0.0.1";              # Host to bind to (default: 127.0.0.1)
 | 
			
		||||
  dataDir = "/var/lib/bitpoll";     # Data directory (default: /var/lib/bitpoll)
 | 
			
		||||
  secretKeyFile = "/path/to/key";   # Optional: File containing Django secret key
 | 
			
		||||
  allowedHosts = [ "localhost" ];   # List of allowed hosts
 | 
			
		||||
  extraSettings = "";               # Extra Django settings
 | 
			
		||||
};
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Data Storage
 | 
			
		||||
 | 
			
		||||
All Bitpoll data is stored in `/var/lib/bitpoll` as requested:
 | 
			
		||||
 | 
			
		||||
- `/var/lib/bitpoll/db.sqlite3` - SQLite database
 | 
			
		||||
- `/var/lib/bitpoll/static/` - Static files (CSS, JS, images)
 | 
			
		||||
- `/var/lib/bitpoll/media/` - User uploaded files
 | 
			
		||||
 | 
			
		||||
## Security
 | 
			
		||||
 | 
			
		||||
The service runs with proper security hardening:
 | 
			
		||||
 | 
			
		||||
- Dedicated `bitpoll` user and group
 | 
			
		||||
- Restricted filesystem access
 | 
			
		||||
- No new privileges
 | 
			
		||||
- Private temporary directories
 | 
			
		||||
- Protected system directories
 | 
			
		||||
 | 
			
		||||
## Production Deployment
 | 
			
		||||
 | 
			
		||||
For production use, consider:
 | 
			
		||||
 | 
			
		||||
1. **Use a secret key file**:
 | 
			
		||||
   ```nix
 | 
			
		||||
   services.bitpoll.secretKeyFile = "/etc/bitpoll/secret-key";
 | 
			
		||||
   ```
 | 
			
		||||
 | 
			
		||||
2. **Configure allowed hosts properly**:
 | 
			
		||||
   ```nix
 | 
			
		||||
   services.bitpoll.allowedHosts = [ "bitpoll.yourdomain.com" ];
 | 
			
		||||
   ```
 | 
			
		||||
 | 
			
		||||
3. **Use a reverse proxy** (nginx, traefik, etc.) for HTTPS termination
 | 
			
		||||
 | 
			
		||||
4. **Set up backups** for `/var/lib/bitpoll/`
 | 
			
		||||
 | 
			
		||||
## Example Complete Configuration
 | 
			
		||||
 | 
			
		||||
See `example-configuration.nix` for a complete NixOS configuration example.
 | 
			
		||||
 | 
			
		||||
## Building and Testing
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# Check flake
 | 
			
		||||
nix flake check
 | 
			
		||||
 | 
			
		||||
# Build package
 | 
			
		||||
nix build
 | 
			
		||||
 | 
			
		||||
# Test the service
 | 
			
		||||
nix run .#bitpoll-manage -- check
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Dependencies
 | 
			
		||||
 | 
			
		||||
This flake includes all necessary dependencies:
 | 
			
		||||
 | 
			
		||||
- Django and related packages
 | 
			
		||||
- Calendar handling (caldav, icalendar)
 | 
			
		||||
- Database support (SQLite by default, PostgreSQL available)
 | 
			
		||||
- Security libraries (cryptography)
 | 
			
		||||
- Markup processing (markdown, bleach)
 | 
			
		||||
- LDAP support (optional)
 | 
			
		||||
 | 
			
		||||
## Version Information
 | 
			
		||||
 | 
			
		||||
- **NixOS Version**: 25.05
 | 
			
		||||
- **Bitpoll Version**: master (commit 4a3e6a5)
 | 
			
		||||
- **Python Version**: 3.x (from nixpkgs)
 | 
			
		||||
- **Django Version**: Latest from nixpkgs
 | 
			
		||||
 | 
			
		||||
## Contributing
 | 
			
		||||
 | 
			
		||||
1. Fork this repository
 | 
			
		||||
2. Make your changes
 | 
			
		||||
3. Test with `nix flake check`
 | 
			
		||||
4. Submit a pull request
 | 
			
		||||
 | 
			
		||||
## License
 | 
			
		||||
 | 
			
		||||
This flake is provided under the same license as Bitpoll (GPL-3.0).
 | 
			
		||||
 | 
			
		||||
## Support
 | 
			
		||||
 | 
			
		||||
For issues with:
 | 
			
		||||
 | 
			
		||||
- **This flake**: Open an issue at [this repository](https://git.s1q.dev/phg/bitpoll-nix)
 | 
			
		||||
- **Bitpoll itself**: See the [upstream repository](https://github.com/fsinfuhh/Bitpoll)
 | 
			
		||||
- **NixOS**: See the [NixOS manual](https://nixos.org/manual/nixos/stable/)
 | 
			
		||||
							
								
								
									
										53
									
								
								example-configuration.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								example-configuration.nix
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
# Example NixOS configuration using the Bitpoll flake
 | 
			
		||||
{ config, pkgs, ... }:
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
  imports = [
 | 
			
		||||
    # Include your hardware configuration
 | 
			
		||||
    ./hardware-configuration.nix
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  # Enable flakes
 | 
			
		||||
  nix.settings.experimental-features = [ "nix-command" "flakes" ];
 | 
			
		||||
 | 
			
		||||
  # Basic system configuration
 | 
			
		||||
  boot.loader.systemd-boot.enable = true;
 | 
			
		||||
  boot.loader.efi.canTouchEfiVariables = true;
 | 
			
		||||
 | 
			
		||||
  networking.hostName = "bitpoll-server";
 | 
			
		||||
  networking.firewall.allowedTCPPorts = [ 8080 22 ];
 | 
			
		||||
 | 
			
		||||
  # Enable SSH for remote management
 | 
			
		||||
  services.openssh.enable = true;
 | 
			
		||||
 | 
			
		||||
  # Bitpoll service configuration
 | 
			
		||||
  services.bitpoll = {
 | 
			
		||||
    enable = true;
 | 
			
		||||
    port = 8080;
 | 
			
		||||
    host = "0.0.0.0";  # Listen on all interfaces
 | 
			
		||||
    allowedHosts = [ 
 | 
			
		||||
      "bitpoll.example.com" 
 | 
			
		||||
      "localhost" 
 | 
			
		||||
      "127.0.0.1"
 | 
			
		||||
    ];
 | 
			
		||||
    
 | 
			
		||||
    # Optional: Use a secret key file for better security
 | 
			
		||||
    # secretKeyFile = "/etc/bitpoll/secret-key";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  # Create a user for administration
 | 
			
		||||
  users.users.admin = {
 | 
			
		||||
    isNormalUser = true;
 | 
			
		||||
    extraGroups = [ "wheel" ]; # Enable 'sudo' for the admin user
 | 
			
		||||
    openssh.authorizedKeys.keys = [
 | 
			
		||||
      # Add your SSH public key here
 | 
			
		||||
      # "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC..."
 | 
			
		||||
    ];
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  # This value determines the NixOS release from which the default
 | 
			
		||||
  # settings for stateful data, like file locations and database versions
 | 
			
		||||
  # on your system were taken. It's perfectly fine and recommended to leave
 | 
			
		||||
  # this value at the release version of the first install of this system.
 | 
			
		||||
  system.stateVersion = "25.05";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								flake.lock
									
										
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								flake.lock
									
										
									
										generated
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,61 @@
 | 
			
		|||
{
 | 
			
		||||
  "nodes": {
 | 
			
		||||
    "flake-utils": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1731533236,
 | 
			
		||||
        "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1751211869,
 | 
			
		||||
        "narHash": "sha256-1Cu92i1KSPbhPCKxoiVG5qnoRiKTgR5CcGSRyLpOd7Y=",
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "b43c397f6c213918d6cfe6e3550abfe79b5d1c51",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "ref": "nixos-25.05",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "root": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-utils": "flake-utils",
 | 
			
		||||
        "nixpkgs": "nixpkgs"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "systems": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681028828,
 | 
			
		||||
        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "root": "root",
 | 
			
		||||
  "version": 7
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										331
									
								
								flake.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								flake.nix
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,331 @@
 | 
			
		|||
{
 | 
			
		||||
  description = "Bitpoll - A web application for scheduling meetings and general polling";
 | 
			
		||||
 | 
			
		||||
  inputs = {
 | 
			
		||||
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
 | 
			
		||||
    flake-utils.url = "github:numtide/flake-utils";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  outputs = { self, nixpkgs, flake-utils }:
 | 
			
		||||
    flake-utils.lib.eachDefaultSystem (system:
 | 
			
		||||
      let
 | 
			
		||||
        pkgs = nixpkgs.legacyPackages.${system};
 | 
			
		||||
        
 | 
			
		||||
        # Pin to current master commit
 | 
			
		||||
        bitpollSrc = pkgs.fetchFromGitHub {
 | 
			
		||||
          owner = "fsinfuhh";
 | 
			
		||||
          repo = "Bitpoll";
 | 
			
		||||
          rev = "4a3e6a5e3500308a428a6c7644f50d423adca6fc";
 | 
			
		||||
          sha256 = "sha256-R4OwQdSJu9+EAlkhYOEe2ZOrS9oOA1ifg/iY6uzYSpE=";
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        # Create settings_local.py for production
 | 
			
		||||
        settingsLocal = pkgs.writeText "settings_local.py" ''
 | 
			
		||||
          import os
 | 
			
		||||
          import secrets
 | 
			
		||||
          
 | 
			
		||||
          # Generate secret key if not provided via environment
 | 
			
		||||
          SECRET_KEY = os.environ.get('BITPOLL_SECRET_KEY', secrets.token_urlsafe(50))
 | 
			
		||||
          
 | 
			
		||||
          # Generate field encryption key if not provided via environment  
 | 
			
		||||
          FIELD_ENCRYPTION_KEY = os.environ.get('BITPOLL_FIELD_ENCRYPTION_KEY', secrets.token_urlsafe(32) + "=")
 | 
			
		||||
          
 | 
			
		||||
          DEBUG = False
 | 
			
		||||
          
 | 
			
		||||
          ALLOWED_HOSTS = ['*']  # Configure appropriately for production
 | 
			
		||||
          
 | 
			
		||||
          # SQLite database configuration
 | 
			
		||||
          DATABASES = {
 | 
			
		||||
              'default': {
 | 
			
		||||
                  'ENGINE': 'django.db.backends.sqlite3',
 | 
			
		||||
                  'NAME': '/var/lib/bitpoll/db.sqlite3',
 | 
			
		||||
              }
 | 
			
		||||
          }
 | 
			
		||||
          
 | 
			
		||||
          # Static files
 | 
			
		||||
          STATIC_ROOT = '/var/lib/bitpoll/static'
 | 
			
		||||
          
 | 
			
		||||
          # Media files
 | 
			
		||||
          MEDIA_ROOT = '/var/lib/bitpoll/media'
 | 
			
		||||
          
 | 
			
		||||
          # Locale
 | 
			
		||||
          LANGUAGE_CODE = 'en-us'
 | 
			
		||||
          TIME_ZONE = 'UTC'
 | 
			
		||||
          
 | 
			
		||||
          # Site configuration
 | 
			
		||||
          SITE_NAME = 'Bitpoll'
 | 
			
		||||
          
 | 
			
		||||
          # Additional apps
 | 
			
		||||
          INSTALLED_APPS_LOCAL = []
 | 
			
		||||
          MIDDLEWARE_LOCAL = []
 | 
			
		||||
          PIPELINE_LOCAL = {}
 | 
			
		||||
          
 | 
			
		||||
          # Registration enabled by default
 | 
			
		||||
          REGISTER_ENABLED = True
 | 
			
		||||
          GROUP_MANAGEMENT = True
 | 
			
		||||
        '';
 | 
			
		||||
 | 
			
		||||
        bitpoll = pkgs.python3Packages.buildPythonApplication rec {
 | 
			
		||||
          pname = "bitpoll";
 | 
			
		||||
          version = "master-${builtins.substring 0 7 bitpollSrc.rev}";
 | 
			
		||||
          
 | 
			
		||||
          src = bitpollSrc;
 | 
			
		||||
          
 | 
			
		||||
          format = "other";
 | 
			
		||||
          
 | 
			
		||||
          propagatedBuildInputs = with pkgs.python3Packages; [
 | 
			
		||||
            # Core Django dependencies
 | 
			
		||||
            django
 | 
			
		||||
            
 | 
			
		||||
            # Calendar and date handling
 | 
			
		||||
            caldav
 | 
			
		||||
            icalendar
 | 
			
		||||
            python-dateutil
 | 
			
		||||
            pytz
 | 
			
		||||
            vobject
 | 
			
		||||
            
 | 
			
		||||
            # Crypto and security
 | 
			
		||||
            cryptography
 | 
			
		||||
            
 | 
			
		||||
            # Web and HTTP
 | 
			
		||||
            requests
 | 
			
		||||
            
 | 
			
		||||
            # Markup and styling
 | 
			
		||||
            markdown
 | 
			
		||||
            bleach
 | 
			
		||||
            
 | 
			
		||||
            # Data handling
 | 
			
		||||
            pydantic
 | 
			
		||||
            
 | 
			
		||||
            # Database
 | 
			
		||||
            psycopg2
 | 
			
		||||
            
 | 
			
		||||
            # Utilities
 | 
			
		||||
            six
 | 
			
		||||
            lxml
 | 
			
		||||
            
 | 
			
		||||
            # Additional dependencies
 | 
			
		||||
            setuptools
 | 
			
		||||
            wheel
 | 
			
		||||
          ] ++ [
 | 
			
		||||
            # System dependencies
 | 
			
		||||
            pkgs.gettext
 | 
			
		||||
          ];
 | 
			
		||||
 | 
			
		||||
          nativeBuildInputs = with pkgs; [
 | 
			
		||||
            gettext
 | 
			
		||||
          ];
 | 
			
		||||
 | 
			
		||||
          buildInputs = with pkgs; [
 | 
			
		||||
            # LDAP support
 | 
			
		||||
            openldap
 | 
			
		||||
            cyrus_sasl
 | 
			
		||||
          ];
 | 
			
		||||
 | 
			
		||||
          # Don't run tests during build
 | 
			
		||||
          doCheck = false;
 | 
			
		||||
 | 
			
		||||
          preBuild = ''
 | 
			
		||||
            # Copy our settings file
 | 
			
		||||
            cp ${settingsLocal} bitpoll/settings_local.py
 | 
			
		||||
          '';
 | 
			
		||||
 | 
			
		||||
          installPhase = ''
 | 
			
		||||
            runHook preInstall
 | 
			
		||||
            
 | 
			
		||||
            mkdir -p $out/share/bitpoll
 | 
			
		||||
            cp -r . $out/share/bitpoll/
 | 
			
		||||
            
 | 
			
		||||
            # Create wrapper script
 | 
			
		||||
            mkdir -p $out/bin
 | 
			
		||||
            cat > $out/bin/bitpoll-manage << EOF
 | 
			
		||||
            #!/bin/sh
 | 
			
		||||
            cd $out/share/bitpoll
 | 
			
		||||
            export PYTHONPATH=$out/share/bitpoll:\$PYTHONPATH
 | 
			
		||||
            exec ${pkgs.python3}/bin/python manage.py "\$@"
 | 
			
		||||
            EOF
 | 
			
		||||
            chmod +x $out/bin/bitpoll-manage
 | 
			
		||||
            
 | 
			
		||||
            # Create server script
 | 
			
		||||
            cat > $out/bin/bitpoll-server << EOF
 | 
			
		||||
            #!/bin/sh
 | 
			
		||||
            cd $out/share/bitpoll
 | 
			
		||||
            export PYTHONPATH=$out/share/bitpoll:\$PYTHONPATH
 | 
			
		||||
            exec ${pkgs.python3}/bin/python manage.py runserver "\$@"
 | 
			
		||||
            EOF
 | 
			
		||||
            chmod +x $out/bin/bitpoll-server
 | 
			
		||||
            
 | 
			
		||||
            runHook postInstall
 | 
			
		||||
          '';
 | 
			
		||||
 | 
			
		||||
          meta = with pkgs.lib; {
 | 
			
		||||
            description = "A web application for scheduling meetings and general polling";
 | 
			
		||||
            homepage = "https://github.com/fsinfuhh/Bitpoll";
 | 
			
		||||
            license = licenses.gpl3Only;
 | 
			
		||||
            maintainers = [ ];
 | 
			
		||||
            platforms = platforms.unix;
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
      in {
 | 
			
		||||
        packages = {
 | 
			
		||||
          default = bitpoll;
 | 
			
		||||
          bitpoll = bitpoll;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        apps = {
 | 
			
		||||
          default = {
 | 
			
		||||
            type = "app";
 | 
			
		||||
            program = "${bitpoll}/bin/bitpoll-server";
 | 
			
		||||
            meta = {
 | 
			
		||||
              description = "Run Bitpoll development server";
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
          bitpoll-manage = {
 | 
			
		||||
            type = "app";
 | 
			
		||||
            program = "${bitpoll}/bin/bitpoll-manage";
 | 
			
		||||
            meta = {
 | 
			
		||||
              description = "Run Bitpoll management commands";
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        devShells.default = pkgs.mkShell {
 | 
			
		||||
          buildInputs = with pkgs; [
 | 
			
		||||
            python3
 | 
			
		||||
            python3Packages.pip
 | 
			
		||||
            python3Packages.virtualenv
 | 
			
		||||
            gettext
 | 
			
		||||
            openldap
 | 
			
		||||
            cyrus_sasl
 | 
			
		||||
          ];
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
    ) // {
 | 
			
		||||
      nixosModules.default = self.nixosModules.bitpoll;
 | 
			
		||||
      
 | 
			
		||||
      nixosModules.bitpoll = { config, lib, pkgs, ... }:
 | 
			
		||||
        with lib;
 | 
			
		||||
        let
 | 
			
		||||
          cfg = config.services.bitpoll;
 | 
			
		||||
          bitpollPackage = self.packages.${pkgs.system}.bitpoll;
 | 
			
		||||
        in {
 | 
			
		||||
          options.services.bitpoll = {
 | 
			
		||||
            enable = mkEnableOption "Bitpoll service";
 | 
			
		||||
 | 
			
		||||
            package = mkOption {
 | 
			
		||||
              type = types.package;
 | 
			
		||||
              default = bitpollPackage;
 | 
			
		||||
              description = "The Bitpoll package to use";
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            port = mkOption {
 | 
			
		||||
              type = types.port;
 | 
			
		||||
              default = 8000;
 | 
			
		||||
              description = "Port to listen on";
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            host = mkOption {
 | 
			
		||||
              type = types.str;
 | 
			
		||||
              default = "127.0.0.1";
 | 
			
		||||
              description = "Host to bind to";
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            dataDir = mkOption {
 | 
			
		||||
              type = types.path;
 | 
			
		||||
              default = "/var/lib/bitpoll";
 | 
			
		||||
              description = "Directory to store Bitpoll data";
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            secretKeyFile = mkOption {
 | 
			
		||||
              type = types.nullOr types.path;
 | 
			
		||||
              default = null;
 | 
			
		||||
              description = "File containing the Django secret key";
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            allowedHosts = mkOption {
 | 
			
		||||
              type = types.listOf types.str;
 | 
			
		||||
              default = [ "localhost" "127.0.0.1" ];
 | 
			
		||||
              description = "List of allowed hosts";
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            extraSettings = mkOption {
 | 
			
		||||
              type = types.lines;
 | 
			
		||||
              default = "";
 | 
			
		||||
              description = "Extra settings to append to settings_local.py";
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          config = mkIf cfg.enable {
 | 
			
		||||
            users.users.bitpoll = {
 | 
			
		||||
              isSystemUser = true;
 | 
			
		||||
              group = "bitpoll";
 | 
			
		||||
              home = cfg.dataDir;
 | 
			
		||||
              createHome = true;
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            users.groups.bitpoll = {};
 | 
			
		||||
 | 
			
		||||
            systemd.services.bitpoll = {
 | 
			
		||||
              description = "Bitpoll web application";
 | 
			
		||||
              wantedBy = [ "multi-user.target" ];
 | 
			
		||||
              after = [ "network.target" ];
 | 
			
		||||
 | 
			
		||||
              environment = {
 | 
			
		||||
                PYTHONPATH = "${cfg.package}/share/bitpoll";
 | 
			
		||||
                BITPOLL_DATA_DIR = cfg.dataDir;
 | 
			
		||||
              } // optionalAttrs (cfg.secretKeyFile != null) {
 | 
			
		||||
                BITPOLL_SECRET_KEY_FILE = cfg.secretKeyFile;
 | 
			
		||||
              };
 | 
			
		||||
 | 
			
		||||
              preStart = ''
 | 
			
		||||
                # Ensure data directory exists and has correct permissions
 | 
			
		||||
                mkdir -p ${cfg.dataDir}/{static,media}
 | 
			
		||||
                chown -R bitpoll:bitpoll ${cfg.dataDir}
 | 
			
		||||
                chmod 750 ${cfg.dataDir}
 | 
			
		||||
 | 
			
		||||
                # Create runtime settings if secret key file is provided
 | 
			
		||||
                if [ -n "''${BITPOLL_SECRET_KEY_FILE:-}" ] && [ -f "$BITPOLL_SECRET_KEY_FILE" ]; then
 | 
			
		||||
                  export BITPOLL_SECRET_KEY="$(cat "$BITPOLL_SECRET_KEY_FILE")"
 | 
			
		||||
                fi
 | 
			
		||||
 | 
			
		||||
                # Run database migrations
 | 
			
		||||
                cd ${cfg.package}/share/bitpoll
 | 
			
		||||
                ${cfg.package}/bin/bitpoll-manage migrate --noinput
 | 
			
		||||
 | 
			
		||||
                # Collect static files
 | 
			
		||||
                ${cfg.package}/bin/bitpoll-manage collectstatic --noinput --clear
 | 
			
		||||
 | 
			
		||||
                # Compile messages
 | 
			
		||||
                ${cfg.package}/bin/bitpoll-manage compilemessages
 | 
			
		||||
              '';
 | 
			
		||||
 | 
			
		||||
              serviceConfig = {
 | 
			
		||||
                Type = "exec";
 | 
			
		||||
                User = "bitpoll";
 | 
			
		||||
                Group = "bitpoll";
 | 
			
		||||
                WorkingDirectory = "${cfg.package}/share/bitpoll";
 | 
			
		||||
                ExecStart = "${cfg.package}/bin/bitpoll-server ${cfg.host}:${toString cfg.port}";
 | 
			
		||||
                Restart = "always";
 | 
			
		||||
                RestartSec = "10s";
 | 
			
		||||
 | 
			
		||||
                # Security settings
 | 
			
		||||
                NoNewPrivileges = true;
 | 
			
		||||
                PrivateTmp = true;
 | 
			
		||||
                ProtectSystem = "strict";
 | 
			
		||||
                ProtectHome = true;
 | 
			
		||||
                ReadWritePaths = [ cfg.dataDir ];
 | 
			
		||||
                PrivateDevices = true;
 | 
			
		||||
                ProtectKernelTunables = true;
 | 
			
		||||
                ProtectKernelModules = true;
 | 
			
		||||
                ProtectControlGroups = true;
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            # Open firewall port if needed
 | 
			
		||||
            # networking.firewall.allowedTCPPorts = [ cfg.port ];
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue