nixos-configuration/pkgs/pretix/module.nix
2023-11-08 23:46:49 +00:00

312 lines
9.8 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ config, lib, pkgs, ... }:
let
cfg = config.services.pretix;
name = "pretix";
user = "pretix";
group = "pretix";
bind = {
host = "127.0.0.1";
port = 8000;
};
postgresql = {
database = "pretix";
user = "pretix";
password = "pretix";
};
redisPort = 6379;
urlScheme = if cfg.enableTls then "https" else "http";
url = "${urlScheme}://${cfg.domain}";
toBool = x: if x then "on" else "off";
hstsHeader = if cfg.enableTls then "add_header Strict-Transport-Security \"max-age=31536000; includeSubDomains; preload\" always;" else "";
pythonPackages = pkgs.pretix.passthru.pythonModule.passthru.pkgs;
python = pkgs.pretix.passthru.python;
runCommandArgs = {
# Sets PYTHONPATH in derivation
buildInputs = [
pkgs.pretix
pythonPackages.gunicorn
pythonPackages.celery
];
};
staticRoot = pkgs.pretix-static;
environmentFile = pkgs.runCommand "pretix-environ" runCommandArgs (''
cat > $out <<EOF
DATA_DIR = /var/pretix
DJANGO_SETTINGS_MODULE=pretix_wrapper.settings
PRETIX_CELERY_BACKEND=redis://127.0.0.1:${toString redisPort}/2
PRETIX_CELERY_BROKER=redis://127.0.0.1:${toString redisPort}/1
PRETIX_DATABASE_BACKEND=postgresql
PRETIX_DATABASE_HOST=localhost
PRETIX_DATABASE_NAME=${postgresql.database}
PRETIX_DATABASE_PASSWORD=${postgresql.password}
PRETIX_DATABASE_USER=${postgresql.user}
PRETIX_LOCALE_DEFAULT=${cfg.locale}
PRETIX_LOCALE_TIMEZONE=${cfg.timezone}
PRETIX_PRETIX_INSTANCE_NAME=${cfg.instanceName}
PRETIX_PRETIX_PASSWORD_RESET=${toBool cfg.passwordReset}
PRETIX_PRETIX_REGISTRATION=${toBool cfg.enableRegistration}
PRETIX_PRETIX_URL=${url}
PRETIX_REDIS_LOCATION=redis://127.0.0.1:${toString redisPort}/0
PRETIX_REDIS_SESSIONS=true
PRETIX_STATIC_ROOT=${staticRoot}
'' + (
if cfg.mail.enable then
''
PRETIX_MAIL_FROM=${toString cfg.mail.from}
PRETIX_MAIL_HOST="${cfg.mail.host}"
PRETIX_MAIL_PORT=${toString cfg.mail.port}
'' else ""
) +
''
PYTHONPATH=$PYTHONPATH
EOF
'');
mkTimer = { description, unit, onCalendar }: {
inherit description;
requires = [ "pretix-migrate.service" ];
after = [ "network.target" ];
wantedBy = [ "timers.target" ];
timerConfig = {
Persistent = true;
OnCalendar = onCalendar;
Unit = unit;
};
};
in
{
options.services.pretix = with lib; with lib.types; {
enable = mkEnableOption "Enable pretix ticket shop application";
instanceName = mkOption {
type = types.str;
description = "The name of this installation.";
};
domain = mkOption {
type = types.str;
description = "The installations main domain";
example = "pretix.example.net";
};
extraDomains = mkOption {
type = listOf str;
description = "A list of extra domains";
default = [ ];
};
enableTls = mkEnableOption "Whether to use TLS or not";
enableRegistration = mkEnableOption "Enables or disables the registration of new admin users.";
passwordReset = mkEnableOption "Enables or disables password reset.";
locale = mkOption {
type = types.str;
description = "The systems default locale.";
};
timezone = mkOption {
type = types.str;
description = "The systems default timezone as a pytz name.";
};
secretsFile = mkOption {
type = types.path;
description = "Path to the sops secrets file which stores pretix.cfg settings.";
};
mail = {
enable = mkEnableOption "Enables or disables emailing.";
from = mkOption {
type = types.str;
description = "The email address to set as From header in outgoing emails by the system.";
};
host = mkOption {
type = types.str;
description = "The SMTP Host to connect to.";
default = "localhost";
};
port = mkOption {
type = types.port;
description = "The SMTP Port to connect to.";
default = 25;
};
admins = mkOption {
type = listOf str;
description = ''
Comma-separated list of email addresses that should receive a report about every error code 500 thrown by pretix.
'';
default = [ ];
};
};
banktool = {
enable = mkEnableOption "Enable tool to query bank account and sync transaction data to pretix server.";
days = mkOption {
type = types.int;
description = "The timeframe of transaction to fetch from the bank in days.";
};
};
};
config = lib.mkIf cfg.enable {
sops.secrets.pretix-cfg = {
sopsFile = cfg.secretsFile;
};
sops.secrets.pretix-banktool-cfg = {
sopsFile = cfg.secretsFile;
};
users.users."${user}" = {
createHome = true;
description = "Pretix user";
home = "/var/pretix";
isNormalUser = false;
isSystemUser = true;
group = group;
};
users.groups."${group}" = { };
services.nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
virtualHosts = lib.listToAttrs (map
(d: {
name = d;
value = {
enableACME = cfg.enableTls;
forceSSL = cfg.enableTls;
kTLS = cfg.enableTls;
locations."/" = {
proxyPass = "http://${bind.host}:${toString bind.port}";
};
extraConfig = ''
${hstsHeader}
'';
};
})
([ cfg.domain ] ++ cfg.extraDomains)
);
};
services.postgresql = {
enable = true;
enableTCPIP = true;
authentication = pkgs.lib.mkOverride 10 ''
local all all trust
host all all ::1/128 trust
'';
initialScript = pkgs.writeText "backend-initScript" ''
CREATE ROLE ${postgresql.user} WITH LOGIN PASSWORD '${postgresql.password}' CREATEDB;
CREATE DATABASE ${postgresql.database};
GRANT ALL PRIVILEGES ON DATABASE ${postgresql.database} TO ${postgresql.user};
'';
};
services.redis.servers.pretix = {
enable = true;
port = redisPort;
databases = 3;
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
systemd.services.pretix-migrate = {
description = "Pretix DB Migrations";
serviceConfig = {
Type = "oneshot";
EnvironmentFile = environmentFile;
User = user;
LoadCredential = "config:${config.sops.secrets.pretix-cfg.path}";
};
script = ''
export PRETIX_CONFIG_FILE="$CREDENTIALS_DIRECTORY/config"
${pkgs.pretix}/bin/pretix migrate
'';
};
systemd.services.pretix-web = {
description = "Pretix Web Service";
serviceConfig = {
Type = "simple";
Restart = "on-failure";
EnvironmentFile = environmentFile;
User = user;
LoadCredential = "config:${config.sops.secrets.pretix-cfg.path}";
ExecStart = pkgs.writeScript "webserver" ''
#!${pkgs.runtimeShell}
set -euo pipefail
export PRETIX_CONFIG_FILE="$CREDENTIALS_DIRECTORY/config"
exec ${pythonPackages.gunicorn}/bin/gunicorn pretix.wsgi --name ${name} \
--workers 3 \
--log-level=info \
--bind=${bind.host}:${toString bind.port}
'';
};
wantedBy = [ "multi-user.target" ];
requires = [ "pretix-migrate.service" ];
after = [ "network.target" ];
};
systemd.services.pretix-worker = {
description = "Pretix Celery (Worker) Service";
serviceConfig = {
Type = "simple";
Restart = "on-failure";
EnvironmentFile = environmentFile;
User = user;
LoadCredential = "config:${config.sops.secrets.pretix-cfg.path}";
ExecStart = pkgs.writeScript "worker" ''
#!${pkgs.runtimeShell}
set -euo pipefail
export PRETIX_CONFIG_FILE="$CREDENTIALS_DIRECTORY/config"
exec ${pythonPackages.celery}/bin/celery -A pretix.celery_app worker -l info
'';
};
wantedBy = [ "multi-user.target" ];
requires = [ "pretix-migrate.service" ];
after = [ "network.target" ];
};
systemd.services.pretix-runperiodic = {
description = "Pretix periodic tasks";
serviceConfig = {
Type = "oneshot";
EnvironmentFile = environmentFile;
User = user;
LoadCredential = "config:${config.sops.secrets.pretix-cfg.path}";
};
script = ''
export PRETIX_CONFIG_FILE="$CREDENTIALS_DIRECTORY/config"
${pkgs.pretix}/bin/pretix runperiodic
'';
};
# Once every 5 minutes
systemd.timers.pretix-runperiodic = mkTimer {
description = "Run pretix tasks";
unit = "pretix-runperiodic.service";
onCalendar = "*:0/5";
};
systemd.services.pretix-banktool = lib.mkIf cfg.banktool.enable {
description = "Tool to query bank account and sync transaction data to pretix server.";
serviceConfig = {
Type = "oneshot";
DynamicUser = true;
CapabilityBoundingSet = null;
PrivateUsers = true;
ProtectHome = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
RestrictNamespaces = true;
SystemCallFilter = "@system-service";
LoadCredential = "config:${config.sops.secrets.pretix-banktool-cfg.path}";
};
script = "${pkgs.pretix-banktool}/bin/pretix-banktool upload \"$CREDENTIALS_DIRECTORY/config\" --days=${toString cfg.banktool.days}";
};
systemd.timers.pretix-banktool = lib.mkIf cfg.banktool.enable {
description = "Run tool to query bank account and sync transaction data to pretix server.";
after = [ "network.target" ];
wantedBy = [ "timers.target" ];
timerConfig = {
Persistent = true;
OnCalendar = "*-*-* *:00:00";
Unit = "pretix-banktool.service";
};
};
};
}