diff --git a/deploy/local/kratos/identity.schema.json b/deploy/local/kratos/identity.schema.json new file mode 100644 index 0000000..0eb69bb --- /dev/null +++ b/deploy/local/kratos/identity.schema.json @@ -0,0 +1,39 @@ +{ + "$id": "https://honeydue.app/identity.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "honeyDue user", + "type": "object", + "properties": { + "traits": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "title": "Email", + "minLength": 3, + "maxLength": 320, + "ory.sh/kratos": { + "credentials": { + "password": { "identifier": true }, + "code": { "identifier": true, "via": "email" }, + "totp": { "account_name": true } + }, + "verification": { "via": "email" }, + "recovery": { "via": "email" } + } + }, + "name": { + "type": "object", + "title": "Name", + "properties": { + "first": { "type": "string", "title": "First name", "maxLength": 100 }, + "last": { "type": "string", "title": "Last name", "maxLength": 100 } + } + } + }, + "required": ["email"], + "additionalProperties": false + } + } +} diff --git a/deploy/local/kratos/kratos.yml b/deploy/local/kratos/kratos.yml new file mode 100644 index 0000000..78864d8 --- /dev/null +++ b/deploy/local/kratos/kratos.yml @@ -0,0 +1,101 @@ +version: v1.3.0 + +serve: + public: + base_url: http://localhost:4433/ + cors: + enabled: true + allowed_origins: + - http://localhost + - http://localhost:3000 + - http://localhost:8000 + - http://127.0.0.1 + allowed_methods: [GET, POST, PUT, PATCH, DELETE, OPTIONS] + allowed_headers: [Authorization, Content-Type, X-Session-Token, Cookie] + exposed_headers: [Content-Type, Set-Cookie] + allow_credentials: true + admin: + base_url: http://kratos:4434/ + +selfservice: + default_browser_return_url: http://localhost:8000/ + allowed_return_urls: + - http://localhost:8000 + - honeydue://callback + + methods: + password: + enabled: true + config: + min_password_length: 8 + identifier_similarity_check_enabled: false + code: + enabled: true + oidc: + enabled: false + + flows: + error: + ui_url: http://localhost:8000/auth/error + login: + ui_url: http://localhost:8000/auth/login + lifespan: 10m + registration: + ui_url: http://localhost:8000/auth/registration + lifespan: 10m + after: + password: + hooks: + - hook: session + verification: + enabled: true + ui_url: http://localhost:8000/auth/verification + use: code + after: + default_browser_return_url: http://localhost:8000/ + recovery: + enabled: true + ui_url: http://localhost:8000/auth/recovery + use: code + settings: + ui_url: http://localhost:8000/auth/settings + privileged_session_max_age: 15m + logout: + after: + default_browser_return_url: http://localhost:8000/ + +log: + level: debug + format: text + leak_sensitive_values: true + +secrets: + cookie: + - local-dev-cookie-secret-please-change-this-32chars + cipher: + - 0123456789abcdef0123456789abcdef + +ciphers: + algorithm: xchacha20-poly1305 + +hashers: + algorithm: bcrypt + bcrypt: + cost: 8 + +identity: + default_schema_id: honeydue + schemas: + - id: honeydue + url: file:///etc/config/kratos/identity.schema.json + +courier: + smtp: + connection_uri: smtp://mailpit:1025/?disable_starttls=true + from_address: noreply@localhost + from_name: honeyDue Local + +session: + lifespan: 720h + cookie: + same_site: Lax diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index b106bb6..85dab43 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -14,6 +14,7 @@ services: POSTGRES_DB: ${POSTGRES_DB:-honeydue} volumes: - postgres_data:/var/lib/postgresql/data + - ./deploy/local/postgres-init:/docker-entrypoint-initdb.d:ro ports: - "${DB_PORT:-5433}:5432" # 5433 externally to avoid conflicts with local postgres healthcheck: @@ -91,6 +92,10 @@ services: # Storage encryption STORAGE_ENCRYPTION_KEY: ${STORAGE_ENCRYPTION_KEY} + + # Kratos (identity service) + KRATOS_PUBLIC_URL: "http://kratos:4433" + KRATOS_ADMIN_URL: "http://kratos:4434" volumes: - ./push_certs:/certs:ro - ./uploads:/app/uploads @@ -99,6 +104,8 @@ services: condition: service_healthy redis: condition: service_healthy + kratos: + condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://127.0.0.1:8000/api/health/"] interval: 30s @@ -184,6 +191,59 @@ services: networks: - honeydue-network + # Mailpit — local SMTP catcher (for Kratos email codes during onboarding) + mailpit: + image: axllent/mailpit:latest + container_name: honeydue-mailpit + restart: unless-stopped + ports: + - "${MAILPIT_SMTP_PORT:-1025}:1025" + - "${MAILPIT_HTTP_PORT:-8025}:8025" + networks: + - honeydue-network + + # Kratos schema migration (one-shot, runs before kratos starts) + kratos-migrate: + image: oryd/kratos:v1.3.0 + container_name: honeydue-kratos-migrate + command: ["migrate", "sql", "-e", "--yes"] + environment: + DSN: "postgres://${POSTGRES_USER:-honeydue}:${POSTGRES_PASSWORD:-honeydue_dev_password}@db:5432/kratos?sslmode=disable" + depends_on: + db: + condition: service_healthy + networks: + - honeydue-network + restart: "no" + + # Ory Kratos — identity service + kratos: + image: oryd/kratos:v1.3.0 + container_name: honeydue-kratos + restart: unless-stopped + command: ["serve", "--config", "/etc/config/kratos/kratos.yml", "--watch-courier", "--dev"] + ports: + - "${KRATOS_PUBLIC_PORT:-4433}:4433" + - "${KRATOS_ADMIN_PORT:-4434}:4434" + environment: + DSN: "postgres://${POSTGRES_USER:-honeydue}:${POSTGRES_PASSWORD:-honeydue_dev_password}@db:5432/kratos?sslmode=disable" + LOG_LEVEL: "debug" + volumes: + - ./deploy/local/kratos:/etc/config/kratos:ro + depends_on: + kratos-migrate: + condition: service_completed_successfully + mailpit: + condition: service_started + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://127.0.0.1:4434/health/ready"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 10s + networks: + - honeydue-network + # Dozzle — lightweight real-time log viewer dozzle: image: amir20/dozzle:latest