forked from jan-leila/nix-config
		
	feat: reworked databse config for panoramax
This commit is contained in:
		
							parent
							
								
									9b02e30080
								
							
						
					
					
						commit
						e2e07c9a70
					
				
					 2 changed files with 255 additions and 328 deletions
				
			
		|  | @ -1,334 +1,8 @@ | ||||||
| { | {...}: { | ||||||
|   config, |  | ||||||
|   lib, |  | ||||||
|   pkgs, |  | ||||||
|   ... |  | ||||||
| }: |  | ||||||
| with lib; let |  | ||||||
|   # Database configuration assertions |  | ||||||
|   dbUrlConfigured = config.services.panoramax.database.url != null; |  | ||||||
|   individualDbConfigured = 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} |  | ||||||
|       '' |  | ||||||
|     } |  | ||||||
|     ${optionalString (config.services.panoramax.storage.fsUrl != null) "FS_URL=${config.services.panoramax.storage.fsUrl}"} |  | ||||||
|     ${optionalString (config.services.panoramax.infrastructure.nbProxies != null) "INFRA_NB_PROXIES=${toString config.services.panoramax.infrastructure.nbProxies}"} |  | ||||||
|     ${optionalString (config.services.panoramax.flask.secretKey != null) "FLASK_SECRET_KEY=${config.services.panoramax.flask.secretKey}"} |  | ||||||
|     ${optionalString (config.services.panoramax.flask.sessionCookieDomain != null) "FLASK_SESSION_COOKIE_DOMAIN=${config.services.panoramax.flask.sessionCookieDomain}"} |  | ||||||
|     ${optionalString (config.services.panoramax.api.pictures.licenseSpdxId != null) "API_PICTURES_LICENSE_SPDX_ID=${config.services.panoramax.api.pictures.licenseSpdxId}"} |  | ||||||
|     ${optionalString (config.services.panoramax.api.pictures.licenseUrl != null) "API_PICTURES_LICENSE_URL=${config.services.panoramax.api.pictures.licenseUrl}"} |  | ||||||
|     ${optionalString (config.services.panoramax.port != null) "PORT=${toString config.services.panoramax.port}"} |  | ||||||
|     ${optionalString (config.services.panoramax.sgblur.enable) "SGBLUR_API_URL=${config.services.panoramax.sgblur.url}"} |  | ||||||
|     ${concatStringsSep "\n" (mapAttrsToList (name: value: "${name}=${value}") config.services.panoramax.extraEnvironment)} |  | ||||||
|   ''; |  | ||||||
| 
 |  | ||||||
|   envFile = pkgs.writeText "panoramax.env" envContent; |  | ||||||
| in { |  | ||||||
|   imports = [ |   imports = [ | ||||||
|     ./proxy.nix |     ./proxy.nix | ||||||
|     ./fail2ban.nix |     ./fail2ban.nix | ||||||
|     ./impermanence.nix |     ./impermanence.nix | ||||||
|   ]; |     ./panoramax.nix | ||||||
| 
 |  | ||||||
|   options.services.panoramax = { |  | ||||||
|     enable = lib.mkEnableOption "panoramax"; |  | ||||||
| 
 |  | ||||||
|     package = lib.mkOption { |  | ||||||
|       type = lib.types.package; |  | ||||||
|       default = pkgs.panoramax; |  | ||||||
|       description = "The panoramax package to use"; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     database = { |  | ||||||
|       createDB = mkOption { |  | ||||||
|         type = types.bool; |  | ||||||
|         default = true; |  | ||||||
|         description = "Whether to automatically create the database and user"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       url = mkOption { |  | ||||||
|         type = types.nullOr types.str; |  | ||||||
|         default = null; |  | ||||||
|         description = '' |  | ||||||
|           Complete database URL connection string (e.g., "postgresql://user:password@host:port/dbname"). |  | ||||||
|           If provided, individual database options (host, port, username, password, name) are ignored. |  | ||||||
|         ''; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       port = mkOption { |  | ||||||
|         type = types.nullOr types.port; |  | ||||||
|         default = 5432; |  | ||||||
|         description = "Database port (ignored if database.url is set)"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       host = mkOption { |  | ||||||
|         type = types.nullOr types.str; |  | ||||||
|         default = "localhost"; |  | ||||||
|         description = "Database host (ignored if database.url is set)"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       username = mkOption { |  | ||||||
|         type = types.nullOr types.str; |  | ||||||
|         default = "panoramax"; |  | ||||||
|         description = "Database username (ignored if database.url is set)"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       password = mkOption { |  | ||||||
|         type = types.nullOr types.str; |  | ||||||
|         default = null; |  | ||||||
|         description = "Database password (ignored if database.url is set)"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       name = mkOption { |  | ||||||
|         type = types.str; |  | ||||||
|         default = "panoramax"; |  | ||||||
|         description = "Database name (ignored if database.url is set)"; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     sgblur = { |  | ||||||
|       enable = mkOption { |  | ||||||
|         type = types.bool; |  | ||||||
|         default = false; |  | ||||||
|         description = "Whether to enable sgblur integration for face and license plate blurring"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       package = mkOption { |  | ||||||
|         type = types.package; |  | ||||||
|         default = pkgs.sgblur; |  | ||||||
|         description = "The sgblur package to use"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       port = mkOption { |  | ||||||
|         type = types.port; |  | ||||||
|         default = 8080; |  | ||||||
|         description = "Port for the sgblur service"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       host = mkOption { |  | ||||||
|         type = types.str; |  | ||||||
|         default = "127.0.0.1"; |  | ||||||
|         description = "Host to bind the sgblur service to"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       url = mkOption { |  | ||||||
|         type = types.str; |  | ||||||
|         default = "http://127.0.0.1:8080"; |  | ||||||
|         description = "URL where sgblur service is accessible"; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     port = mkOption { |  | ||||||
|       type = types.nullOr types.port; |  | ||||||
|       default = 5000; |  | ||||||
|       description = "Port for the Panoramax service"; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     host = mkOption { |  | ||||||
|       type = types.str; |  | ||||||
|       default = "127.0.0.1"; |  | ||||||
|       description = "Host to bind the Panoramax service to"; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     urlScheme = mkOption { |  | ||||||
|       type = types.enum ["http" "https"]; |  | ||||||
|       default = "https"; |  | ||||||
|       description = "URL scheme for the application"; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     storage = { |  | ||||||
|       fsUrl = mkOption { |  | ||||||
|         type = types.nullOr types.str; |  | ||||||
|         default = "/var/lib/panoramax/storage"; |  | ||||||
|         description = "File system URL for storage"; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     infrastructure = { |  | ||||||
|       nbProxies = mkOption { |  | ||||||
|         type = types.nullOr types.int; |  | ||||||
|         default = 1; |  | ||||||
|         description = "Number of proxies in front of the application"; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     flask = { |  | ||||||
|       secretKey = mkOption { |  | ||||||
|         type = types.nullOr types.str; |  | ||||||
|         default = null; |  | ||||||
|         description = "Flask secret key for session security"; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       sessionCookieDomain = mkOption { |  | ||||||
|         type = types.nullOr types.str; |  | ||||||
|         default = null; |  | ||||||
|         description = "Flask session cookie domain"; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     api = { |  | ||||||
|       pictures = { |  | ||||||
|         licenseSpdxId = mkOption { |  | ||||||
|           type = types.nullOr types.str; |  | ||||||
|           default = null; |  | ||||||
|           description = "SPDX license identifier for API pictures"; |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         licenseUrl = mkOption { |  | ||||||
|           type = types.nullOr types.str; |  | ||||||
|           default = null; |  | ||||||
|           description = "License URL for API pictures"; |  | ||||||
|         }; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     extraEnvironment = mkOption { |  | ||||||
|       type = types.attrsOf types.str; |  | ||||||
|       default = {}; |  | ||||||
|       description = "Additional environment variables"; |  | ||||||
|       example = { |  | ||||||
|         CUSTOM_SETTING = "value"; |  | ||||||
|         DEBUG = "true"; |  | ||||||
|       }; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   config = lib.mkIf config.services.panoramax.enable (lib.mkMerge [ |  | ||||||
|     { |  | ||||||
|       environment.systemPackages = with pkgs; |  | ||||||
|         [ |  | ||||||
|           config.services.panoramax.package |  | ||||||
|           python3Packages.waitress |  | ||||||
|         ] |  | ||||||
|         ++ optionals config.services.panoramax.sgblur.enable [ |  | ||||||
|           config.services.panoramax.sgblur.package |  | ||||||
|         ]; |  | ||||||
| 
 |  | ||||||
|       systemd.services.panoramax = { |  | ||||||
|         description = "Panoramax Service"; |  | ||||||
|         after = ["network.target"]; |  | ||||||
|         wantedBy = ["multi-user.target"]; |  | ||||||
|         serviceConfig = { |  | ||||||
|           ExecStart = "${pkgs.python3Packages.waitress}/bin/waitress-serve --env-file=${envFile} --host=${config.services.panoramax.host} --port=${toString config.services.panoramax.port} --url-scheme=${config.services.panoramax.urlScheme} --call geovisio:create_app"; |  | ||||||
|           Restart = "always"; |  | ||||||
|           User = "panoramax"; |  | ||||||
|           Group = "panoramax"; |  | ||||||
|           WorkingDirectory = "/var/lib/panoramax"; |  | ||||||
|           Environment = "PYTHONPATH=${config.services.panoramax.package}/lib/python3.11/site-packages"; |  | ||||||
|         }; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       users.users.panoramax = { |  | ||||||
|         isSystemUser = true; |  | ||||||
|         group = "panoramax"; |  | ||||||
|         home = "/var/lib/panoramax"; |  | ||||||
|         createHome = true; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       users.groups.panoramax = {}; |  | ||||||
| 
 |  | ||||||
|       systemd.tmpfiles.rules = [ |  | ||||||
|         "d /var/lib/panoramax 0755 panoramax panoramax -" |  | ||||||
|         "d ${config.services.panoramax.storage.fsUrl} 0755 panoramax panoramax -" |  | ||||||
|       ]; |  | ||||||
| 
 |  | ||||||
|       assertions = [ |  | ||||||
|         { |  | ||||||
|           assertion = dbUrlConfigured || individualDbConfigured; |  | ||||||
|           message = '' |  | ||||||
|             Panoramax database configuration requires either: |  | ||||||
|             - A complete database URL (services.panoramax.database.url), OR |  | ||||||
|             - All individual database options (host, port, username, password, name) |  | ||||||
| 
 |  | ||||||
|             Currently configured: |  | ||||||
|             - database.url: ${ |  | ||||||
|               if dbUrlConfigured |  | ||||||
|               then "✓ configured" |  | ||||||
|               else "✗ not configured" |  | ||||||
|             } |  | ||||||
|             - individual options: ${ |  | ||||||
|               if individualDbConfigured |  | ||||||
|               then "✓ all configured" |  | ||||||
|               else "✗ some missing" |  | ||||||
|             } |  | ||||||
|           ''; |  | ||||||
|         } |  | ||||||
|         { |  | ||||||
|           assertion = !config.services.panoramax.database.createDB || config.services.panoramax.database.url == null || (lib.hasPrefix "/run/" config.services.panoramax.database.url || lib.hasPrefix "unix:" config.services.panoramax.database.url || lib.hasPrefix "/" config.services.panoramax.database.host); |  | ||||||
|           message = '' |  | ||||||
|             Panoramax createDB option can only be used with socket connections when a database URL is provided. |  | ||||||
|             Socket connections are identified by: |  | ||||||
|             - URLs starting with "unix:" |  | ||||||
|             - URLs starting with "/run/" |  | ||||||
|             - Host paths starting with "/" |  | ||||||
| 
 |  | ||||||
|             Current configuration: |  | ||||||
|             - createDB: ${lib.boolToString config.services.panoramax.database.createDB} |  | ||||||
|             - database.url: ${ |  | ||||||
|               if config.services.panoramax.database.url != null |  | ||||||
|               then config.services.panoramax.database.url |  | ||||||
|               else "not set" |  | ||||||
|             } |  | ||||||
|             - database.host: ${config.services.panoramax.database.host} |  | ||||||
|           ''; |  | ||||||
|         } |  | ||||||
|   ]; |   ]; | ||||||
| } | } | ||||||
|     (lib.mkIf config.services.panoramax.database.createDB { |  | ||||||
|       systemd.services.panoramax = { |  | ||||||
|         after = ["postgresql.service"]; |  | ||||||
|         requires = ["postgresql.service"]; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       services.postgresql = { |  | ||||||
|         enable = true; |  | ||||||
|         ensureDatabases = [config.services.panoramax.database.name]; |  | ||||||
|         ensureUsers = [ |  | ||||||
|           { |  | ||||||
|             name = config.services.panoramax.database.username; |  | ||||||
|             ensureDBOwnership = true; |  | ||||||
|             ensureClauses.login = true; |  | ||||||
|           } |  | ||||||
|         ]; |  | ||||||
|         extensions = ps: with ps; [postgis]; |  | ||||||
|         settings = { |  | ||||||
|           shared_preload_libraries = ["postgis"]; |  | ||||||
|         }; |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       systemd.services.postgresql.serviceConfig.ExecStartPost = let |  | ||||||
|         sqlFile = pkgs.writeText "panoramax-postgis-setup.sql" '' |  | ||||||
|           CREATE EXTENSION IF NOT EXISTS postgis; |  | ||||||
|           CREATE EXTENSION IF NOT EXISTS postgis_topology; |  | ||||||
|           CREATE EXTENSION IF NOT EXISTS fuzzystrmatch; |  | ||||||
|           CREATE EXTENSION IF NOT EXISTS postgis_tiger_geocoder; |  | ||||||
| 
 |  | ||||||
|           ALTER SCHEMA public OWNER TO ${config.services.panoramax.database.username}; |  | ||||||
|           GRANT ALL ON SCHEMA public TO ${config.services.panoramax.database.username}; |  | ||||||
|         ''; |  | ||||||
|       in [ |  | ||||||
|         '' |  | ||||||
|           ${lib.getExe' config.services.postgresql.package "psql"} -d "${config.services.panoramax.database.name}" -f "${sqlFile}" |  | ||||||
|         '' |  | ||||||
|       ]; |  | ||||||
|     }) |  | ||||||
|   ]); |  | ||||||
| } |  | ||||||
|  |  | ||||||
							
								
								
									
										253
									
								
								modules/nixos-modules/server/panoramax/panoramax.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								modules/nixos-modules/server/panoramax/panoramax.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,253 @@ | ||||||
|  | { | ||||||
|  |   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}" | ||||||
|  |         '' | ||||||
|  |       ]; | ||||||
|  |     }) | ||||||
|  |   ]); | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue