fix: fixed pkg dependencies for panoramax

This commit is contained in:
Leyla Becker 2025-09-17 15:15:07 -05:00
parent 1b1a3f7219
commit 3bee0c7402
13 changed files with 632 additions and 39 deletions

View file

@ -3,43 +3,7 @@
lib,
pkgs,
...
}: let
dbUrlConfigured = config.services.panoramax.database.url != null;
individualDbConfigured = lib.all (x: x != null) [
config.services.panoramax.database.host
config.services.panoramax.database.port
config.services.panoramax.database.username
config.services.panoramax.database.password
config.services.panoramax.database.name
];
envContent = ''
# Panoramax Configuration
FLASK_APP=geovisio
${
if dbUrlConfigured
then "DB_URL=${config.services.panoramax.database.url}"
else ''
DB_HOST=${config.services.panoramax.database.host}
DB_PORT=${toString config.services.panoramax.database.port}
DB_USERNAME=${config.services.panoramax.database.username}
DB_PASSWORD=${config.services.panoramax.database.password}
DB_NAME=${config.services.panoramax.database.name}
''
}
${lib.optionalString (config.services.panoramax.storage.fsUrl != null) "FS_URL=${config.services.panoramax.storage.fsUrl}"}
${lib.optionalString (config.services.panoramax.infrastructure.nbProxies != null) "INFRA_NB_PROXIES=${toString config.services.panoramax.infrastructure.nbProxies}"}
${lib.optionalString (config.services.panoramax.flask.secretKey != null) "FLASK_SECRET_KEY=${config.services.panoramax.flask.secretKey}"}
${lib.optionalString (config.services.panoramax.flask.sessionCookieDomain != null) "FLASK_SESSION_COOKIE_DOMAIN=${config.services.panoramax.flask.sessionCookieDomain}"}
${lib.optionalString (config.services.panoramax.api.pictures.licenseSpdxId != null) "API_PICTURES_LICENSE_SPDX_ID=${config.services.panoramax.api.pictures.licenseSpdxId}"}
${lib.optionalString (config.services.panoramax.api.pictures.licenseUrl != null) "API_PICTURES_LICENSE_URL=${config.services.panoramax.api.pictures.licenseUrl}"}
${lib.optionalString (config.services.panoramax.port != null) "PORT=${toString config.services.panoramax.port}"}
${lib.optionalString (config.services.panoramax.sgblur.enable) "SGBLUR_API_URL=${config.services.panoramax.sgblur.url}"}
${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: "${name}=${value}") config.services.panoramax.extraEnvironment)}
'';
envFile = pkgs.writeText "panoramax.env" envContent;
in {
}: {
options.services = {
panoramax = {
enable = lib.mkEnableOption "panoramax";
@ -217,10 +181,145 @@ in {
config = lib.mkIf config.services.panoramax.enable (lib.mkMerge [
{
# TODO: start panoramax service
# Create panoramax user and group
users.users.${config.services.panoramax.user} = {
isSystemUser = true;
group = config.services.panoramax.group;
home = "/var/lib/panoramax";
createHome = true;
};
users.groups.${config.services.panoramax.group} = {};
# Ensure storage directory exists with correct permissions
systemd.tmpfiles.rules = [
"d '${config.services.panoramax.settings.storage.fsUrl}' 0755 ${config.services.panoramax.user} ${config.services.panoramax.group} - -"
];
systemd.services.panoramax-api = {
description = "Panoramax API server (self hosted map street view)";
after = ["network.target" "postgresql.service"];
wantedBy = ["multi-user.target"];
environment =
{
# Core Flask configuration
FLASK_APP = "geovisio";
# Database configuration
DB_HOST = config.services.panoramax.database.host;
DB_PORT = toString config.services.panoramax.database.port;
DB_USERNAME = config.services.panoramax.database.user;
DB_NAME = config.services.panoramax.database.name;
# Storage configuration
FS_URL = config.services.panoramax.settings.storage.fsUrl;
# Infrastructure configuration
INFRA_NB_PROXIES = toString config.services.panoramax.settings.infrastructure.nbProxies;
# Application configuration
PORT = toString config.services.panoramax.port;
# Python path to include the panoramax package
PYTHONPATH = "${config.services.panoramax.package}/${pkgs.python3.sitePackages}";
}
// (lib.optionalAttrs (config.services.panoramax.settings.flask.secretKey != null) {
FLASK_SECRET_KEY = config.services.panoramax.settings.flask.secretKey;
})
// (lib.optionalAttrs (config.services.panoramax.settings.flask.sessionCookieDomain != null) {
FLASK_SESSION_COOKIE_DOMAIN = config.services.panoramax.settings.flask.sessionCookieDomain;
})
// (lib.optionalAttrs (config.services.panoramax.settings.api.pictures.licenseSpdxId != null) {
API_PICTURES_LICENSE_SPDX_ID = config.services.panoramax.settings.api.pictures.licenseSpdxId;
})
// (lib.optionalAttrs (config.services.panoramax.settings.api.pictures.licenseUrl != null) {
API_PICTURES_LICENSE_URL = config.services.panoramax.settings.api.pictures.licenseUrl;
})
// (lib.optionalAttrs config.services.sgblur.enable {
SGBLUR_API_URL = config.services.sgblur.url;
})
// config.services.panoramax.settings.extraEnvironment;
path = with pkgs; [
(python3.withPackages (ps: with ps; [config.services.panoramax.package waitress]))
];
serviceConfig = {
ExecStart = "${pkgs.python3.withPackages (ps: with ps; [config.services.panoramax.package waitress])}/bin/waitress-serve --port ${toString config.services.panoramax.port} --call geovisio:create_app";
User = config.services.panoramax.user;
Group = config.services.panoramax.group;
WorkingDirectory = "/var/lib/panoramax";
Restart = "always";
RestartSec = 5;
# Security hardening
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
ReadWritePaths = [
"/var/lib/panoramax"
config.services.panoramax.settings.storage.fsUrl
];
NoNewPrivileges = true;
PrivateDevices = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
RestrictSUIDSGID = true;
RestrictRealtime = true;
RestrictNamespaces = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
SystemCallArchitectures = "native";
};
};
# Open firewall if requested
networking.firewall.allowedTCPPorts = lib.mkIf config.services.panoramax.openFirewall [
config.services.panoramax.port
];
}
(lib.mkIf config.services.sgblur.enable {
# TODO: start sg blur config
# SGBlur service configuration
systemd.services.sgblur = {
description = "SGBlur face and license plate blurring service";
after = ["network.target"];
wantedBy = ["multi-user.target"];
path = with pkgs; [
config.services.sgblur.package
python3
python3Packages.waitress
];
serviceConfig = {
ExecStart = "${pkgs.python3Packages.waitress}/bin/waitress-serve --host ${config.services.sgblur.host} --port ${toString config.services.sgblur.port} src.detect.detect_api:app";
WorkingDirectory = "${config.services.sgblur.package}";
Restart = "always";
RestartSec = 5;
# Basic security hardening
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
NoNewPrivileges = true;
PrivateDevices = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
RestrictSUIDSGID = true;
RestrictRealtime = true;
RestrictNamespaces = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
SystemCallArchitectures = "native";
};
};
networking.firewall.allowedTCPPorts = lib.mkIf config.services.panoramax.openFirewall [
config.services.sgblur.port
];
})
(lib.mkIf config.services.panoramax.database.createDB {
services.postgresql = {