completed local setup with compose
Some checks failed
CI/CD Pipeline / Generate SBOM (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Code Quality & Linting (push) Has been cancelled
CI/CD Pipeline / Policy Validation (push) Has been cancelled
CI/CD Pipeline / Test Suite (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-coverage) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-extract) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-firm-connectors) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-forms) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-hmrc) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-ingestion) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-kg) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-normalize-map) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-ocr) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-rag-indexer) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-rag-retriever) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-reason) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-rpa) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (ui-review) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-coverage) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-extract) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-kg) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-rag-retriever) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (ui-review) (push) Has been cancelled
CI/CD Pipeline / Notifications (push) Has been cancelled
Some checks failed
CI/CD Pipeline / Generate SBOM (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Code Quality & Linting (push) Has been cancelled
CI/CD Pipeline / Policy Validation (push) Has been cancelled
CI/CD Pipeline / Test Suite (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-coverage) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-extract) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-firm-connectors) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-forms) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-hmrc) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-ingestion) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-kg) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-normalize-map) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-ocr) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-rag-indexer) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-rag-retriever) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-reason) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (svc-rpa) (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (ui-review) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-coverage) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-extract) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-kg) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (svc-rag-retriever) (push) Has been cancelled
CI/CD Pipeline / Security Scanning (ui-review) (push) Has been cancelled
CI/CD Pipeline / Notifications (push) Has been cancelled
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
|
||||
Multi-environment Docker Compose infrastructure for AI Tax Agent.
|
||||
|
||||
For local development use the dedicated self-signed stack in `infra/compose` (see `infra/compose/README.md`). For remote environments use the shared base files with `infra/scripts/deploy.sh` and the envs in `infra/environments`.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
@@ -244,4 +246,3 @@ For issues or questions:
|
||||
- Check logs: `docker compose logs -f <service>`
|
||||
- Review documentation in `docs/`
|
||||
- Check Traefik dashboard for routing issues
|
||||
|
||||
|
||||
370
infra/authentik/bootstrap.yaml
Normal file
370
infra/authentik/bootstrap.yaml
Normal file
@@ -0,0 +1,370 @@
|
||||
# FILE: blueprints/ai-tax-agent-bootstrap.yaml
|
||||
# Authentik Bootstrap (v2025.x): users, groups, scope mappings, OIDC providers, applications
|
||||
|
||||
version: 1
|
||||
|
||||
metadata:
|
||||
name: AI Tax Agent — Bootstrap + OIDC Providers
|
||||
|
||||
entries:
|
||||
# --- Groups first (so the admin user can reference them) -------------------
|
||||
- model: authentik_core.group
|
||||
state: present
|
||||
identifiers:
|
||||
name: "Administrators"
|
||||
attrs:
|
||||
is_superuser: true
|
||||
|
||||
- model: authentik_core.group
|
||||
state: present
|
||||
identifiers:
|
||||
name: "Tax Reviewers"
|
||||
attrs:
|
||||
is_superuser: false
|
||||
|
||||
- model: authentik_core.group
|
||||
state: present
|
||||
identifiers:
|
||||
name: "Accountants"
|
||||
attrs:
|
||||
is_superuser: false
|
||||
|
||||
- model: authentik_core.group
|
||||
state: present
|
||||
identifiers:
|
||||
name: "Clients"
|
||||
attrs:
|
||||
is_superuser: false
|
||||
|
||||
# --- Admin user ------------------------------------------------------------
|
||||
- model: authentik_core.user
|
||||
state: present
|
||||
identifiers:
|
||||
username: admin
|
||||
attrs:
|
||||
name: "System Administrator"
|
||||
email: admin@local.lan
|
||||
is_active: true
|
||||
is_staff: true
|
||||
is_superuser: true
|
||||
groups:
|
||||
- !Find [authentik_core.group, [name, "Administrators"]]
|
||||
|
||||
# Helper finders
|
||||
|
||||
# ========= OIDC Providers + Applications ==================================
|
||||
|
||||
# --- UI Review (Proxy Provider for ForwardAuth) ---------------------------
|
||||
- model: authentik_providers_proxy.proxyprovider
|
||||
state: present
|
||||
identifiers:
|
||||
name: "UI Review Proxy"
|
||||
attrs:
|
||||
external_host: "https://review.local.lan"
|
||||
internal_host: "http://ui-review:3030"
|
||||
authorization_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
|
||||
invalidation_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]
|
||||
mode: "forward_single"
|
||||
cookie_domain: "local.lan"
|
||||
|
||||
- model: authentik_core.application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: "ui-review"
|
||||
attrs:
|
||||
name: "UI Review"
|
||||
provider:
|
||||
!Find [
|
||||
authentik_providers_proxy.proxyprovider,
|
||||
[name, "UI Review Proxy"],
|
||||
]
|
||||
meta_launch_url: "https://review.local.lan"
|
||||
meta_description: "Tax Agent Platform - Review UI"
|
||||
meta_publisher: "AI Tax Agent"
|
||||
policy_engine_mode: "any"
|
||||
|
||||
# --- Vault OIDC Provider --------------------------------------------------
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: "Vault OIDC"
|
||||
attrs:
|
||||
client_id: "vault"
|
||||
client_secret: !Env [AUTHENTIK_VAULT_CLIENT_SECRET, "changeme"]
|
||||
client_type: "confidential"
|
||||
redirect_uris:
|
||||
- matching_mode: strict
|
||||
url: "https://vault.local.lan/ui/vault/auth/oidc/oidc/callback"
|
||||
- matching_mode: strict
|
||||
url: "https://vault.local.lan/oidc/callback"
|
||||
- matching_mode: strict
|
||||
url: "http://localhost:8250/oidc/callback"
|
||||
sub_mode: "hashed_user_id"
|
||||
include_claims_in_id_token: true
|
||||
issuer_mode: "per_provider"
|
||||
signing_key:
|
||||
!Find [
|
||||
authentik_crypto.certificatekeypair,
|
||||
[name, "authentik Self-signed Certificate"],
|
||||
]
|
||||
property_mappings:
|
||||
- !Find [
|
||||
authentik_providers_oauth2.scopemapping,
|
||||
[scope_name, "openid"],
|
||||
]
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, "email"]]
|
||||
- !Find [
|
||||
authentik_providers_oauth2.scopemapping,
|
||||
[scope_name, "profile"],
|
||||
]
|
||||
authorization_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
|
||||
invalidation_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]
|
||||
|
||||
- model: authentik_core.application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: "vault-oidc"
|
||||
attrs:
|
||||
name: "Vault OIDC"
|
||||
provider:
|
||||
!Find [authentik_providers_oauth2.oauth2provider, [name, "Vault OIDC"]]
|
||||
meta_launch_url: "https://vault.local.lan"
|
||||
meta_description: "Vault OIDC Authentication"
|
||||
meta_publisher: "AI Tax Agent"
|
||||
policy_engine_mode: "any"
|
||||
|
||||
# --- MinIO OIDC Provider --------------------------------------------------
|
||||
|
||||
# Scope Mapping for MinIO Policy
|
||||
- model: authentik_providers_oauth2.scopemapping
|
||||
state: present
|
||||
identifiers:
|
||||
name: "MinIO Policy Mapping"
|
||||
attrs:
|
||||
name: "MinIO Policy Mapping"
|
||||
description: "Maps Authentik users to MinIO policies"
|
||||
scope_name: "minio"
|
||||
expression: |
|
||||
# Default to readwrite for all authenticated users
|
||||
# You can customize this based on groups
|
||||
return {
|
||||
"policy": "readwrite"
|
||||
}
|
||||
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: "MinIO OIDC"
|
||||
attrs:
|
||||
client_id: "minio"
|
||||
client_secret: !Env [AUTHENTIK_MINIO_CLIENT_SECRET, "changeme"]
|
||||
client_type: "confidential"
|
||||
redirect_uris:
|
||||
- matching_mode: strict
|
||||
url: "https://minio.local.lan/oauth_callback"
|
||||
sub_mode: "hashed_user_id"
|
||||
include_claims_in_id_token: true
|
||||
issuer_mode: "per_provider"
|
||||
signing_key:
|
||||
!Find [
|
||||
authentik_crypto.certificatekeypair,
|
||||
[name, "authentik Self-signed Certificate"],
|
||||
]
|
||||
property_mappings:
|
||||
- !Find [
|
||||
authentik_providers_oauth2.scopemapping,
|
||||
[scope_name, "openid"],
|
||||
]
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, "email"]]
|
||||
- !Find [
|
||||
authentik_providers_oauth2.scopemapping,
|
||||
[scope_name, "profile"],
|
||||
]
|
||||
- !Find [
|
||||
authentik_providers_oauth2.scopemapping,
|
||||
[name, "MinIO Policy Mapping"],
|
||||
]
|
||||
authorization_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
|
||||
invalidation_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]
|
||||
|
||||
- model: authentik_core.application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: "minio-oidc"
|
||||
attrs:
|
||||
name: "MinIO OIDC"
|
||||
provider:
|
||||
!Find [authentik_providers_oauth2.oauth2provider, [name, "MinIO OIDC"]]
|
||||
meta_launch_url: "https://minio.local.lan"
|
||||
meta_description: "MinIO Object Storage OIDC"
|
||||
meta_publisher: "AI Tax Agent"
|
||||
policy_engine_mode: "any"
|
||||
|
||||
# --- Grafana SSO Configuration -------------------------------------------
|
||||
|
||||
# Custom Role Mapping for Grafana
|
||||
- model: authentik_providers_oauth2.scopemapping
|
||||
state: present
|
||||
identifiers:
|
||||
name: "Grafana Role Mapping"
|
||||
attrs:
|
||||
name: "Grafana Role Mapping"
|
||||
description: "Maps Authentik groups to Grafana roles"
|
||||
scope_name: "role"
|
||||
expression: |
|
||||
# Map Authentik groups to Grafana roles
|
||||
user_groups = [group.name for group in request.user.ak_groups.all()]
|
||||
|
||||
# Admin role mapping
|
||||
if "authentik Admins" in user_groups or "Administrators" in user_groups:
|
||||
return "Admin"
|
||||
|
||||
# Editor role mapping
|
||||
if "Tax Reviewers" in user_groups or "Accountants" in user_groups:
|
||||
return "Editor"
|
||||
|
||||
# Default to Viewer role
|
||||
return "Viewer"
|
||||
|
||||
# Grafana OAuth2 Provider
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: "Grafana"
|
||||
attrs:
|
||||
client_id: !Env [GRAFANA_OAUTH_CLIENT_ID, "grafana"]
|
||||
client_secret: !Env [GRAFANA_OAUTH_CLIENT_SECRET, "changeme"]
|
||||
client_type: "confidential"
|
||||
redirect_uris:
|
||||
- matching_mode: strict
|
||||
url: "https://grafana.local.lan/login/generic_oauth"
|
||||
sub_mode: "hashed_user_id"
|
||||
include_claims_in_id_token: true
|
||||
issuer_mode: "per_provider"
|
||||
signing_key:
|
||||
!Find [
|
||||
authentik_crypto.certificatekeypair,
|
||||
[name, "authentik Self-signed Certificate"],
|
||||
]
|
||||
property_mappings:
|
||||
- !Find [
|
||||
authentik_providers_oauth2.scopemapping,
|
||||
[scope_name, "openid"],
|
||||
]
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, "email"]]
|
||||
- !Find [
|
||||
authentik_providers_oauth2.scopemapping,
|
||||
[scope_name, "profile"],
|
||||
]
|
||||
|
||||
- !Find [
|
||||
authentik_providers_oauth2.scopemapping,
|
||||
[name, "Grafana Role Mapping"],
|
||||
]
|
||||
authorization_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
|
||||
invalidation_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]
|
||||
|
||||
# Grafana Application
|
||||
- model: authentik_core.application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: "grafana"
|
||||
attrs:
|
||||
name: "Grafana"
|
||||
provider:
|
||||
!Find [authentik_providers_oauth2.oauth2provider, [name, "Grafana"]]
|
||||
meta_launch_url: "https://grafana.local.lan"
|
||||
meta_description: "Grafana monitoring and observability platform"
|
||||
meta_publisher: "Grafana Labs"
|
||||
policy_engine_mode: "any"
|
||||
|
||||
# --- Traefik Dashboard (Proxy Provider for ForwardAuth) -------------------
|
||||
- model: authentik_providers_proxy.proxyprovider
|
||||
state: present
|
||||
identifiers:
|
||||
name: "Traefik Dashboard Proxy"
|
||||
attrs:
|
||||
external_host: "https://traefik.local.lan"
|
||||
internal_host: "http://apa-traefik:8080"
|
||||
authorization_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
|
||||
invalidation_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]
|
||||
mode: "forward_single"
|
||||
cookie_domain: "local.lan"
|
||||
|
||||
- model: authentik_core.application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: "traefik-dashboard"
|
||||
attrs:
|
||||
name: "Traefik Dashboard"
|
||||
provider:
|
||||
!Find [
|
||||
authentik_providers_proxy.proxyprovider,
|
||||
[name, "Traefik Dashboard Proxy"],
|
||||
]
|
||||
meta_launch_url: "https://traefik.local.lan"
|
||||
meta_description: "Traefik Edge Router Dashboard"
|
||||
meta_publisher: "AI Tax Agent"
|
||||
policy_engine_mode: "any"
|
||||
|
||||
# --- AI Tax Agent API (Proxy Provider for ForwardAuth) --------------------
|
||||
- model: authentik_providers_proxy.proxyprovider
|
||||
state: present
|
||||
identifiers:
|
||||
name: "AI Tax Agent API Proxy"
|
||||
attrs:
|
||||
external_host: "https://api.local.lan"
|
||||
internal_host: "http://apa-traefik:8080"
|
||||
authorization_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
|
||||
invalidation_flow:
|
||||
!Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]
|
||||
mode: "forward_single"
|
||||
cookie_domain: "local.lan"
|
||||
|
||||
- model: authentik_core.application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: "ai-tax-agent-api-gateway"
|
||||
attrs:
|
||||
name: "AI Tax Agent API Gateway"
|
||||
provider:
|
||||
!Find [
|
||||
authentik_providers_proxy.proxyprovider,
|
||||
[name, "AI Tax Agent API Proxy"],
|
||||
]
|
||||
meta_launch_url: "https://api.local.lan"
|
||||
meta_description: "AI Tax Agent API Gateway"
|
||||
meta_publisher: "AI Tax Agent"
|
||||
policy_engine_mode: "any"
|
||||
|
||||
# --- Outpost Configuration ------------------------------------------------
|
||||
- model: authentik_outposts.outpost
|
||||
state: present
|
||||
identifiers:
|
||||
name: "authentik Embedded Outpost"
|
||||
attrs:
|
||||
token: !Env [AUTHENTIK_OUTPOST_TOKEN, "changeme"]
|
||||
providers:
|
||||
- !Find [
|
||||
authentik_providers_proxy.proxyprovider,
|
||||
[name, "Traefik Dashboard Proxy"],
|
||||
]
|
||||
- !Find [
|
||||
authentik_providers_proxy.proxyprovider,
|
||||
[name, "UI Review Proxy"],
|
||||
]
|
||||
- !Find [
|
||||
authentik_providers_proxy.proxyprovider,
|
||||
[name, "AI Tax Agent API Proxy"],
|
||||
]
|
||||
@@ -20,6 +20,7 @@ volumes:
|
||||
vault_data:
|
||||
redis_data:
|
||||
nats_data:
|
||||
authentik_data:
|
||||
|
||||
services:
|
||||
# Edge Gateway & SSO
|
||||
@@ -37,6 +38,14 @@ services:
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- ./traefik/config/:/etc/traefik/:ro
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.dashboard.rule=Host(`traefik.${DOMAIN}`)"
|
||||
- "traefik.http.routers.dashboard.entrypoints=websecure"
|
||||
- "traefik.http.routers.dashboard.tls=true"
|
||||
- "traefik.http.routers.dashboard.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.dashboard.service=api@internal"
|
||||
- "traefik.http.routers.dashboard.middlewares=authentik-forwardauth@file"
|
||||
|
||||
# Identity & SSO (Authentik)
|
||||
apa-authentik-db:
|
||||
@@ -46,7 +55,7 @@ services:
|
||||
networks:
|
||||
- backend
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- authentik_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: authentik
|
||||
POSTGRES_USER: authentik
|
||||
@@ -94,7 +103,7 @@ services:
|
||||
- "traefik.http.routers.authentik.rule=Host(`auth.${DOMAIN}`)"
|
||||
- "traefik.http.routers.authentik.entrypoints=websecure"
|
||||
- "traefik.http.routers.authentik.tls=true"
|
||||
- "traefik.http.routers.authentik.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.authentik.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.services.authentik.loadbalancer.server.port=9000"
|
||||
|
||||
apa-authentik-worker:
|
||||
@@ -149,18 +158,23 @@ services:
|
||||
command: vault server -dev -dev-listen-address=0.0.0.0:8200
|
||||
cap_add:
|
||||
- IPC_LOCK
|
||||
extra_hosts:
|
||||
- "auth.local.lan:host-gateway"
|
||||
- "vault.local.lan:host-gateway"
|
||||
- "minio.local.lan:host-gateway"
|
||||
- "api.local.lan:host-gateway"
|
||||
- "traefik.local.lan:host-gateway"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.vault.rule=Host(`vault.${DOMAIN}`)"
|
||||
- "traefik.http.routers.vault.entrypoints=websecure"
|
||||
- "traefik.http.routers.vault.tls=true"
|
||||
- "traefik.http.routers.vault.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.vault.middlewares=authentik-forwardauth@file"
|
||||
- "traefik.http.routers.vault.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.services.vault.loadbalancer.server.port=8200"
|
||||
|
||||
# Object Storage
|
||||
apa-minio:
|
||||
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
|
||||
image: minio/minio:RELEASE.2025-04-22T22-12-26Z
|
||||
container_name: apa-minio
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
@@ -172,26 +186,35 @@ services:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||
MINIO_BROWSER_REDIRECT_URL: https://minio.${DOMAIN}
|
||||
MINIO_IDENTITY_OPENID_CONFIG_URL: "https://auth.${DOMAIN}/application/o/minio-oidc/.well-known/openid-configuration"
|
||||
MINIO_IDENTITY_OPENID_CLIENT_ID: "minio"
|
||||
MINIO_IDENTITY_OPENID_CLIENT_SECRET: ${AUTHENTIK_MINIO_CLIENT_SECRET}
|
||||
MINIO_IDENTITY_OPENID_SCOPES: "openid,profile,email,minio"
|
||||
MINIO_IDENTITY_OPENID_REDIRECT_URI: "https://minio.${DOMAIN}/oauth_callback"
|
||||
MINIO_IDENTITY_OPENID_DISPLAY_NAME: "Login with Authentik"
|
||||
command: server /data --address ":9092" --console-address ":9093"
|
||||
healthcheck:
|
||||
test: ["CMD", "mc", "--version"]
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9092/minio/health/live"]
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
extra_hosts:
|
||||
- "auth.local.lan:host-gateway"
|
||||
- "minio.local.lan:host-gateway"
|
||||
- "api.local.lan:host-gateway"
|
||||
- "traefik.local.lan:host-gateway"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.minio-api.rule=Host(`minio-api.${DOMAIN}`)"
|
||||
- "traefik.http.routers.minio-api.entrypoints=websecure"
|
||||
- "traefik.http.routers.minio-api.tls=true"
|
||||
- "traefik.http.routers.minio-api.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.minio-api.middlewares=authentik-forwardauth@file"
|
||||
- "traefik.http.routers.minio-api.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.minio-api.service=minio-api"
|
||||
- "traefik.http.services.minio-api.loadbalancer.server.port=9092"
|
||||
- "traefik.http.routers.minio-console.rule=Host(`minio.${DOMAIN}`)"
|
||||
- "traefik.http.routers.minio-console.entrypoints=websecure"
|
||||
- "traefik.http.routers.minio-console.tls=true"
|
||||
- "traefik.http.routers.minio-console.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.minio-console.middlewares=authentik-forwardauth@file"
|
||||
- "traefik.http.routers.minio-console.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.minio-console.service=minio-console"
|
||||
- "traefik.http.services.minio-console.loadbalancer.server.port=9093"
|
||||
|
||||
@@ -214,7 +237,7 @@ services:
|
||||
- "traefik.http.routers.qdrant.rule=Host(`qdrant.${DOMAIN}`)"
|
||||
- "traefik.http.routers.qdrant.entrypoints=websecure"
|
||||
- "traefik.http.routers.qdrant.tls=true"
|
||||
- "traefik.http.routers.qdrant.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.qdrant.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.qdrant.middlewares=authentik-forwardauth@file"
|
||||
- "traefik.http.services.qdrant.loadbalancer.server.port=6333"
|
||||
|
||||
@@ -242,7 +265,7 @@ services:
|
||||
- "traefik.http.routers.neo4j.rule=Host(`neo4j.${DOMAIN}`)"
|
||||
- "traefik.http.routers.neo4j.entrypoints=websecure"
|
||||
- "traefik.http.routers.neo4j.tls=true"
|
||||
- "traefik.http.routers.neo4j.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.neo4j.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.neo4j.middlewares=authentik-forwardauth@file"
|
||||
- "traefik.http.services.neo4j.loadbalancer.server.port=7474"
|
||||
|
||||
@@ -334,6 +357,6 @@ services:
|
||||
- "traefik.http.routers.nats-monitor.rule=Host(`nats.${DOMAIN}`)"
|
||||
- "traefik.http.routers.nats-monitor.entrypoints=websecure"
|
||||
- "traefik.http.routers.nats-monitor.tls=true"
|
||||
- "traefik.http.routers.nats-monitor.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.nats-monitor.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.nats-monitor.middlewares=authentik-forwardauth@file"
|
||||
- "traefik.http.services.nats-monitor.loadbalancer.server.port=8222"
|
||||
|
||||
30
infra/base/loki/loki.yml
Normal file
30
infra/base/loki/loki.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
auth_enabled: false
|
||||
|
||||
server:
|
||||
http_listen_port: 3100
|
||||
grpc_listen_port: 9096
|
||||
|
||||
common:
|
||||
instance_addr: 127.0.0.1
|
||||
path_prefix: /loki
|
||||
storage:
|
||||
filesystem:
|
||||
chunks_directory: /loki/chunks
|
||||
rules_directory: /loki/rules
|
||||
replication_factor: 1
|
||||
ring:
|
||||
kvstore:
|
||||
store: inmemory
|
||||
|
||||
schema_config:
|
||||
configs:
|
||||
- from: 2020-10-24
|
||||
store: boltdb-shipper
|
||||
object_store: filesystem
|
||||
schema: v11
|
||||
index:
|
||||
prefix: index_
|
||||
period: 24h
|
||||
|
||||
ruler:
|
||||
alertmanager_url: http://localhost:9093
|
||||
26
infra/base/loki/promtail-config.yml
Normal file
26
infra/base/loki/promtail-config.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
server:
|
||||
http_listen_port: 9080
|
||||
grpc_listen_port: 0
|
||||
|
||||
positions:
|
||||
filename: /tmp/positions.yaml
|
||||
|
||||
clients:
|
||||
- url: http://apa-loki:3100/loki/api/v1/push
|
||||
|
||||
scrape_configs:
|
||||
- job_name: system
|
||||
static_configs:
|
||||
- targets:
|
||||
- localhost
|
||||
labels:
|
||||
job: varlogs
|
||||
__path__: /var/log/*log
|
||||
|
||||
- job_name: docker
|
||||
static_configs:
|
||||
- targets:
|
||||
- localhost
|
||||
labels:
|
||||
job: docker
|
||||
__path__: /var/lib/docker/containers/*/*-json.log
|
||||
@@ -39,7 +39,7 @@ services:
|
||||
- "traefik.http.routers.prometheus.rule=Host(`prometheus.${DOMAIN}`)"
|
||||
- "traefik.http.routers.prometheus.entrypoints=websecure"
|
||||
- "traefik.http.routers.prometheus.tls=true"
|
||||
- "traefik.http.routers.prometheus.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.prometheus.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.prometheus.middlewares=authentik-forwardauth@file"
|
||||
- "traefik.http.services.prometheus.loadbalancer.server.port=9090"
|
||||
|
||||
@@ -80,12 +80,19 @@ services:
|
||||
GF_SECURITY_COOKIE_SECURE: true
|
||||
GF_SECURITY_COOKIE_SAMESITE: lax
|
||||
GF_AUTH_GENERIC_OAUTH_USE_PKCE: true
|
||||
GF_AUTH_GENERIC_OAUTH_TLS_SKIP_VERIFY_INSECURE: true
|
||||
GF_AUTH_SIGNOUT_REDIRECT_URL: https://auth.${DOMAIN}/application/o/grafana/end-session/
|
||||
extra_hosts:
|
||||
- "auth.local.lan:host-gateway"
|
||||
- "grafana.local.lan:host-gateway"
|
||||
- "api.local.lan:host-gateway"
|
||||
- "traefik.local.lan:host-gateway"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.grafana.rule=Host(`grafana.${DOMAIN}`)"
|
||||
- "traefik.http.routers.grafana.entrypoints=websecure"
|
||||
- "traefik.http.routers.grafana.tls=true"
|
||||
- "traefik.http.routers.grafana.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.grafana.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.services.grafana.loadbalancer.server.port=3000"
|
||||
|
||||
# Log Aggregation
|
||||
@@ -105,7 +112,7 @@ services:
|
||||
- "traefik.http.routers.loki.rule=Host(`loki.${DOMAIN}`)"
|
||||
- "traefik.http.routers.loki.entrypoints=websecure"
|
||||
- "traefik.http.routers.loki.tls=true"
|
||||
- "traefik.http.routers.loki.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.loki.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.loki.middlewares=authentik-forwardauth@file"
|
||||
- "traefik.http.services.loki.loadbalancer.server.port=3100"
|
||||
|
||||
|
||||
21
infra/base/prometheus/prometheus.yml
Normal file
21
infra/base/prometheus/prometheus.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: "prometheus"
|
||||
static_configs:
|
||||
- targets: ["localhost:9090"]
|
||||
|
||||
- job_name: "traefik"
|
||||
static_configs:
|
||||
- targets: ["apa-traefik:8080"]
|
||||
|
||||
- job_name: "services"
|
||||
static_configs:
|
||||
- targets:
|
||||
- "apa-svc-ingestion:8000"
|
||||
- "apa-svc-extract:8000"
|
||||
- "apa-svc-kg:8000"
|
||||
- "apa-svc-rag-retriever:8000"
|
||||
- "apa-svc-rag-indexer:8000"
|
||||
@@ -40,8 +40,8 @@ services:
|
||||
- "traefik.http.routers.svc-ingestion.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/ingestion`)"
|
||||
- "traefik.http.routers.svc-ingestion.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-ingestion.tls=true"
|
||||
- "traefik.http.routers.svc-ingestion.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-ingestion.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-ingestion.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-ingestion.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-ingestion.loadbalancer.server.port=8000"
|
||||
|
||||
# Data Extraction Service
|
||||
@@ -73,8 +73,8 @@ services:
|
||||
- "traefik.http.routers.svc-extract.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/extract`)"
|
||||
- "traefik.http.routers.svc-extract.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-extract.tls=true"
|
||||
- "traefik.http.routers.svc-extract.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-extract.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-extract.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-extract.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-extract.loadbalancer.server.port=8000"
|
||||
|
||||
# Knowledge Graph Service
|
||||
@@ -100,8 +100,8 @@ services:
|
||||
- "traefik.http.routers.svc-kg.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/kg`)"
|
||||
- "traefik.http.routers.svc-kg.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-kg.tls=true"
|
||||
- "traefik.http.routers.svc-kg.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-kg.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-kg.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-kg.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-kg.loadbalancer.server.port=8000"
|
||||
|
||||
# RAG Retrieval Service
|
||||
@@ -130,8 +130,8 @@ services:
|
||||
- "traefik.http.routers.svc-rag-retriever.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/rag`)"
|
||||
- "traefik.http.routers.svc-rag-retriever.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-rag-retriever.tls=true"
|
||||
- "traefik.http.routers.svc-rag-retriever.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-rag-retriever.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-rag-retriever.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-rag-retriever.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-rag-retriever.loadbalancer.server.port=8000"
|
||||
|
||||
# Forms Service
|
||||
@@ -163,8 +163,8 @@ services:
|
||||
- "traefik.http.routers.svc-forms.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/forms`)"
|
||||
- "traefik.http.routers.svc-forms.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-forms.tls=true"
|
||||
- "traefik.http.routers.svc-forms.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-forms.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-forms.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-forms.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-forms.loadbalancer.server.port=8000"
|
||||
|
||||
# HMRC Integration Service
|
||||
@@ -197,8 +197,8 @@ services:
|
||||
- "traefik.http.routers.svc-hmrc.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/hmrc`)"
|
||||
- "traefik.http.routers.svc-hmrc.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-hmrc.tls=true"
|
||||
- "traefik.http.routers.svc-hmrc.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-hmrc.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-hmrc.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-hmrc.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-hmrc.loadbalancer.server.port=8000"
|
||||
|
||||
# OCR Service
|
||||
@@ -230,8 +230,8 @@ services:
|
||||
- "traefik.http.routers.svc-ocr.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/ocr`)"
|
||||
- "traefik.http.routers.svc-ocr.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-ocr.tls=true"
|
||||
- "traefik.http.routers.svc-ocr.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-ocr.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-ocr.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-ocr.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-ocr.loadbalancer.server.port=8000"
|
||||
|
||||
# RAG Indexer Service
|
||||
@@ -263,8 +263,8 @@ services:
|
||||
- "traefik.http.routers.svc-rag-indexer.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/rag-indexer`)"
|
||||
- "traefik.http.routers.svc-rag-indexer.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-rag-indexer.tls=true"
|
||||
- "traefik.http.routers.svc-rag-indexer.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-rag-indexer.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-rag-indexer.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-rag-indexer.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-rag-indexer.loadbalancer.server.port=8000"
|
||||
|
||||
# Reasoning Service
|
||||
@@ -296,8 +296,8 @@ services:
|
||||
- "traefik.http.routers.svc-reason.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/reason`)"
|
||||
- "traefik.http.routers.svc-reason.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-reason.tls=true"
|
||||
- "traefik.http.routers.svc-reason.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-reason.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-reason.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-reason.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-reason.loadbalancer.server.port=8000"
|
||||
|
||||
# RPA Service
|
||||
@@ -329,8 +329,8 @@ services:
|
||||
- "traefik.http.routers.svc-rpa.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/rpa`)"
|
||||
- "traefik.http.routers.svc-rpa.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-rpa.tls=true"
|
||||
- "traefik.http.routers.svc-rpa.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-rpa.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-rpa.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-rpa.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-rpa.loadbalancer.server.port=8000"
|
||||
|
||||
# Normalize & Map Service
|
||||
@@ -362,8 +362,8 @@ services:
|
||||
- "traefik.http.routers.svc-normalize-map.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/normalize-map`)"
|
||||
- "traefik.http.routers.svc-normalize-map.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-normalize-map.tls=true"
|
||||
- "traefik.http.routers.svc-normalize-map.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-normalize-map.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-normalize-map.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-normalize-map.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-normalize-map.loadbalancer.server.port=8000"
|
||||
|
||||
# Coverage Service
|
||||
@@ -395,8 +395,8 @@ services:
|
||||
- "traefik.http.routers.svc-coverage.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/coverage`)"
|
||||
- "traefik.http.routers.svc-coverage.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-coverage.tls=true"
|
||||
- "traefik.http.routers.svc-coverage.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-coverage.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-coverage.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-coverage.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-coverage.loadbalancer.server.port=8000"
|
||||
|
||||
# Firm Connectors Service
|
||||
@@ -428,8 +428,8 @@ services:
|
||||
- "traefik.http.routers.svc-firm-connectors.rule=Host(`api.${DOMAIN}`) && PathPrefix(`/firm-connectors`)"
|
||||
- "traefik.http.routers.svc-firm-connectors.entrypoints=websecure"
|
||||
- "traefik.http.routers.svc-firm-connectors.tls=true"
|
||||
- "traefik.http.routers.svc-firm-connectors.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.svc-firm-connectors.middlewares=authentik-forwardauth@file,rate-limit@file"
|
||||
- "traefik.http.routers.svc-firm-connectors.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.svc-firm-connectors.middlewares=authentik-forwardauth@file,rate-limit@file,strip-api-prefixes@file"
|
||||
- "traefik.http.services.svc-firm-connectors.loadbalancer.server.port=8000"
|
||||
|
||||
# Review UI
|
||||
@@ -448,6 +448,6 @@ services:
|
||||
- "traefik.http.routers.ui-review.rule=Host(`app.${DOMAIN}`)"
|
||||
- "traefik.http.routers.ui-review.entrypoints=websecure"
|
||||
- "traefik.http.routers.ui-review.tls=true"
|
||||
- "traefik.http.routers.ui-review.tls.certresolver=godaddy"
|
||||
- "traefik.http.routers.ui-review.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
|
||||
- "traefik.http.routers.ui-review.middlewares=authentik-forwardauth@file"
|
||||
- "traefik.http.services.ui-review.loadbalancer.server.port=3030"
|
||||
|
||||
@@ -1,133 +1,23 @@
|
||||
# External Services
|
||||
# Compose Stacks
|
||||
|
||||
This directory contains Docker Compose configurations for external services that run on the production server.
|
||||
This folder is for the self-contained local stack (self-signed TLS) and Traefik assets. Remote environments use the shared compose files in `infra/base` together with `infra/scripts/deploy.sh`.
|
||||
|
||||
## Services
|
||||
## Local development (self-signed TLS)
|
||||
- Copy envs: `cp infra/compose/env.example infra/compose/.env` then set passwords/secrets and the dev domain (defaults to `local.lan`).
|
||||
- Host aliases: add the domain to `/etc/hosts` (e.g. `127.0.0.1 auth.local.lan api.local.lan grafana.local.lan vault.local.lan minio.local.lan`).
|
||||
- Networks: `./infra/scripts/setup-networks.sh` (creates `apa-frontend` and `apa-backend` used everywhere).
|
||||
- Run: `cd infra/compose && docker compose --env-file .env -f docker-compose.local.yml up -d`.
|
||||
- Stop: `docker compose --env-file .env -f docker-compose.local.yml down`.
|
||||
- TLS: Traefik mounts `infra/compose/traefik/certs/local.{crt,key}`. Regenerate if needed with `openssl req -x509 -newkey rsa:2048 -nodes -keyout infra/compose/traefik/certs/local.key -out infra/compose/traefik/certs/local.crt -days 365 -subj "/CN=*.local.lan"`.
|
||||
|
||||
### Traefik
|
||||
- **Location**: `traefik/`
|
||||
- **Purpose**: Reverse proxy and load balancer for all services
|
||||
- **Deploy**: `cd traefik && docker compose up -d`
|
||||
- **Access**: https://traefik.harkon.co.uk
|
||||
## Cloud / remote (Let’s Encrypt)
|
||||
- Config lives in `infra/base` with env files in `infra/environments/{development,production}/.env`.
|
||||
- Create the same docker networks on the host (`./infra/scripts/setup-networks.sh`) so Traefik and services share `apa-frontend` / `apa-backend`.
|
||||
- Deploy on the server: `./infra/scripts/deploy.sh <environment> all` (or `infrastructure`, `monitoring`, `services`).
|
||||
- Certificates: Traefik uses DNS-01 via GoDaddy from the provider env in `infra/base/traefik/config` (make sure `DOMAIN`, ACME email, and provider creds are set in the env file).
|
||||
|
||||
### Authentik
|
||||
- **Location**: `authentik/`
|
||||
- **Purpose**: SSO and authentication provider
|
||||
- **Deploy**: `cd authentik && docker compose up -d`
|
||||
- **Access**: https://authentik.harkon.co.uk
|
||||
|
||||
### Gitea
|
||||
- **Location**: `gitea/`
|
||||
- **Purpose**: Git repository hosting and container registry
|
||||
- **Deploy**: `cd gitea && docker compose up -d`
|
||||
- **Access**: https://gitea.harkon.co.uk
|
||||
|
||||
### Nextcloud
|
||||
- **Location**: `nextcloud/`
|
||||
- **Purpose**: File storage and collaboration
|
||||
- **Deploy**: `cd nextcloud && docker compose up -d`
|
||||
- **Access**: https://nextcloud.harkon.co.uk
|
||||
|
||||
### Portainer
|
||||
- **Location**: `portainer/`
|
||||
- **Purpose**: Docker management UI
|
||||
- **Deploy**: `cd portainer && docker compose up -d`
|
||||
- **Access**: https://portainer.harkon.co.uk
|
||||
|
||||
## Deployment
|
||||
|
||||
### Production (Remote Server)
|
||||
|
||||
```bash
|
||||
# SSH to server
|
||||
ssh deploy@141.136.35.199
|
||||
|
||||
# Navigate to service directory
|
||||
cd /opt/ai-tax-agent/infra/compose/<service>
|
||||
|
||||
# Deploy service
|
||||
docker compose up -d
|
||||
|
||||
# Check logs
|
||||
docker compose logs -f
|
||||
|
||||
# Check status
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
### Local Development
|
||||
|
||||
For local development, use the all-in-one compose file:
|
||||
|
||||
```bash
|
||||
cd infra/compose
|
||||
docker compose -f docker-compose.local.yml up -d
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Each service has its own `.env` file for environment-specific configuration:
|
||||
|
||||
- `traefik/.provider.env` - GoDaddy API credentials
|
||||
- `authentik/.env` - Authentik secrets
|
||||
- `gitea/.env` - Gitea database credentials
|
||||
|
||||
## Networks
|
||||
|
||||
All services use shared Docker networks:
|
||||
|
||||
- `frontend` - Public-facing services
|
||||
- `backend` - Internal services
|
||||
|
||||
Create networks before deploying:
|
||||
|
||||
```bash
|
||||
docker network create frontend
|
||||
docker network create backend
|
||||
```
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Update Service
|
||||
|
||||
```bash
|
||||
cd /opt/ai-tax-agent/infra/compose/<service>
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Restart Service
|
||||
|
||||
```bash
|
||||
cd /opt/ai-tax-agent/infra/compose/<service>
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
cd /opt/ai-tax-agent/infra/compose/<service>
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
### Backup Data
|
||||
|
||||
```bash
|
||||
# Backup volumes
|
||||
docker run --rm -v <service>_data:/data -v $(pwd):/backup alpine tar czf /backup/<service>-backup.tar.gz /data
|
||||
```
|
||||
|
||||
## Integration with Application
|
||||
|
||||
These external services are used by the application infrastructure:
|
||||
|
||||
- **Traefik** - Routes traffic to application services
|
||||
- **Authentik** - Provides SSO for application UIs
|
||||
- **Gitea** - Hosts Docker images for application services
|
||||
|
||||
The application infrastructure is deployed separately using:
|
||||
|
||||
```bash
|
||||
./infra/scripts/deploy.sh production infrastructure
|
||||
./infra/scripts/deploy.sh production services
|
||||
```
|
||||
## Files of note
|
||||
- `docker-compose.local.yml` – full local stack.
|
||||
- `traefik/traefik.local.yml` and `traefik/traefik-dynamic.local.yml` – static/dynamic Traefik config for local.
|
||||
- `traefik/certs/` – self-signed certs used by the local proxy.
|
||||
- `env.example` – defaults for local `.env`.
|
||||
|
||||
156
infra/compose/compose.override.yaml
Normal file
156
infra/compose/compose.override.yaml
Normal file
@@ -0,0 +1,156 @@
|
||||
# FILE: infra/compose/compose.override.yaml
|
||||
# Local development overrides
|
||||
# Automatically loaded by docker compose when compose.yaml is present
|
||||
|
||||
services:
|
||||
# --- Infrastructure Overrides ---
|
||||
|
||||
apa-traefik:
|
||||
volumes:
|
||||
- ./traefik/traefik.local.yml:/etc/traefik/traefik.yml:ro
|
||||
- ./traefik/traefik-dynamic.local.yml:/etc/traefik/traefik-dynamic.yml:ro
|
||||
- ./traefik/certs/:/var/traefik/certs/:ro
|
||||
ports:
|
||||
- "8080:8080" # Dashboard (admin entrypoint, insecure mode only for local)
|
||||
|
||||
apa-authentik-server:
|
||||
environment:
|
||||
AUTHENTIK_ERROR_REPORTING__ENABLED: "false"
|
||||
DOMAIN: ${DOMAIN:-local.lan}
|
||||
GRAFANA_OAUTH_CLIENT_ID: ${GRAFANA_OAUTH_CLIENT_ID}
|
||||
GRAFANA_OAUTH_CLIENT_SECRET: ${GRAFANA_OAUTH_CLIENT_SECRET}
|
||||
AUTHENTIK_MINIO_CLIENT_SECRET: ${AUTHENTIK_MINIO_CLIENT_SECRET}
|
||||
AUTHENTIK_VAULT_CLIENT_SECRET: ${AUTHENTIK_VAULT_CLIENT_SECRET}
|
||||
AUTHENTIK_OUTPOST_TOKEN: ${AUTHENTIK_OUTPOST_TOKEN}
|
||||
volumes:
|
||||
- ../authentik/bootstrap.yaml:/blueprints/ai-tax-agent-bootstrap.yaml:ro
|
||||
|
||||
apa-authentik-worker:
|
||||
environment:
|
||||
DOMAIN: ${DOMAIN:-local.lan}
|
||||
GRAFANA_OAUTH_CLIENT_ID: ${GRAFANA_OAUTH_CLIENT_ID}
|
||||
GRAFANA_OAUTH_CLIENT_SECRET: ${GRAFANA_OAUTH_CLIENT_SECRET}
|
||||
AUTHENTIK_MINIO_CLIENT_SECRET: ${AUTHENTIK_MINIO_CLIENT_SECRET}
|
||||
AUTHENTIK_VAULT_CLIENT_SECRET: ${AUTHENTIK_VAULT_CLIENT_SECRET}
|
||||
AUTHENTIK_OUTPOST_TOKEN: ${AUTHENTIK_OUTPOST_TOKEN}
|
||||
volumes:
|
||||
- ../authentik/bootstrap.yaml:/blueprints/ai-tax-agent-bootstrap.yaml:ro
|
||||
|
||||
apa-vault:
|
||||
volumes:
|
||||
- ./traefik/certs/:/certs:ro
|
||||
|
||||
# --- Service Build Overrides ---
|
||||
# Pointing to local source code for building
|
||||
|
||||
apa-svc-ingestion:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_ingestion/Dockerfile
|
||||
image: ai-tax-agent/svc-ingestion:local
|
||||
pull_policy: never
|
||||
|
||||
apa-svc-extract:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_extract/Dockerfile
|
||||
image: ai-tax-agent/svc-extract:local
|
||||
pull_policy: never
|
||||
|
||||
apa-svc-kg:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_kg/Dockerfile
|
||||
image: ai-tax-agent/svc-kg:local
|
||||
pull_policy: never
|
||||
|
||||
apa-svc-rag-retriever:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_rag_retriever/Dockerfile
|
||||
image: ai-tax-agent/svc-rag-retriever:local
|
||||
pull_policy: never
|
||||
|
||||
apa-svc-forms:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_forms/Dockerfile
|
||||
image: ai-tax-agent/svc-forms:local
|
||||
pull_policy: never
|
||||
|
||||
apa-svc-hmrc:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_hmrc/Dockerfile
|
||||
image: ai-tax-agent/svc-hmrc:local
|
||||
pull_policy: never
|
||||
|
||||
apa-svc-ocr:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_ocr/Dockerfile
|
||||
image: ai-tax-agent/svc-ocr:local
|
||||
pull_policy: never
|
||||
restart: on-failure
|
||||
|
||||
apa-svc-rag-indexer:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_rag_indexer/Dockerfile
|
||||
image: ai-tax-agent/svc-rag-indexer:local
|
||||
pull_policy: never
|
||||
|
||||
apa-svc-reason:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_reason/Dockerfile
|
||||
image: ai-tax-agent/svc-reason:local
|
||||
pull_policy: never
|
||||
|
||||
apa-svc-rpa:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_rpa/Dockerfile
|
||||
image: ai-tax-agent/svc-rpa:local
|
||||
pull_policy: never
|
||||
|
||||
apa-svc-normalize-map:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_normalize_map/Dockerfile
|
||||
image: ai-tax-agent/svc-normalize-map:local
|
||||
pull_policy: never
|
||||
|
||||
apa-svc-coverage:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_coverage/Dockerfile
|
||||
image: ai-tax-agent/svc-coverage:local
|
||||
pull_policy: never
|
||||
|
||||
apa-svc-firm-connectors:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: apps/svc_firm_connectors/Dockerfile
|
||||
image: ai-tax-agent/svc-firm-connectors:local
|
||||
pull_policy: never
|
||||
|
||||
apa-ui-review:
|
||||
# UI might not have a Dockerfile in root/ui-review/Dockerfile based on previous file view
|
||||
# Assuming standard build context if it exists, otherwise comment out build
|
||||
# build:
|
||||
# context: ../../ui-review
|
||||
# dockerfile: Dockerfile
|
||||
image: alpine:latest
|
||||
profiles: ["disabled"]
|
||||
environment:
|
||||
- NEXTAUTH_URL=https://app.local.lan
|
||||
- API_BASE_URL=https://api.local.lan
|
||||
|
||||
apa-minio:
|
||||
volumes:
|
||||
- ./traefik/certs/local.crt:/root/.minio/certs/CAs/local.crt:ro
|
||||
|
||||
# --- Local Development Specific Services ---
|
||||
# Services that only exist in local dev (e.g. mailhog if used, or specific tools)
|
||||
# None identified from docker-compose.local.yml that aren't in base
|
||||
14
infra/compose/compose.yaml
Normal file
14
infra/compose/compose.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
# FILE: infra/compose/compose.yaml
|
||||
# Main entry point for Docker Compose
|
||||
# Includes base configurations from infra/base/
|
||||
|
||||
include:
|
||||
- ../base/infrastructure.yaml
|
||||
- ../base/services.yaml
|
||||
# Monitoring stack is optional for local dev but included for completeness
|
||||
# Can be disabled via profiles if needed, but keeping simple for now
|
||||
- ../base/monitoring.yaml
|
||||
|
||||
# Define project name to match existing convention if needed,
|
||||
# though 'compose' directory name usually defaults to 'compose'
|
||||
name: ai-tax-agent
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
# FILE: infra/compose/env.example
|
||||
|
||||
# Domain Configuration
|
||||
DOMAIN=local
|
||||
DOMAIN=local.lan
|
||||
EMAIL=admin@local.lan
|
||||
|
||||
# Database Passwords
|
||||
@@ -26,6 +26,7 @@ AUTHENTIK_SECRET_KEY=changeme
|
||||
AUTHENTIK_OUTPOST_TOKEN=changeme
|
||||
AUTHENTIK_BOOTSTRAP_EMAIL=admin@local.lan
|
||||
AUTHENTIK_BOOTSTRAP_PASSWORD=admin123
|
||||
# AUTHENTIK_BOOTSTRAP_TOKEN: This value will be automatically updated after the initial setup.
|
||||
AUTHENTIK_BOOTSTRAP_TOKEN=
|
||||
|
||||
# Monitoring
|
||||
@@ -80,7 +81,7 @@ PII_LOG_RETENTION_DAYS=30
|
||||
|
||||
# Backup & DR
|
||||
BACKUP_ENABLED=true
|
||||
BACKUP_SCHEDULE=0 2 * * *
|
||||
BACKUP_SCHEDULE="0 2 * * *"
|
||||
BACKUP_RETENTION_DAYS=30
|
||||
|
||||
# Performance Tuning
|
||||
|
||||
89
infra/compose/traefik/traefik-dynamic.local.yml
Normal file
89
infra/compose/traefik/traefik-dynamic.local.yml
Normal file
@@ -0,0 +1,89 @@
|
||||
http:
|
||||
middlewares:
|
||||
authentik-forwardauth:
|
||||
forwardAuth:
|
||||
address: "http://apa-authentik-outpost:9000/outpost.goauthentik.io/auth/traefik"
|
||||
trustForwardHeader: true
|
||||
authResponseHeaders:
|
||||
- X-authentik-username
|
||||
- X-authentik-groups
|
||||
- X-authentik-email
|
||||
- X-authentik-name
|
||||
- X-authentik-uid
|
||||
- X-authentik-jwt
|
||||
- X-authentik-meta-jwks
|
||||
- X-authentik-meta-outpost
|
||||
- X-authentik-meta-provider
|
||||
- X-authentik-meta-app
|
||||
- X-authentik-meta-version
|
||||
|
||||
# Large upload middleware for Gitea registry
|
||||
gitea-large-upload:
|
||||
buffering:
|
||||
maxRequestBodyBytes: 5368709120 # 5GB
|
||||
memRequestBodyBytes: 104857600 # 100MB
|
||||
maxResponseBodyBytes: 5368709120 # 5GB
|
||||
memResponseBodyBytes: 104857600 # 100MB
|
||||
retryExpression: "IsNetworkError() && Attempts() < 3"
|
||||
|
||||
# Rate limiting for public APIs
|
||||
rate-limit:
|
||||
rateLimit:
|
||||
average: 100
|
||||
burst: 50
|
||||
period: 1s
|
||||
|
||||
# Security headers
|
||||
security-headers:
|
||||
headers:
|
||||
frameDeny: true
|
||||
sslRedirect: true
|
||||
browserXssFilter: true
|
||||
contentTypeNosniff: true
|
||||
stsIncludeSubdomains: true
|
||||
stsPreload: true
|
||||
stsSeconds: 31536000
|
||||
|
||||
# CORS headers
|
||||
api-cors:
|
||||
headers:
|
||||
accessControlAllowMethods:
|
||||
- GET
|
||||
- POST
|
||||
- PUT
|
||||
- DELETE
|
||||
- OPTIONS
|
||||
accessControlAllowOriginList:
|
||||
- "https://app.harkon.co.uk"
|
||||
accessControlAllowHeaders:
|
||||
- "Content-Type"
|
||||
- "Authorization"
|
||||
accessControlMaxAge: 100
|
||||
addVaryHeader: true
|
||||
|
||||
# Strip API prefixes
|
||||
strip-api-prefixes:
|
||||
stripPrefix:
|
||||
prefixes:
|
||||
- "/rag-indexer"
|
||||
- "/firm-connectors"
|
||||
- "/normalize-map"
|
||||
- "/ingestion"
|
||||
- "/extract"
|
||||
- "/forms"
|
||||
- "/hmrc"
|
||||
- "/ocr"
|
||||
- "/reason"
|
||||
- "/rpa"
|
||||
- "/coverage"
|
||||
- "/kg"
|
||||
- "/rag"
|
||||
|
||||
tls:
|
||||
certificates:
|
||||
- certFile: /var/traefik/certs/local.crt
|
||||
keyFile: /var/traefik/certs/local.key
|
||||
options:
|
||||
default:
|
||||
minVersion: VersionTLS12
|
||||
sniStrict: false
|
||||
35
infra/compose/traefik/traefik.local.yml
Normal file
35
infra/compose/traefik/traefik.local.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
# Traefik static configuration for local development (self-signed TLS)
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":80"
|
||||
http:
|
||||
redirections:
|
||||
entryPoint:
|
||||
to: websecure
|
||||
scheme: https
|
||||
websecure:
|
||||
address: ":443"
|
||||
http:
|
||||
tls:
|
||||
options: default
|
||||
|
||||
providers:
|
||||
docker:
|
||||
endpoint: "unix:///var/run/docker.sock"
|
||||
exposedByDefault: false
|
||||
network: "apa-frontend"
|
||||
file:
|
||||
filename: "/etc/traefik/traefik-dynamic.yml"
|
||||
watch: true
|
||||
|
||||
api:
|
||||
dashboard: true
|
||||
insecure: true
|
||||
|
||||
serversTransport:
|
||||
insecureSkipVerify: true
|
||||
|
||||
log:
|
||||
level: INFO
|
||||
|
||||
accessLog: {}
|
||||
8
infra/postgres/init/unleash.sh
Executable file
8
infra/postgres/init/unleash.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
CREATE USER unleash WITH PASSWORD '${UNLEASH_DB_PASSWORD:-unleash}';
|
||||
CREATE DATABASE unleash;
|
||||
GRANT ALL PRIVILEGES ON DATABASE unleash TO unleash;
|
||||
EOSQL
|
||||
@@ -112,6 +112,18 @@ echo ""
|
||||
compose_cmd() {
|
||||
local file=$1
|
||||
shift
|
||||
|
||||
# For local environment, use the new unified compose.yaml
|
||||
if [ "$ENVIRONMENT" = "local" ] && [ "$file" = "all" ]; then
|
||||
docker compose -f "$INFRA_DIR/compose/compose.yaml" -f "$INFRA_DIR/compose/compose.override.yaml" --env-file "$ENV_FILE" --project-name "ai-tax-agent" "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
# For other environments or specific stacks, keep existing behavior for now
|
||||
# or adapt as needed. The goal is to eventually unify everything.
|
||||
# If file is 'infrastructure.yaml', etc., we might still want to use base/
|
||||
# directly for production to avoid local overrides.
|
||||
|
||||
docker compose -f "$BASE_DIR/$file" --env-file "$ENV_FILE" --project-name "ai-tax-agent-$ENVIRONMENT" "$@"
|
||||
}
|
||||
|
||||
@@ -139,7 +151,7 @@ deploy_services() {
|
||||
# Deploy external services stack
|
||||
deploy_external() {
|
||||
log_info "Deploying external services stack..."
|
||||
|
||||
|
||||
if [ "$ENVIRONMENT" = "production" ] || [ "$ENVIRONMENT" = "development" ]; then
|
||||
log_warning "External services (Traefik, Authentik, Gitea) may already exist on this server"
|
||||
read -p "Do you want to deploy external services? (y/N) " -n 1 -r
|
||||
@@ -149,7 +161,7 @@ deploy_external() {
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
compose_cmd "external.yaml" up -d "$@"
|
||||
log_success "External services stack deployed"
|
||||
}
|
||||
@@ -157,50 +169,55 @@ deploy_external() {
|
||||
# Stop all stacks
|
||||
stop_all() {
|
||||
log_info "Stopping all stacks..."
|
||||
|
||||
|
||||
if [ -f "$BASE_DIR/services.yaml" ]; then
|
||||
compose_cmd "services.yaml" down
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "$BASE_DIR/monitoring.yaml" ]; then
|
||||
compose_cmd "monitoring.yaml" down
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "$BASE_DIR/infrastructure.yaml" ]; then
|
||||
compose_cmd "infrastructure.yaml" down
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "$BASE_DIR/external.yaml" ]; then
|
||||
log_warning "External services not stopped (may be shared)"
|
||||
fi
|
||||
|
||||
|
||||
log_success "All stacks stopped"
|
||||
}
|
||||
|
||||
# Deploy all stacks
|
||||
deploy_all() {
|
||||
log_info "Deploying all stacks..."
|
||||
|
||||
|
||||
# Check if networks exist
|
||||
if ! docker network inspect apa-frontend >/dev/null 2>&1; then
|
||||
log_warning "Network 'apa-frontend' does not exist. Creating..."
|
||||
docker network create apa-frontend
|
||||
fi
|
||||
|
||||
|
||||
if ! docker network inspect apa-backend >/dev/null 2>&1; then
|
||||
log_warning "Network 'apa-backend' does not exist. Creating..."
|
||||
docker network create apa-backend
|
||||
fi
|
||||
|
||||
|
||||
# Deploy in order
|
||||
deploy_infrastructure "$@"
|
||||
sleep 5
|
||||
|
||||
deploy_monitoring "$@"
|
||||
sleep 5
|
||||
|
||||
deploy_services "$@"
|
||||
|
||||
if [ "$ENVIRONMENT" = "local" ]; then
|
||||
log_info "Deploying unified stack for local environment..."
|
||||
compose_cmd "all" up -d "$@"
|
||||
else
|
||||
deploy_infrastructure "$@"
|
||||
sleep 5
|
||||
|
||||
deploy_monitoring "$@"
|
||||
sleep 5
|
||||
|
||||
deploy_services "$@"
|
||||
fi
|
||||
|
||||
log_success "All stacks deployed successfully!"
|
||||
echo ""
|
||||
log_info "Access your services:"
|
||||
|
||||
16
infra/traefik/certs/godaddy-acme.json
Normal file
16
infra/traefik/certs/godaddy-acme.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"godaddy": {
|
||||
"Account": {
|
||||
"Email": "info@harkon.co.uk",
|
||||
"Registration": {
|
||||
"body": {
|
||||
"status": "valid"
|
||||
},
|
||||
"uri": "https://acme-v02.api.letsencrypt.org/acme/acct/2826907666"
|
||||
},
|
||||
"PrivateKey": "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",
|
||||
"KeyType": "4096"
|
||||
},
|
||||
"Certificates": null
|
||||
}
|
||||
}
|
||||
64
infra/traefik/config/traefik-dynamic.yml
Normal file
64
infra/traefik/config/traefik-dynamic.yml
Normal file
@@ -0,0 +1,64 @@
|
||||
http:
|
||||
middlewares:
|
||||
authentik-forwardauth:
|
||||
forwardAuth:
|
||||
address: "http://apa-authentik-outpost:9000/outpost.goauthentik.io/auth/traefik"
|
||||
trustForwardHeader: true
|
||||
authResponseHeaders:
|
||||
- X-authentik-username
|
||||
- X-authentik-groups
|
||||
- X-authentik-email
|
||||
- X-authentik-name
|
||||
- X-authentik-uid
|
||||
- X-authentik-jwt
|
||||
- X-authentik-meta-jwks
|
||||
- X-authentik-meta-outpost
|
||||
- X-authentik-meta-provider
|
||||
- X-authentik-meta-app
|
||||
- X-authentik-meta-version
|
||||
|
||||
# Large upload middleware for Gitea registry
|
||||
gitea-large-upload:
|
||||
buffering:
|
||||
maxRequestBodyBytes: 5368709120 # 5GB
|
||||
memRequestBodyBytes: 104857600 # 100MB
|
||||
maxResponseBodyBytes: 5368709120 # 5GB
|
||||
memResponseBodyBytes: 104857600 # 100MB
|
||||
retryExpression: "IsNetworkError() && Attempts() < 3"
|
||||
|
||||
# Rate limiting for public APIs
|
||||
api-ratelimit:
|
||||
rateLimit:
|
||||
average: 100
|
||||
burst: 50
|
||||
period: 1s
|
||||
|
||||
# Security headers
|
||||
security-headers:
|
||||
headers:
|
||||
frameDeny: true
|
||||
sslRedirect: true
|
||||
browserXssFilter: true
|
||||
contentTypeNosniff: true
|
||||
stsIncludeSubdomains: true
|
||||
stsPreload: true
|
||||
stsSeconds: 31536000
|
||||
|
||||
# CORS headers
|
||||
api-cors:
|
||||
headers:
|
||||
accessControlAllowMethods:
|
||||
- GET
|
||||
- POST
|
||||
- PUT
|
||||
- DELETE
|
||||
- OPTIONS
|
||||
accessControlAllowOriginList:
|
||||
- "https://app.harkon.co.uk"
|
||||
accessControlAllowHeaders:
|
||||
- "Content-Type"
|
||||
- "Authorization"
|
||||
accessControlMaxAge: 100
|
||||
addVaryHeader: true
|
||||
|
||||
# Security headers
|
||||
35
infra/traefik/config/traefik.yml
Normal file
35
infra/traefik/config/traefik.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
# Static Traefik configuration (production)
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":80"
|
||||
websecure:
|
||||
address: ":443"
|
||||
transport:
|
||||
respondingTimeouts:
|
||||
readTimeout: 30m
|
||||
api:
|
||||
dashboard: true
|
||||
|
||||
providers:
|
||||
docker:
|
||||
endpoint: "unix:///var/run/docker.sock"
|
||||
exposedByDefault: false
|
||||
network: "apa-frontend"
|
||||
file:
|
||||
filename: "/etc/traefik/traefik-dynamic.yml"
|
||||
watch: true
|
||||
|
||||
# -- Configure your CertificateResolver here...
|
||||
certificatesResolvers:
|
||||
godaddy:
|
||||
acme:
|
||||
email: info@harkon.co.uk
|
||||
storage: /var/traefik/certs/godaddy-acme.json
|
||||
caServer: "https://acme-v02.api.letsencrypt.org/directory"
|
||||
dnsChallenge:
|
||||
provider: godaddy
|
||||
resolvers:
|
||||
- 1.1.1.1:53
|
||||
- 8.8.8.8:53
|
||||
- 97.74.103.44:53
|
||||
- 173.201.71.44:53
|
||||
Reference in New Issue
Block a user