# External services — message brokers, LLM backends, object storage, … # # All sensitive values use '${ENV_VAR}' tokens resolved after deserialisation. # Set real values in .env — never inline credentials here. # Required env vars (add to .env as needed): # NATS_URL, NATS_TOKEN # NATS_ADMIN_URL, NATS_ADMIN_CREDENTIALS_FILE, NATS_ADMIN_NAMESPACE_PREFIX, NATS_ADMIN_NAMESPACE_ENV # OLLAMA_BASE_URL # S3_ENDPOINT, S3_REGION, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY # # To activate a service: set enabled = true and configure the matching env vars. let C = import "external-services/contracts.ncl" in { external_services = { # ── NATS — message broker / event bus ───────────────────────────────────── nats = { enabled = true, url = "${NATS_URL}", token = "${NATS_TOKEN}", connection_timeout = 5, max_reconnects = 10, reconnect_delay = 2, subjects = { events = "app.events", notify = "app.notifications", control = "app.control", }, } | C.NatsConfig, # ── NATS Admin — operational bus for supervisor toolkit ─────────────────── # Separate connection from the general app NATS: different credentials, # namespace-scoped subjects, and JetStream for audit log. # # Leaf-node topology: the web server connects outbound to the hub — # no inbound ports required in k8s. # # Subject full path assembled at runtime: # {namespace.prefix}.{namespace.env}.{subjects.*} # e.g. "evol.website.prod.admin.logs" # # To override namespace.env per Deployment without changing this file: # set NATS_ADMIN_NAMESPACE_ENV=staging in the k8s Deployment env. nats_admin = { enabled = true, url = "${NATS_ADMIN_URL}", credentials_file = "${NATS_ADMIN_CREDENTIALS_FILE}", connection_timeout = 5, max_reconnects = 10, reconnect_delay = 2, namespace = { prefix = "${NATS_ADMIN_NAMESPACE_PREFIX}", env = "${NATS_ADMIN_NAMESPACE_ENV}", }, subjects = { # Admin operational subjects (leaf — prefix+env prepended at runtime) logs = "admin.logs", health = "admin.health", users = "admin.users", # Ops signals from CI/CD pipeline deploy = "ops.deploy", reload = "ops.config-reload", }, jetstream = { enabled = true, stream_name = "rustelo-admin", retention_days = 30, retention = "Limits", storage = "File", max_messages = 0, max_bytes = 0, consumers = [ { name = "rustelo-pipelines", ack_policy = "Explicit", filter_subjects = [], }, ], }, nkey_seed = "${NATS_ADMIN_NKEY_SEED}", require_signed_messages = false, trusted_nkeys = [], } | C.NatsAdminConfig, # ── Ollama — local LLM inference ────────────────────────────────────────── ollama = { enabled = false, base_url = "${OLLAMA_BASE_URL}", default_model = "llama3", request_timeout = 120, stream = true, keep_alive = "5m", max_tokens = 2048, temperature = 0.7, } | C.OllamaConfig, # ── S3-compatible object storage (AWS S3, MinIO, R2, …) ────────────────── s3 = { enabled = false, endpoint = "${S3_ENDPOINT}", region = "${S3_REGION}", bucket = "${S3_BUCKET}", access_key = "${S3_ACCESS_KEY}", secret_key = "${S3_SECRET_KEY}", path_style = false, upload_prefix = "uploads/", max_object_size = 104857600, presign_ttl = 3600, } | C.S3Config, } | C.ExternalServicesConfig, }