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
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