nix-config/modules/nixos-modules/server/panoramax/panoramax.nix

253 lines
8.4 KiB
Nix

{
config,
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";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.panoramax;
description = "The panoramax package to use";
};
user = lib.mkOption {
type = lib.types.str;
default = "panoramax";
description = "The user panoramax should run as.";
};
group = lib.mkOption {
type = lib.types.str;
default = "panoramax";
description = "The group panoramax should run as.";
};
host = lib.mkOption {
type = lib.types.str;
default = "127.0.0.1";
description = "Host to bind the panoramax service to";
};
port = lib.mkOption {
type = lib.types.nullOr lib.types.port;
default = 5000;
description = "Port for the panoramax service";
};
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to open the panoramax port in the firewall";
};
settings = {
urlScheme = lib.mkOption {
type = lib.types.enum ["http" "https"];
default = "https";
description = "URL scheme for the application";
};
storage = {
fsUrl = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = "/var/lib/panoramax/storage";
description = "File system URL for storage";
};
};
infrastructure = {
nbProxies = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = 1;
description = "Number of proxies in front of the application";
};
};
flask = {
secretKey = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Flask secret key for session security";
};
sessionCookieDomain = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Flask session cookie domain";
};
};
api = {
pictures = {
licenseSpdxId = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "SPDX license identifier for API pictures";
};
licenseUrl = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "License URL for API pictures";
};
};
};
extraEnvironment = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = {};
description = "Additional environment variables";
example = {
CUSTOM_SETTING = "value";
DEBUG = "true";
};
};
};
database = {
createDB = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to automatically create the database and user";
};
name = lib.mkOption {
type = lib.types.str;
default = "panoramax";
description = "The name of the panoramax database";
};
host = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = "/run/postgresql";
description = "Hostname or address of the postgresql server. If an absolute path is given here, it will be interpreted as a unix socket path.";
};
port = lib.mkOption {
type = lib.types.nullOr lib.types.port;
default = 5432;
description = "Port of the postgresql server.";
};
user = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = "panoramax";
description = "The database user for panoramax.";
};
# TODO: password file for external database
};
sgblur = {
# TODO: configs to bind to sgblur
};
};
sgblur = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to enable sgblur integration for face and license plate blurring";
};
package = lib.mkOption {
type = lib.types.package;
default = pkgs.sgblur;
description = "The sgblur package to use";
};
port = lib.mkOption {
type = lib.types.port;
default = 8080;
description = "Port for the sgblur service";
};
host = lib.mkOption {
type = lib.types.str;
default = "127.0.0.1";
description = "Host to bind the sgblur service to";
};
url = lib.mkOption {
type = lib.types.str;
default = "http://127.0.0.1:8080";
description = "URL where sgblur service is accessible";
};
};
};
config = lib.mkIf config.services.panoramax.enable (lib.mkMerge [
{
# TODO: start panoramax service
}
(lib.mkIf config.services.sgblur.enable {
# TODO: start sg blur config
})
(lib.mkIf config.services.panoramax.database.createDB {
services.postgresql = lib.mkIf config.services.panoramax.database.enable {
enable = true;
ensureDatabases = lib.mkIf config.services.panoramax.database.createDB [config.services.panoramax.database.name];
ensureUsers = lib.mkIf config.services.panoramax.database.createDB [
{
name = config.services.panoramax.database.user;
ensureDBOwnership = true;
ensureClauses.login = true;
}
];
extensions = ps: with ps; [postgis];
};
systemd.services.postgresql.serviceConfig.ExecStartPost = let
sqlFile = pkgs.writeText "panoramax-postgis-setup.sql" ''
CREATE EXTENSION IF NOT EXISTS postgis;
ALTER DATABASE ${config.services.panoramax.database.name} SET TIMEZONE TO 'UTC';
GRANT SET ON PARAMETER session_replication_role TO ${config.services.panoramax.database.user};
'';
in [
''
${lib.getExe' config.services.postgresql.package "psql"} -d "${config.services.panoramax.database.user}" -f "${sqlFile}"
''
];
})
]);
}