Files
Magent/scripts/prepare_production_settings.py

63 lines
3.1 KiB
Python

"""Run inside the configured source container. Export configuration, NEVER data.
Usage: python prepare_production_settings.py /secure/new-directory
Creates new files exclusively with mode 0600. No secrets go to stdout.
"""
import json
import os
from pathlib import Path
import secrets
import sys
from cryptography.fernet import Fernet
from app.runtime import get_runtime_settings
def prepare(destination: Path) -> None:
runtime = get_runtime_settings()
keys = [
'jellyfin_base_url', 'jellyfin_api_key', 'jellyfin_public_url',
'jellyseerr_base_url', 'jellyseerr_api_key',
'sonarr_base_url', 'sonarr_api_key', 'radarr_base_url', 'radarr_api_key',
'prowlarr_base_url', 'prowlarr_api_key', 'bazarr_base_url', 'bazarr_api_key',
'qbittorrent_base_url', 'qbittorrent_username', 'qbittorrent_password',
'magent_notify_enabled', 'magent_notify_email_enabled',
'magent_notify_email_smtp_host', 'magent_notify_email_smtp_port',
'magent_notify_email_smtp_username', 'magent_notify_email_smtp_password',
'magent_notify_email_from_address', 'magent_notify_email_from_name',
'magent_notify_email_use_tls', 'magent_notify_email_use_ssl',
]
values = {key.upper(): getattr(runtime, key) for key in keys if getattr(runtime, key, None) is not None}
password = secrets.token_urlsafe(30)
values.update(
APP_NAME='Magent', JWT_SECRET=secrets.token_urlsafe(48),
SETTINGS_ENCRYPTION_KEY=Fernet.generate_key().decode('ascii'),
ADMIN_USERNAME='admin', ADMIN_PASSWORD=password,
AUTH_COOKIE_SECURE=True, AUTH_COOKIE_DOMAIN='magent.grizzlyflix.co.nz',
AUTH_COOKIE_NAME='magent_auth', AUTH_STATE_COOKIE_NAME='magent_logged_in',
CORS_ALLOW_ORIGIN='https://magent.grizzlyflix.co.nz',
MAGENT_APPLICATION_URL='https://magent.grizzlyflix.co.nz',
MAGENT_API_URL='https://magent.grizzlyflix.co.nz/api',
SQLITE_PATH='/app/data/magent.db', LOG_FILE='/app/data/magent.log',
SITE_BANNER_ENABLED=False, MAGENT_COMING_SOON=True,
BACKGROUND_TASKS_ENABLED=False,
)
destination.mkdir(mode=0o700, parents=True, exist_ok=False)
def write_private(name, content):
with os.fdopen(os.open(destination / name, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600), 'w') as stream:
stream.write(content)
# Compose single-quoted values preserve dollar signs in SMTP passwords.
def encode(value):
text = str(value).lower() if isinstance(value, bool) else str(value)
if '\n' in text or '\r' in text:
raise ValueError('Multiline configuration values require manual review')
return "'" + text.replace('\\', '\\\\').replace("'", "\\'") + "'"
write_private('.env', ''.join(f'{key}={encode(value)}\n' for key, value in values.items()))
write_private('bootstrap-admin.json', json.dumps({'username': 'admin', 'password': password}))
print(f'Prepared {len(keys)} allowlisted connection settings; fresh session and admin credentials. No client records copied.')
if __name__ == '__main__':
prepare(Path(sys.argv[1]))