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