add credentials option support

This commit is contained in:
Jonas Heinrich 2026-03-22 10:19:01 +01:00
parent 56f1f4e8fb
commit ecaf5ab897
2 changed files with 42 additions and 5 deletions

View file

@ -36,6 +36,22 @@ logger = logging.getLogger(__name__)
SITE_BASE_URL = os.environ.get("MEINANTRAG_BASE_URL", "http://localhost:8000")
def resolve_env_value(value):
"""
Resolve environment variable values that may use file: prefix.
If the value starts with 'file:', read the content from the specified path.
"""
if value and value.startswith("file:"):
file_path = value[5:]
try:
with open(file_path, 'r') as f:
return f.read().strip()
except (IOError, OSError) as e:
logger.warning(f"Failed to read credential file {file_path}: {e}")
return None
return value
class BaseTemplateResource:
"""Base class for resources that need template rendering"""
@ -141,8 +157,9 @@ class DatenschutzResource(BaseTemplateResource):
class GenerateAntragResource:
def __init__(self):
# Initialize Gemini API
api_key = os.environ.get("GOOGLE_GEMINI_API_KEY")
# Initialize Gemini API with file-macro support
api_key_raw = os.environ.get("GOOGLE_GEMINI_API_KEY")
api_key = resolve_env_value(api_key_raw)
if api_key:
genai.configure(api_key=api_key)
self.model = genai.GenerativeModel("gemini-2.5-pro")

View file

@ -20,12 +20,27 @@ in
type = lib.types.attrsOf lib.types.str;
default = { };
example = {
GOOGLE_GEMINI_API_KEY = "your-api-key-here";
MEINANTRAG_BASE_URL = "https://example.com";
GOOGLE_GEMINI_API_KEY = "file:/run/secrets/gemini_api_key";
};
description = ''
Additional environment variables to pass to the MeinAntrag service.
For example, set GOOGLE_GEMINI_API_KEY for Gemini API integration.
Values starting with "file:" will be read from the specified path.
For secrets with systemd LoadCredential, use the credentials option instead.
'';
};
credentials = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = { };
example = {
GOOGLE_GEMINI_API_KEY = "/run/secrets/gemini_api_key";
};
description = ''
Credentials to pass to the MeinAntrag service.
Maps environment variable names to file paths containing the secret values.
These are loaded via systemd's LoadCredential mechanism.
The Python app will automatically read the value from the file.
'';
};
@ -64,7 +79,8 @@ in
"PYTHONPATH=${pkgs.meinantrag}/share/meinantrag:${pkgs.meinantrag.pythonPath}"
"MEINANTRAG_TEMPLATES_DIR=${pkgs.meinantrag}/share/meinantrag/templates"
"MEINANTRAG_STATIC_DIR=${pkgs.meinantrag}/share/meinantrag/assets"
] ++ (lib.mapAttrsToList (name: value: "${name}=${value}") cfg.settings);
] ++ (lib.mapAttrsToList (name: value: "${name}=${value}") cfg.settings)
++ (lib.mapAttrsToList (name: _: "${name}=file:/run/credentials/uwsgi.service/${name}") cfg.credentials);
settings = {
"static-map" = "/static=${pkgs.meinantrag}/share/meinantrag/assets";
@ -74,6 +90,10 @@ in
};
};
# Load credentials via systemd's LoadCredential mechanism
systemd.services.uwsgi.serviceConfig.LoadCredential =
lib.mapAttrsToList (key: value: "${key}:${value}") cfg.credentials;
# Ensure meinantrag user and group exist
users.users.meinantrag = {
isSystemUser = true;