1
0
forked from baron/baron-sso

ory스택 버전업 및 하드코딩URL 제거

This commit is contained in:
2026-05-07 10:27:31 +09:00
parent 13dee9ae9b
commit 45a14163bf
25 changed files with 1583 additions and 779 deletions

View File

@@ -22,13 +22,13 @@ services:
retries: 5
kratos-migrate:
image: oryd/kratos:${KRATOS_VERSION:-v25.4.0}
image: oryd/kratos:${KRATOS_VERSION:-v26.2.0}
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KRATOS_DB:-ory_kratos}?sslmode=disable&max_conns=20
- KRATOS_SERVE_PUBLIC_BASE_URL="${KRATOS_BROWSER_URL:-http://localhost:4433}"
- KRATOS_SERVE_ADMIN_BASE_URL="${KRATOS_ADMIN_URL:-http://kratos:4434}"
- KRATOS_SELFSERVICE_DEFAULT_BROWSER_RETURN_URL="${KRATOS_UI_URL:-http://localhost:5000}"
- KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS='["${KRATOS_UI_URL:-http://localhost:5000}","${USERFRONT_URL:-http://localhost:5000}"]'
- KRATOS_SERVE_PUBLIC_BASE_URL=${KRATOS_BROWSER_URL}
- KRATOS_SERVE_ADMIN_BASE_URL=${KRATOS_ADMIN_URL}
- KRATOS_SELFSERVICE_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL}
- KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS=${KRATOS_ALLOWED_RETURN_URLS_JSON:-["${KRATOS_UI_URL}","${USERFRONT_URL}"]}
volumes:
- ./docker/ory/kratos:/etc/config/kratos
command: migrate sql up -e -c /etc/config/kratos/kratos.yml --yes
@@ -39,15 +39,15 @@ services:
- ory-net
kratos:
image: oryd/kratos:${KRATOS_VERSION:-v25.4.0}
image: oryd/kratos:${KRATOS_VERSION:-v26.2.0}
container_name: ory_kratos
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KRATOS_DB:-ory_kratos}?sslmode=disable&max_conns=20
- COOKIE_SECRET="${COOKIE_SECRET:-localcookie123}"
- KRATOS_SERVE_PUBLIC_BASE_URL="${KRATOS_BROWSER_URL:-http://localhost:4433}"
- KRATOS_SERVE_ADMIN_BASE_URL="${KRATOS_ADMIN_URL:-http://kratos:4434}"
- KRATOS_SELFSERVICE_DEFAULT_BROWSER_RETURN_URL="${KRATOS_UI_URL:-http://localhost:5000}"
- KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS='["${KRATOS_UI_URL:-http://localhost:5000}","${USERFRONT_URL:-http://localhost:5000}"]'
- COOKIE_SECRET=${COOKIE_SECRET:-localcookie123}
- KRATOS_SERVE_PUBLIC_BASE_URL=${KRATOS_BROWSER_URL}
- KRATOS_SERVE_ADMIN_BASE_URL=${KRATOS_ADMIN_URL}
- KRATOS_SELFSERVICE_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL}
- KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS=${KRATOS_ALLOWED_RETURN_URLS_JSON:-["${KRATOS_UI_URL}","${USERFRONT_URL}"]}
volumes:
- ./docker/ory/kratos:/etc/config/kratos
command: serve -c /etc/config/kratos/kratos.yml
@@ -59,7 +59,7 @@ services:
- kratosnet
hydra-migrate:
image: oryd/hydra:${HYDRA_VERSION:-v25.4.0}
image: oryd/hydra:${HYDRA_VERSION:-v26.2.0}
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20
command: migrate sql up -e --yes
@@ -70,13 +70,14 @@ services:
- ory-net
hydra:
image: oryd/hydra:${HYDRA_VERSION:-v25.4.0}
image: oryd/hydra:${HYDRA_VERSION:-v26.2.0}
container_name: ory_hydra
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20
- URLS_SELF_ISSUER=${USERFRONT_URL:-http://localhost:5000}/oidc
- URLS_LOGIN=${USERFRONT_URL:-http://localhost:5000}/login
- URLS_CONSENT=${USERFRONT_URL:-http://localhost:5000}/consent
- URLS_SELF_ISSUER=${HYDRA_PUBLIC_URL}
- URLS_LOGIN=${HYDRA_LOGIN_URL:-${USERFRONT_URL}/login}
- URLS_CONSENT=${HYDRA_CONSENT_URL:-${USERFRONT_URL}/consent}
- URLS_ERROR=${HYDRA_ERROR_URL:-${USERFRONT_URL}/error}
- SECRETS_SYSTEM=${ORY_POSTGRES_PASSWORD}
volumes:
- ./docker/ory/hydra:/etc/config/hydra
@@ -89,7 +90,7 @@ services:
- hydranet
keto-migrate:
image: oryd/keto:${KETO_VERSION:-v25.4.0}
image: oryd/keto:${KETO_VERSION:-v26.2.0}
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB:-ory_keto}?sslmode=disable&max_conns=20
volumes:
@@ -102,7 +103,7 @@ services:
- ory-net
keto:
image: oryd/keto:${KETO_VERSION:-v25.4.0}
image: oryd/keto:${KETO_VERSION:-v26.2.0}
container_name: ory_keto
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB:-ory_keto}?sslmode=disable&max_conns=20
@@ -116,21 +117,24 @@ services:
- ory-net
oathkeeper:
image: oryd/oathkeeper:${OATHKEEPER_VERSION:-v0.40.6}
image: oryd/oathkeeper:${OATHKEEPER_VERSION:-v26.2.0}
container_name: oathkeeper
restart: unless-stopped
depends_on:
kratos:
condition: service_started
environment:
- APP_ENV=${APP_ENV:-development}
- LOG_LEVEL=debug
command: serve proxy --config /etc/config/oathkeeper/oathkeeper.yml
- OATHKEEPER_INTROSPECT_CLIENT_ID=${OATHKEEPER_INTROSPECT_CLIENT_ID:-oathkeeper-introspect}
- OATHKEEPER_INTROSPECT_CLIENT_SECRET=${OATHKEEPER_INTROSPECT_CLIENT_SECRET:-oathkeeper-secret}
volumes:
- ./docker/ory/oathkeeper:/etc/config/oathkeeper
- oathkeeper_logs:/var/log/oathkeeper
entrypoint: ["/etc/config/oathkeeper/entrypoint.sh"]
networks:
- ory-net
- baron_net
- baron_net
- public_net
ports:
- "4455:4455"
@@ -168,47 +172,47 @@ services:
- /bin/sh
- -ec
- |
apk add --no-cache curl tar
HYDRA_CLI_VERSION="$${HYDRA_VERSION:-v26.2.0}"
HYDRA_CLI_VERSION="$${HYDRA_CLI_VERSION%-distroless}"
HYDRA_CLI_ARCHIVE_VERSION="$${HYDRA_CLI_VERSION#v}"
curl -fsSLo /tmp/hydra.tar.gz "https://github.com/ory/hydra/releases/download/$${HYDRA_CLI_VERSION}/hydra_$${HYDRA_CLI_ARCHIVE_VERSION}-linux_64bit.tar.gz"
tar -xzf /tmp/hydra.tar.gz -C /usr/local/bin hydra
rm /tmp/hydra.tar.gz
apk add --no-cache curl tar
HYDRA_CLI_VERSION="$${HYDRA_VERSION:-v26.2.0}"
HYDRA_CLI_VERSION="$${HYDRA_CLI_VERSION%-distroless}"
HYDRA_CLI_ARCHIVE_VERSION="$${HYDRA_CLI_VERSION#v}"
curl -fsSLo /tmp/hydra.tar.gz "https://github.com/ory/hydra/releases/download/$${HYDRA_CLI_VERSION}/hydra_$${HYDRA_CLI_ARCHIVE_VERSION}-linux_64bit.tar.gz"
tar -xzf /tmp/hydra.tar.gz -C /usr/local/bin hydra
rm /tmp/hydra.tar.gz
echo "Creating/Updating OAuth2 Clients..."
hydra create oauth2-client \
--endpoint http://hydra:4445 \
--id adminfront \
--name "AdminFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri ${ADMINFRONT_CALLBACK_URLS:-http://localhost:5173/auth/callback,http://172.16.10.176:5173/auth/callback}
echo "Creating/Updating OAuth2 Clients..."
hydra create oauth2-client \
--endpoint http://hydra:4445 \
--id devfront \
--name "DevFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri ${DEVFRONT_CALLBACK_URLS:-http://localhost:5174/auth/callback,http://172.16.10.176:5174/auth/callback}
hydra create oauth2-client \
--endpoint "$${HYDRA_ADMIN_URL}" \
--id adminfront \
--name "AdminFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri "$${ADMINFRONT_CALLBACK_URLS}"
hydra create oauth2-client \
--endpoint http://hydra:4445 \
--id orgfront \
--name "OrgFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri ${ORGFRONT_CALLBACK_URLS:-http://localhost:5175/auth/callback,http://172.16.10.176:5175/auth/callback,https://baron-orgchart.hmac.kr/auth/callback}
hydra create oauth2-client \
--endpoint "$${HYDRA_ADMIN_URL}" \
--id devfront \
--name "DevFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri "$${DEVFRONT_CALLBACK_URLS}"
echo "All RP clients initialized successfully."
hydra create oauth2-client \
--endpoint "$${HYDRA_ADMIN_URL}" \
--id orgfront \
--name "OrgFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri "$${ORGFRONT_CALLBACK_URLS}"
echo "All RP clients initialized successfully."
depends_on:
ory_stack_check:
condition: service_completed_successfully

View File

@@ -4,23 +4,18 @@ dsn: ${DSN}
serve:
public:
base_url: http://localhost:4433/
base_url: ${KRATOS_BROWSER_URL}
cors:
enabled: true
allowed_origins:
- http://localhost:5173
- http://localhost:5174
- http://localhost:5175
- http://localhost:5000
- ${USERFRONT_URL}
- ${ADMINFRONT_URL}
- ${DEVFRONT_URL}
- ${ORGFRONT_URL}
- http://backend:3000
- http://baron_backend:3000
- https://ssologin.hmac.kr
- https://sso-test.hmac.kr
- https://app.brsw.kr
- https://sss.hmac.kr
- https://sso.hmac.kr
admin:
base_url: http://localhost:4434/
base_url: ${KRATOS_ADMIN_URL}
session:
cookie:
@@ -29,21 +24,22 @@ session:
path: /
selfservice:
default_browser_return_url: http://localhost:5000/
default_browser_return_url: ${KRATOS_UI_URL}
allowed_return_urls:
- http://baron_backend:3000
- http://baron_backend:3000/
- http://localhost:5000
- https://app.brsw.kr
- https://app.brsw.kr/
- https://sss.hmac.kr
- https://sss.hmac.kr/
- https://sso.hmac.kr
- https://sso.hmac.kr/
- https://ssologin.hmac.kr
- https://ssologin.hmac.kr/
- https://sso-test.hmac.kr
- https://sso-test.hmac.kr/
- ${KRATOS_UI_URL}
- ${KRATOS_UI_URL}/
- ${USERFRONT_URL}
- ${USERFRONT_URL}/
- ${USERFRONT_URL}/ko
- ${USERFRONT_URL}/ko/
- ${USERFRONT_URL}/en
- ${USERFRONT_URL}/en/
- ${USERFRONT_URL}/auth/callback
- ${USERFRONT_URL}/ko/auth/callback
- ${USERFRONT_URL}/en/auth/callback
- ${ADMINFRONT_URL}/auth/callback
- ${DEVFRONT_URL}/auth/callback
- ${ORGFRONT_URL}/auth/callback
methods:
password:
@@ -56,24 +52,24 @@ selfservice:
flows:
error:
ui_url: http://localhost:5000/error
ui_url: ${KRATOS_UI_URL}/error
settings:
ui_url: http://localhost:5000/error?error=settings_disabled
ui_url: ${KRATOS_UI_URL}/error?error=settings_disabled
privileged_session_max_age: 15m
recovery:
ui_url: http://localhost:5000/recovery
ui_url: ${KRATOS_UI_URL}/recovery
use: code
verification:
ui_url: http://localhost:5000/verification
ui_url: ${KRATOS_UI_URL}/verification
use: code
logout:
after:
default_browser_return_url: http://localhost:5000/login
default_browser_return_url: ${KRATOS_UI_URL}/login
login:
ui_url: http://localhost:5000/login
ui_url: ${KRATOS_UI_URL}/login
lifespan: 10m
registration:
ui_url: http://localhost:5000/registration
ui_url: ${KRATOS_UI_URL}/registration
lifespan: 10m
log:

View File

@@ -3,7 +3,7 @@
"id": "public-health",
"description": "공개 헬스체크",
"match": {
"url": "<.*>://<.*>/health",
"url": "<.*>://<[^/]+>/health",
"methods": ["GET"]
},
"upstream": {
@@ -17,7 +17,7 @@
"id": "public-preflight",
"description": "CORS preflight",
"match": {
"url": "<.*>://<.*>/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["OPTIONS"]
},
"upstream": {
@@ -31,7 +31,7 @@
"id": "public-auth",
"description": "인증/회원가입 등 공개 엔드포인트",
"match": {
"url": "<.*>://<.*>/api/v1/auth/<.*>",
"url": "<.*>://<[^/]+>/api/v1/auth/<.*>",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
@@ -45,7 +45,7 @@
"id": "backend-command",
"description": "Command 요청은 Backend로 전달 (Audit 강제)",
"match": {
"url": "<.*>://<.*>/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["POST", "PUT", "PATCH", "DELETE"]
},
"upstream": {
@@ -59,7 +59,7 @@
"id": "backend-query",
"description": "Backend Query (admin/dev 포함)",
"match": {
"url": "<.*>://<.*>/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["GET"]
},
"upstream": {
@@ -73,7 +73,7 @@
"id": "hydra-well-known",
"description": "Hydra OIDC Discovery & JWKS",
"match": {
"url": "<.*>://<.*>/.well-known/<.*>",
"url": "<.*>://<[^/]+>/.well-known/<.*>",
"methods": ["GET", "OPTIONS"]
},
"upstream": {
@@ -87,12 +87,12 @@
"id": "hydra-well-known-oidc",
"description": "Hydra OIDC Discovery & JWKS (with /oidc prefix)",
"match": {
"url": "<.*>://<.*>/oidc/.well-known/<.*>",
"url": "<.*>://<[^/]+>/oidc/.well-known/<.*>",
"methods": ["GET", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path_prefix": "/oidc"
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
@@ -102,7 +102,7 @@
"id": "hydra-oauth2",
"description": "Hydra OAuth2 Endpoints",
"match": {
"url": "<.*>://<.*>/oauth2/<.*>",
"url": "<.*>://<[^/]+>/oauth2/<.*>",
"methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
},
"upstream": {
@@ -116,12 +116,12 @@
"id": "hydra-oauth2-oidc",
"description": "Hydra OAuth2 Endpoints (with /oidc prefix)",
"match": {
"url": "<.*>://<.*>/oidc/oauth2/<.*>",
"url": "<.*>://<[^/]+>/oidc/oauth2/<.*>",
"methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path_prefix": "/oidc"
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
@@ -131,7 +131,7 @@
"id": "hydra-userinfo",
"description": "Hydra Userinfo",
"match": {
"url": "<.*>://<.*>/userinfo",
"url": "<.*>://<[^/]+>/userinfo",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
@@ -145,12 +145,12 @@
"id": "hydra-userinfo-oidc",
"description": "Hydra Userinfo (with /oidc prefix)",
"match": {
"url": "<.*>://<.*>/oidc/userinfo",
"url": "<.*>://<[^/]+>/oidc/userinfo",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path_prefix": "/oidc"
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },

View File

@@ -3,7 +3,7 @@
"id": "public-health",
"description": "공개 헬스체크",
"match": {
"url": "<.*>://<.*>/health",
"url": "<.*>://<[^/]+>/health",
"methods": ["GET"]
},
"upstream": {
@@ -17,7 +17,7 @@
"id": "public-preflight",
"description": "CORS preflight",
"match": {
"url": "<.*>://<.*>/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["OPTIONS"]
},
"upstream": {
@@ -31,7 +31,7 @@
"id": "public-auth",
"description": "인증/회원가입 등 공개 엔드포인트",
"match": {
"url": "<.*>://<.*>/api/v1/auth/<.*>",
"url": "<.*>://<[^/]+>/api/v1/auth/<.*>",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
@@ -45,7 +45,7 @@
"id": "backend-command",
"description": "Command 요청은 Backend로 전달 (Audit 강제)",
"match": {
"url": "<.*>://<.*>/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["POST", "PUT", "PATCH", "DELETE"]
},
"upstream": {
@@ -59,7 +59,7 @@
"id": "backend-query",
"description": "Backend Query (admin/dev 포함)",
"match": {
"url": "<.*>://<.*>/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["GET"]
},
"upstream": {
@@ -73,7 +73,7 @@
"id": "hydra-well-known",
"description": "Hydra OIDC Discovery & JWKS",
"match": {
"url": "<.*>://<.*>/.well-known/<.*>",
"url": "<.*>://<[^/]+>/.well-known/<.*>",
"methods": ["GET", "OPTIONS"]
},
"upstream": {
@@ -87,12 +87,12 @@
"id": "hydra-well-known-oidc",
"description": "Hydra OIDC Discovery & JWKS (with /oidc prefix)",
"match": {
"url": "<.*>://<.*>/oidc/.well-known/<.*>",
"url": "<.*>://<[^/]+>/oidc/.well-known/<.*>",
"methods": ["GET", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path_prefix": "/oidc"
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
@@ -102,7 +102,7 @@
"id": "hydra-oauth2",
"description": "Hydra OAuth2 Endpoints",
"match": {
"url": "<.*>://<.*>/oauth2/<.*>",
"url": "<.*>://<[^/]+>/oauth2/<.*>",
"methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
},
"upstream": {
@@ -116,12 +116,12 @@
"id": "hydra-oauth2-oidc",
"description": "Hydra OAuth2 Endpoints (with /oidc prefix)",
"match": {
"url": "<.*>://<.*>/oidc/oauth2/<.*>",
"url": "<.*>://<[^/]+>/oidc/oauth2/<.*>",
"methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path_prefix": "/oidc"
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
@@ -131,7 +131,7 @@
"id": "hydra-userinfo",
"description": "Hydra Userinfo",
"match": {
"url": "<.*>://<.*>/userinfo",
"url": "<.*>://<[^/]+>/userinfo",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
@@ -145,12 +145,12 @@
"id": "hydra-userinfo-oidc",
"description": "Hydra Userinfo (with /oidc prefix)",
"match": {
"url": "<.*>://<.*>/oidc/userinfo",
"url": "<.*>://<[^/]+>/oidc/userinfo",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path_prefix": "/oidc"
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },

View File

@@ -1,9 +1,9 @@
[
{
"id": "public-health",
"description": "공개 헬스체크 (PROD 도메인)",
"description": "공개 헬스체크 (PROD)",
"match": {
"url": "https://app.brsw.kr/health",
"url": "<.*>://<[^/]+>/health",
"methods": ["GET"]
},
"upstream": {
@@ -15,9 +15,9 @@
},
{
"id": "public-preflight",
"description": "CORS preflight (PROD 도메인)",
"description": "CORS preflight (PROD)",
"match": {
"url": "https://app.brsw.kr/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["OPTIONS"]
},
"upstream": {
@@ -29,9 +29,9 @@
},
{
"id": "public-auth",
"description": "인증/회원가입 등 공개 엔드포인트 (PROD 도메인)",
"description": "인증/회원가입 등 공개 엔드포인트 (PROD)",
"match": {
"url": "https://app.brsw.kr/api/v1/auth/<.*>",
"url": "<.*>://<[^/]+>/api/v1/auth/<.*>",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
@@ -45,7 +45,7 @@
"id": "backend-command",
"description": "Command 요청은 Backend로 전달 (Audit 강제)",
"match": {
"url": "https://app.brsw.kr/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["POST", "PUT", "PATCH", "DELETE"]
},
"upstream": {
@@ -59,7 +59,7 @@
"id": "backend-query",
"description": "Backend Query (admin/dev 포함)",
"match": {
"url": "https://app.brsw.kr/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["GET"]
},
"upstream": {
@@ -68,5 +68,92 @@
"authenticators": [{ "handler": "cookie_session" }],
"authorizer": { "handler": "remote_json" },
"mutators": [{ "handler": "noop" }]
},
{
"id": "hydra-well-known",
"description": "Hydra OIDC Discovery & JWKS (PROD)",
"match": {
"url": "<.*>://<[^/]+>/.well-known/<.*>",
"methods": ["GET", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
"mutators": [{ "handler": "noop" }]
},
{
"id": "hydra-well-known-oidc",
"description": "Hydra OIDC Discovery & JWKS with /oidc prefix (PROD)",
"match": {
"url": "<.*>://<[^/]+>/oidc/.well-known/<.*>",
"methods": ["GET", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
"mutators": [{ "handler": "noop" }]
},
{
"id": "hydra-oauth2",
"description": "Hydra OAuth2 Endpoints (PROD)",
"match": {
"url": "<.*>://<[^/]+>/oauth2/<.*>",
"methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
"mutators": [{ "handler": "noop" }]
},
{
"id": "hydra-oauth2-oidc",
"description": "Hydra OAuth2 Endpoints with /oidc prefix (PROD 도메인)",
"match": {
"url": "<.*>://<[^/]+>/oidc/oauth2/<.*>",
"methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
"mutators": [{ "handler": "noop" }]
},
{
"id": "hydra-userinfo",
"description": "Hydra Userinfo (PROD)",
"match": {
"url": "<.*>://<[^/]+>/userinfo",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
"mutators": [{ "handler": "noop" }]
},
{
"id": "hydra-userinfo-oidc",
"description": "Hydra Userinfo with /oidc prefix (PROD 도메인)",
"match": {
"url": "<.*>://<[^/]+>/oidc/userinfo",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
"mutators": [{ "handler": "noop" }]
}
]

View File

@@ -3,7 +3,7 @@
"id": "public-health",
"description": "공개 헬스체크",
"match": {
"url": "<.*>://<.*>/health",
"url": "<.*>://<[^/]+>/health",
"methods": ["GET"]
},
"upstream": {
@@ -17,7 +17,7 @@
"id": "public-preflight",
"description": "CORS preflight",
"match": {
"url": "<.*>://<.*>/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["OPTIONS"]
},
"upstream": {
@@ -31,7 +31,7 @@
"id": "public-auth",
"description": "인증/회원가입 등 공개 엔드포인트",
"match": {
"url": "<.*>://<.*>/api/v1/auth/<.*>",
"url": "<.*>://<[^/]+>/api/v1/auth/<.*>",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
@@ -45,7 +45,7 @@
"id": "backend-command",
"description": "Command 요청은 Backend로 전달 (Audit 강제)",
"match": {
"url": "<.*>://<.*>/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["POST", "PUT", "PATCH", "DELETE"]
},
"upstream": {
@@ -59,7 +59,7 @@
"id": "backend-query",
"description": "Backend Query (admin/dev 포함)",
"match": {
"url": "<.*>://<.*>/api/v1/<.*>",
"url": "<.*>://<[^/]+>/api/v1/<.*>",
"methods": ["GET"]
},
"upstream": {
@@ -73,7 +73,7 @@
"id": "hydra-well-known",
"description": "Hydra OIDC Discovery & JWKS",
"match": {
"url": "<.*>://<.*>/.well-known/<.*>",
"url": "<.*>://<[^/]+>/.well-known/<.*>",
"methods": ["GET", "OPTIONS"]
},
"upstream": {
@@ -87,12 +87,12 @@
"id": "hydra-well-known-oidc",
"description": "Hydra OIDC Discovery & JWKS (with /oidc prefix)",
"match": {
"url": "<.*>://<.*>/oidc/.well-known/<.*>",
"url": "<.*>://<[^/]+>/oidc/.well-known/<.*>",
"methods": ["GET", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path_prefix": "/oidc"
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
@@ -102,7 +102,7 @@
"id": "hydra-oauth2",
"description": "Hydra OAuth2 Endpoints",
"match": {
"url": "<.*>://<.*>/oauth2/<.*>",
"url": "<.*>://<[^/]+>/oauth2/<.*>",
"methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
},
"upstream": {
@@ -116,12 +116,12 @@
"id": "hydra-oauth2-oidc",
"description": "Hydra OAuth2 Endpoints (with /oidc prefix)",
"match": {
"url": "<.*>://<.*>/oidc/oauth2/<.*>",
"url": "<.*>://<[^/]+>/oidc/oauth2/<.*>",
"methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path_prefix": "/oidc"
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },
@@ -131,7 +131,7 @@
"id": "hydra-userinfo",
"description": "Hydra Userinfo",
"match": {
"url": "<.*>://<.*>/userinfo",
"url": "<.*>://<[^/]+>/userinfo",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
@@ -145,12 +145,12 @@
"id": "hydra-userinfo-oidc",
"description": "Hydra Userinfo (with /oidc prefix)",
"match": {
"url": "<.*>://<.*>/oidc/userinfo",
"url": "<.*>://<[^/]+>/oidc/userinfo",
"methods": ["GET", "POST", "OPTIONS"]
},
"upstream": {
"url": "http://hydra:4444",
"strip_path_prefix": "/oidc"
"strip_path": "/oidc"
},
"authenticators": [{ "handler": "noop" }],
"authorizer": { "handler": "allow" },

View File

@@ -1,501 +1,521 @@
services:
postgres:
image: postgres:17-alpine
container_name: baron_postgres
environment:
POSTGRES_USER: "${DB_USER:-baron}"
POSTGRES_PASSWORD: "${DB_PASSWORD:-password}"
POSTGRES_DB: "${DB_NAME:-baron_sso}"
ports:
- "${DB_PORT:-5432}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./docker/init-metadata:/docker-entrypoint-initdb.d
networks:
- baron_net
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -U ${DB_USER:-baron} -d ${DB_NAME:-baron_sso}",
]
interval: 5s
timeout: 5s
retries: 5
restart: always
postgres:
image: postgres:17-alpine
container_name: baron_postgres
environment:
POSTGRES_USER: "${DB_USER:-baron}"
POSTGRES_PASSWORD: "${DB_PASSWORD:-password}"
POSTGRES_DB: "${DB_NAME:-baron_sso}"
ports:
- "${DB_PORT:-5432}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./docker/init-metadata:/docker-entrypoint-initdb.d
networks:
- baron_net
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -U ${DB_USER:-baron} -d ${DB_NAME:-baron_sso}",
]
interval: 5s
timeout: 5s
retries: 5
restart: always
clickhouse:
image: clickhouse/clickhouse-server:latest
container_name: baron_clickhouse
restart: always
volumes:
- clickhouse_data:/var/lib/clickhouse
environment:
CLICKHOUSE_USER: "${CLICKHOUSE_USER:-baron}"
CLICKHOUSE_PASSWORD: "${CLICKHOUSE_PASSWORD:-password}"
networks:
- baron_net
healthcheck:
test: ["CMD", "clickhouse-client", "--query", "SELECT 1"]
interval: 5s
timeout: 5s
retries: 5
clickhouse:
image: clickhouse/clickhouse-server:latest
container_name: baron_clickhouse
restart: always
volumes:
- clickhouse_data:/var/lib/clickhouse
environment:
CLICKHOUSE_USER: "${CLICKHOUSE_USER:-baron}"
CLICKHOUSE_PASSWORD: "${CLICKHOUSE_PASSWORD:-password}"
networks:
- baron_net
healthcheck:
test: ["CMD", "clickhouse-client", "--query", "SELECT 1"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: baron_redis
restart: always
command: redis-server --port 6389
ports:
- "6389:6389"
volumes:
- redis_data:/data
networks:
- baron_net
healthcheck:
test: ["CMD", "redis-cli", "-p", "6389", "ping"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: baron_redis
restart: always
command: redis-server --port 6389
ports:
- "6389:6389"
volumes:
- redis_data:/data
networks:
- baron_net
healthcheck:
test: ["CMD", "redis-cli", "-p", "6389", "ping"]
interval: 5s
timeout: 5s
retries: 5
gateway:
image: nginx:alpine
container_name: baron_gateway
restart: always
ports:
- "${USERFRONT_PORT:-5000}:5000"
volumes:
- ./gateway/nginx.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- baron_net
- public_net
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:5000/"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
gateway:
image: nginx:alpine
container_name: baron_gateway
restart: always
ports:
- "${USERFRONT_PORT:-5000}:5000"
volumes:
- ./gateway/nginx.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- baron_net
- public_net
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:5000/"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
postgres_ory:
image: postgres:${ORY_POSTGRES_TAG:-17-alpine}
container_name: ory_postgres
environment:
- POSTGRES_USER=${ORY_POSTGRES_USER:-ory}
- POSTGRES_PASSWORD=${ORY_POSTGRES_PASSWORD:-secret}
- POSTGRES_DB=${ORY_POSTGRES_DB:-ory}
volumes:
- ./docker/ory/init-db:/docker-entrypoint-initdb.d
- ory_postgres_data:/var/lib/postgresql/data
networks:
- ory-net
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -U ${ORY_POSTGRES_USER:-ory} -d ${KRATOS_DB:-ory_kratos}",
]
interval: 5s
timeout: 5s
retries: 5
postgres_ory:
image: postgres:${ORY_POSTGRES_TAG:-17-alpine}
container_name: ory_postgres
environment:
- POSTGRES_USER=${ORY_POSTGRES_USER:-ory}
- POSTGRES_PASSWORD=${ORY_POSTGRES_PASSWORD:-secret}
- POSTGRES_DB=${ORY_POSTGRES_DB:-ory}
volumes:
- ./docker/ory/init-db:/docker-entrypoint-initdb.d
- ory_postgres_data:/var/lib/postgresql/data
networks:
- ory-net
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -U ${ORY_POSTGRES_USER:-ory} -d ${KRATOS_DB:-ory_kratos}",
]
interval: 5s
timeout: 5s
retries: 5
kratos-migrate:
image: oryd/kratos:${KRATOS_VERSION:-v25.4.0}
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KRATOS_DB:-ory_kratos}?sslmode=disable&max_conns=20
- KRATOS_SERVE_PUBLIC_BASE_URL=${KRATOS_BROWSER_URL:-http://localhost:4433}
- KRATOS_SERVE_ADMIN_BASE_URL=${KRATOS_ADMIN_URL:-http://kratos:4434}
- KRATOS_SELFSERVICE_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL:-http://localhost:5000}
- KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS=["${KRATOS_UI_URL:-http://localhost:5000}","${USERFRONT_URL:-http://localhost:5000}"]
- KRATOS_SELFSERVICE_FLOWS_ERROR_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/error
- KRATOS_SELFSERVICE_FLOWS_SETTINGS_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/error?error=settings_disabled
- KRATOS_SELFSERVICE_FLOWS_RECOVERY_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/recovery
- KRATOS_SELFSERVICE_FLOWS_VERIFICATION_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/verification
- KRATOS_SELFSERVICE_FLOWS_LOGIN_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/login
- KRATOS_SELFSERVICE_FLOWS_REGISTRATION_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/registration
- KRATOS_SELFSERVICE_FLOWS_LOGOUT_AFTER_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL:-http://localhost:5000}/login
volumes:
- ./docker/ory/kratos:/etc/config/kratos
command: migrate sql up -e -c /etc/config/kratos/kratos.yml --yes
depends_on:
postgres_ory:
condition: service_healthy
networks:
- ory-net
kratos-migrate:
image: oryd/kratos:${KRATOS_VERSION:-v26.2.0}
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KRATOS_DB:-ory_kratos}?sslmode=disable&max_conns=20
- KRATOS_SERVE_PUBLIC_BASE_URL=${KRATOS_BROWSER_URL}
- KRATOS_SERVE_ADMIN_BASE_URL=${KRATOS_ADMIN_URL}
- KRATOS_SELFSERVICE_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL}
- KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS=${KRATOS_ALLOWED_RETURN_URLS_JSON:-["${KRATOS_UI_URL}","${KRATOS_UI_URL}/","${USERFRONT_URL}","${USERFRONT_URL}/","${USERFRONT_URL}/ko","${USERFRONT_URL}/ko/","${USERFRONT_URL}/en","${USERFRONT_URL}/en/","${USERFRONT_URL}/auth/callback","${USERFRONT_URL}/ko/auth/callback","${USERFRONT_URL}/en/auth/callback","${ADMINFRONT_URL}/auth/callback","${DEVFRONT_URL}/auth/callback","${ORGFRONT_URL}/auth/callback"]}
- KRATOS_SELFSERVICE_FLOWS_ERROR_UI_URL=${KRATOS_UI_URL}/error
- KRATOS_SELFSERVICE_FLOWS_SETTINGS_UI_URL=${KRATOS_UI_URL}/error?error=settings_disabled
- KRATOS_SELFSERVICE_FLOWS_RECOVERY_UI_URL=${KRATOS_UI_URL}/recovery
- KRATOS_SELFSERVICE_FLOWS_VERIFICATION_UI_URL=${KRATOS_UI_URL}/verification
- KRATOS_SELFSERVICE_FLOWS_LOGIN_UI_URL=${KRATOS_UI_URL}/login
- KRATOS_SELFSERVICE_FLOWS_REGISTRATION_UI_URL=${KRATOS_UI_URL}/registration
- KRATOS_SELFSERVICE_FLOWS_LOGOUT_AFTER_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL}/login
volumes:
- ./docker/ory/kratos:/etc/config/kratos
command: migrate sql up -e -c /etc/config/kratos/kratos.yml --yes
depends_on:
postgres_ory:
condition: service_healthy
networks:
- ory-net
kratos:
image: oryd/kratos:${KRATOS_VERSION:-v25.4.0}
container_name: ory_kratos
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KRATOS_DB:-ory_kratos}?sslmode=disable&max_conns=20
- COOKIE_SECRET=${COOKIE_SECRET:-localcookie123}
- KRATOS_SERVE_PUBLIC_BASE_URL=${KRATOS_BROWSER_URL:-http://localhost:4433}
- KRATOS_SERVE_ADMIN_BASE_URL=${KRATOS_ADMIN_URL:-http://kratos:4434}
- KRATOS_SELFSERVICE_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL:-http://localhost:5000}
- KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS=["${KRATOS_UI_URL:-http://localhost:5000}","${USERFRONT_URL:-http://localhost:5000}"]
- KRATOS_SELFSERVICE_FLOWS_ERROR_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/error
- KRATOS_SELFSERVICE_FLOWS_SETTINGS_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/error?error=settings_disabled
- KRATOS_SELFSERVICE_FLOWS_RECOVERY_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/recovery
- KRATOS_SELFSERVICE_FLOWS_VERIFICATION_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/verification
- KRATOS_SELFSERVICE_FLOWS_LOGIN_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/login
- KRATOS_SELFSERVICE_FLOWS_REGISTRATION_UI_URL=${KRATOS_UI_URL:-http://localhost:5000}/registration
- KRATOS_SELFSERVICE_FLOWS_LOGOUT_AFTER_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL:-http://localhost:5000}/login
volumes:
- ./docker/ory/kratos:/etc/config/kratos
command: serve -c /etc/config/kratos/kratos.yml --dev --watch-courier
depends_on:
kratos-migrate:
condition: service_completed_successfully
networks:
- ory-net
- kratosnet
kratos:
image: oryd/kratos:${KRATOS_VERSION:-v26.2.0}
container_name: ory_kratos
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KRATOS_DB:-ory_kratos}?sslmode=disable&max_conns=20
- COOKIE_SECRET=${COOKIE_SECRET:-localcookie123}
- KRATOS_SERVE_PUBLIC_BASE_URL=${KRATOS_BROWSER_URL}
- KRATOS_SERVE_ADMIN_BASE_URL=${KRATOS_ADMIN_URL}
- KRATOS_SELFSERVICE_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL}
- KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS=${KRATOS_ALLOWED_RETURN_URLS_JSON:-["${KRATOS_UI_URL}","${KRATOS_UI_URL}/","${USERFRONT_URL}","${USERFRONT_URL}/","${USERFRONT_URL}/ko","${USERFRONT_URL}/ko/","${USERFRONT_URL}/en","${USERFRONT_URL}/en/","${USERFRONT_URL}/auth/callback","${USERFRONT_URL}/ko/auth/callback","${USERFRONT_URL}/en/auth/callback","${ADMINFRONT_URL}/auth/callback","${DEVFRONT_URL}/auth/callback","${ORGFRONT_URL}/auth/callback"]}
- KRATOS_SELFSERVICE_FLOWS_ERROR_UI_URL=${KRATOS_UI_URL}/error
- KRATOS_SELFSERVICE_FLOWS_SETTINGS_UI_URL=${KRATOS_UI_URL}/error?error=settings_disabled
- KRATOS_SELFSERVICE_FLOWS_RECOVERY_UI_URL=${KRATOS_UI_URL}/recovery
- KRATOS_SELFSERVICE_FLOWS_VERIFICATION_UI_URL=${KRATOS_UI_URL}/verification
- KRATOS_SELFSERVICE_FLOWS_LOGIN_UI_URL=${KRATOS_UI_URL}/login
- KRATOS_SELFSERVICE_FLOWS_REGISTRATION_UI_URL=${KRATOS_UI_URL}/registration
- KRATOS_SELFSERVICE_FLOWS_LOGOUT_AFTER_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL}/login
volumes:
- ./docker/ory/kratos:/etc/config/kratos
command: serve -c /etc/config/kratos/kratos.yml --dev --watch-courier
depends_on:
kratos-migrate:
condition: service_completed_successfully
networks:
- ory-net
- kratosnet
hydra-migrate:
image: oryd/hydra:${HYDRA_VERSION:-v25.4.0}
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20
command: migrate sql up -e --yes
depends_on:
postgres_ory:
condition: service_healthy
networks:
- ory-net
hydra-migrate:
image: oryd/hydra:${HYDRA_VERSION:-v26.2.0}
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20
command: migrate sql up -e --yes
depends_on:
postgres_ory:
condition: service_healthy
networks:
- ory-net
hydra:
image: oryd/hydra:${HYDRA_VERSION:-v25.4.0}
container_name: ory_hydra
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20
- URLS_SELF_ISSUER=${USERFRONT_URL:-http://localhost:5000}/oidc
- URLS_LOGIN=${USERFRONT_URL:-http://localhost:5000}/login
- URLS_CONSENT=${USERFRONT_URL:-http://localhost:5000}/consent
- SECRETS_SYSTEM=${ORY_POSTGRES_PASSWORD}
volumes:
- ./docker/ory/hydra:/etc/config/hydra
command: serve -c /etc/config/hydra/hydra.yml all --dev
depends_on:
hydra-migrate:
condition: service_completed_successfully
networks:
- ory-net
- hydranet
hydra:
image: oryd/hydra:${HYDRA_VERSION:-v26.2.0}
container_name: ory_hydra
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20
- URLS_SELF_ISSUER=${HYDRA_PUBLIC_URL}
- URLS_LOGIN=${HYDRA_LOGIN_URL:-${USERFRONT_URL}/login}
- URLS_CONSENT=${HYDRA_CONSENT_URL:-${USERFRONT_URL}/consent}
- URLS_ERROR=${HYDRA_ERROR_URL:-${USERFRONT_URL}/error}
- SECRETS_SYSTEM=${ORY_POSTGRES_PASSWORD}
volumes:
- ./docker/ory/hydra:/etc/config/hydra
command: serve -c /etc/config/hydra/hydra.yml all --dev
depends_on:
hydra-migrate:
condition: service_completed_successfully
networks:
- ory-net
- hydranet
keto-migrate:
image: oryd/keto:${KETO_VERSION:-v25.4.0}
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB:-ory_keto}?sslmode=disable&max_conns=20
volumes:
- ./docker/ory/keto:/etc/config/keto
command: ["migrate", "up", "-c", "/etc/config/keto/keto.yml", "--yes"]
depends_on:
postgres_ory:
condition: service_healthy
networks:
- ory-net
keto-migrate:
image: oryd/keto:${KETO_VERSION:-v26.2.0}
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB:-ory_keto}?sslmode=disable&max_conns=20
volumes:
- ./docker/ory/keto:/etc/config/keto
command: ["migrate", "up", "-c", "/etc/config/keto/keto.yml", "--yes"]
depends_on:
postgres_ory:
condition: service_healthy
networks:
- ory-net
keto:
image: oryd/keto:${KETO_VERSION:-v25.4.0}
container_name: ory_keto
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB:-ory_keto}?sslmode=disable&max_conns=20
volumes:
- ./docker/ory/keto:/etc/config/keto
command: serve -c /etc/config/keto/keto.yml
depends_on:
keto-migrate:
condition: service_completed_successfully
networks:
- ory-net
keto:
image: oryd/keto:${KETO_VERSION:-v26.2.0}
container_name: ory_keto
environment:
- DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB:-ory_keto}?sslmode=disable&max_conns=20
volumes:
- ./docker/ory/keto:/etc/config/keto
command: serve -c /etc/config/keto/keto.yml
depends_on:
keto-migrate:
condition: service_completed_successfully
networks:
- ory-net
oathkeeper:
image: oryd/oathkeeper:${OATHKEEPER_VERSION:-v0.40.6}
container_name: oathkeeper
restart: unless-stopped
depends_on:
kratos:
condition: service_started
environment:
- LOG_LEVEL=debug
command: serve proxy --config /etc/config/oathkeeper/oathkeeper.yml
volumes:
- ./docker/ory/oathkeeper:/etc/config/oathkeeper
- oathkeeper_logs:/var/log/oathkeeper
networks:
- ory-net
- baron_net
- public_net
ports:
- "4455:4455"
- "4456:4456"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:4456/health/ready"]
interval: 5s
timeout: 5s
retries: 5
oathkeeper_logs_init:
image: alpine:latest
command:
[
"sh",
"-c",
"mkdir -p /var/log/oathkeeper && chown -R ${OATHKEEPER_UID:-1001}:${OATHKEEPER_GID:-1001} /var/log/oathkeeper",
]
volumes:
- oathkeeper_logs:/var/log/oathkeeper
networks:
- ory-net
ory_clickhouse:
image: clickhouse/clickhouse-server:latest
container_name: ory_clickhouse
environment:
- CLICKHOUSE_USER=${ORY_CLICKHOUSE_USER:-ory}
- CLICKHOUSE_PASSWORD=${ORY_CLICKHOUSE_PASSWORD:-orypass}
volumes:
- ory_clickhouse_data:/var/lib/clickhouse
- ./docker/ory/clickhouse:/docker-entrypoint-initdb.d
networks:
- ory-net
oathkeeper:
image: oryd/oathkeeper:${OATHKEEPER_VERSION:-v0.40.6}
container_name: oathkeeper
restart: unless-stopped
depends_on:
oathkeeper_logs_init:
condition: service_completed_successfully
kratos:
condition: service_started
user: "${OATHKEEPER_UID:-1001}:${OATHKEEPER_GID:-1001}"
environment:
- APP_ENV=${APP_ENV:-stage}
- LOG_LEVEL=debug
- OATHKEEPER_INTROSPECT_CLIENT_ID=${OATHKEEPER_INTROSPECT_CLIENT_ID:-oathkeeper-introspect}
- OATHKEEPER_INTROSPECT_CLIENT_SECRET=${OATHKEEPER_INTROSPECT_CLIENT_SECRET:-oathkeeper-secret}
volumes:
- ./docker/ory/oathkeeper:/etc/config/oathkeeper
- oathkeeper_logs:/var/log/oathkeeper
entrypoint: ["/etc/config/oathkeeper/entrypoint.sh"]
networks:
- ory-net
- baron_net
- public_net
ports:
- "4455:4455"
- "4456:4456"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:4456/health/ready"]
interval: 5s
timeout: 5s
retries: 5
ory_stack_check:
image: alpine:latest
container_name: ory_stack_check
command: >
/bin/sh -c "
apk add --no-cache curl;
echo 'Wait for services...';
until curl -s http://kratos:4433/health/ready; do sleep 1; done;
until curl -s http://hydra:4444/health/ready; do sleep 1; done;
until curl -s http://keto:4466/health/ready; do sleep 1; done;
echo 'Ory Stack is fully operational!';"
depends_on:
- kratos
- hydra
- keto
networks:
- ory-net
ory_clickhouse:
image: clickhouse/clickhouse-server:latest
container_name: ory_clickhouse
environment:
- CLICKHOUSE_USER=${ORY_CLICKHOUSE_USER:-ory}
- CLICKHOUSE_PASSWORD=${ORY_CLICKHOUSE_PASSWORD:-orypass}
volumes:
- ory_clickhouse_data:/var/lib/clickhouse
- ./docker/ory/clickhouse:/docker-entrypoint-initdb.d
networks:
- ory-net
init-rp:
image: alpine:latest
env_file:
- .env
command:
- /bin/sh
- -ec
- |
apk add --no-cache curl tar
HYDRA_CLI_VERSION="$${HYDRA_VERSION:-v26.2.0}"
HYDRA_CLI_VERSION="$${HYDRA_CLI_VERSION%-distroless}"
HYDRA_CLI_ARCHIVE_VERSION="$${HYDRA_CLI_VERSION#v}"
curl -fsSLo /tmp/hydra.tar.gz "https://github.com/ory/hydra/releases/download/$${HYDRA_CLI_VERSION}/hydra_$${HYDRA_CLI_ARCHIVE_VERSION}-linux_64bit.tar.gz"
tar -xzf /tmp/hydra.tar.gz -C /usr/local/bin hydra
rm /tmp/hydra.tar.gz
ory_stack_check:
image: alpine:latest
container_name: ory_stack_check
command: >
/bin/sh -c "
apk add --no-cache curl;
echo 'Wait for services...';
until curl -s http://kratos:4433/health/ready; do sleep 1; done;
until curl -s http://hydra:4444/health/ready; do sleep 1; done;
until curl -s http://keto:4466/health/ready; do sleep 1; done;
echo 'Ory Stack is fully operational!';"
depends_on:
- kratos
- hydra
- keto
networks:
- ory-net
# Function to create or update OAuth2 client (Idempotency)
upsert_client() {
ID=$$1
shift
if hydra get oauth2-client --endpoint http://hydra:4445 "$$ID" >/dev/null 2>&1; then
echo "Updating existing client: $$ID"
hydra update oauth2-client --endpoint http://hydra:4445 "$$ID" "$$@"
else
echo "Creating new client: $$ID"
hydra create oauth2-client --endpoint http://hydra:4445 --id "$$ID" "$$@"
fi
}
init-rp:
image: alpine:latest
env_file:
- .env
command:
- /bin/sh
- -ec
- |
apk add --no-cache curl tar
HYDRA_CLI_VERSION="$${HYDRA_VERSION:-v26.2.0}"
HYDRA_CLI_VERSION="$${HYDRA_CLI_VERSION%-distroless}"
HYDRA_CLI_ARCHIVE_VERSION="$${HYDRA_CLI_VERSION#v}"
curl -fsSLo /tmp/hydra.tar.gz "https://github.com/ory/hydra/releases/download/$${HYDRA_CLI_VERSION}/hydra_$${HYDRA_CLI_ARCHIVE_VERSION}-linux_64bit.tar.gz"
tar -xzf /tmp/hydra.tar.gz -C /usr/local/bin hydra
rm /tmp/hydra.tar.gz
upsert_client "adminfront" \
--name "AdminFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri "$${ADMINFRONT_CALLBACK_URLS:-http://localhost:5173/auth/callback}"
# Function to create or update OAuth2 client (Idempotency)
upsert_client() {
ID=$$1
shift
if hydra get oauth2-client --endpoint "$${HYDRA_ADMIN_URL}" "$$ID" >/dev/null 2>&1; then
echo "Updating existing client: $$ID"
hydra update oauth2-client --endpoint "$${HYDRA_ADMIN_URL}" "$$ID" "$$@"
else
echo "Creating new client: $$ID"
hydra create oauth2-client --endpoint "$${HYDRA_ADMIN_URL}" --id "$$ID" "$$@"
fi
}
upsert_client "devfront" \
--name "DevFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri "$${DEVFRONT_CALLBACK_URLS:-http://localhost:5174/auth/callback}"
upsert_client "adminfront" \
--name "AdminFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri "$${ADMINFRONT_CALLBACK_URLS:-$${ADMINFRONT_URL}/auth/callback}"
upsert_client "orgfront" \
--name "OrgFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri "$${ORGFRONT_CALLBACK_URLS:-http://localhost:5175/auth/callback,http://172.16.10.176:5175/auth/callback, https://baron-orgchart.hmac.kr/auth/callback}"
upsert_client "devfront" \
--name "DevFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri "$${DEVFRONT_CALLBACK_URLS:-$${DEVFRONT_URL}/auth/callback}"
upsert_client "$${OATHKEEPER_INTROSPECT_CLIENT_ID:-oathkeeper-introspect}" \
--secret "$${OATHKEEPER_INTROSPECT_CLIENT_SECRET:-oathkeeper-secret}" \
--grant-type client_credentials \
--response-type token \
--scope openid,offline_access,profile,email
depends_on:
ory_stack_check:
condition: service_completed_successfully
networks:
- hydranet
upsert_client "orgfront" \
--name "OrgFront" \
--grant-type authorization_code,refresh_token \
--response-type code \
--scope openid,offline_access,profile,email \
--token-endpoint-auth-method none \
--redirect-uri "$${ORGFRONT_CALLBACK_URLS:-$${ORGFRONT_URL}/auth/callback}"
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: baron_backend
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-development}
- GO_ENV=${APP_ENV:-development}
- COOKIE_SECRET=${COOKIE_SECRET}
- JWT_SECRET=${JWT_SECRET}
- NAVER_CLOUD_ACCESS_KEY=${NAVER_CLOUD_ACCESS_KEY}
- NAVER_CLOUD_SECRET_KEY=${NAVER_CLOUD_SECRET_KEY}
- NAVER_CLOUD_SERVICE_ID=${NAVER_CLOUD_SERVICE_ID}
- NAVER_SENDER_PHONE_NUMBER=${NAVER_SENDER_PHONE_NUMBER}
- USERFRONT_URL=${USERFRONT_URL}
- REDIS_ADDR=${REDIS_ADDR}
- IDP_PROVIDER=${IDP_PROVIDER:-ory}
- KRATOS_ADMIN_URL=${KRATOS_ADMIN_URL:-http://kratos:4434}
- HYDRA_ADMIN_URL=${HYDRA_ADMIN_URL:-http://hydra:4445}
- HYDRA_PUBLIC_URL=${HYDRA_PUBLIC_URL:-http://hydra:4444}
- DB_HOST=postgres
- CLICKHOUSE_HOST=clickhouse
- CLICKHOUSE_PORT=${CLICKHOUSE_PORT_NATIVE:-9000}
- CLICKHOUSE_USER=${CLICKHOUSE_USER:-baron}
- CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD:-password}
- SEED_TENANT_CSV_PATH=/app/seed-tenant.csv
depends_on:
clickhouse:
condition: service_healthy
redis:
condition: service_healthy
oathkeeper:
condition: service_healthy
kratos:
condition: service_started
hydra:
condition: service_started
keto:
condition: service_started
infra_check:
condition: service_started
networks:
- baron_net
- ory-net
volumes:
- ./backend:/app
- ./adminfront/seed-tenant.csv:/app/seed-tenant.csv:ro
command: ["go", "run", "./cmd/server"]
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
upsert_client "$${OATHKEEPER_INTROSPECT_CLIENT_ID:-oathkeeper-introspect}" \
--secret "$${OATHKEEPER_INTROSPECT_CLIENT_SECRET:-oathkeeper-secret}" \
--grant-type client_credentials \
--response-type token \
--scope openid,offline_access,profile,email
depends_on:
ory_stack_check:
condition: service_completed_successfully
networks:
- hydranet
adminfront:
build:
context: ./adminfront
dockerfile: Dockerfile
container_name: baron_adminfront
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-development}
- API_PROXY_TARGET=http://baron_backend:3000
ports:
- "${ADMINFRONT_PORT:-5173}:5173"
volumes:
- ./adminfront:/app
- /app/node_modules
networks:
- baron_net
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: baron_backend
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-development}
- GO_ENV=${APP_ENV:-development}
- COOKIE_SECRET=${COOKIE_SECRET}
- JWT_SECRET=${JWT_SECRET}
- NAVER_CLOUD_ACCESS_KEY=${NAVER_CLOUD_ACCESS_KEY}
- NAVER_CLOUD_SECRET_KEY=${NAVER_CLOUD_SECRET_KEY}
- NAVER_CLOUD_SERVICE_ID=${NAVER_CLOUD_SERVICE_ID}
- NAVER_SENDER_PHONE_NUMBER=${NAVER_SENDER_PHONE_NUMBER}
- USERFRONT_URL=${USERFRONT_URL}
- REDIS_ADDR=${REDIS_ADDR}
- IDP_PROVIDER=${IDP_PROVIDER:-ory}
- KRATOS_ADMIN_URL=${KRATOS_ADMIN_URL:-http://kratos:4434}
- HYDRA_ADMIN_URL=${HYDRA_ADMIN_URL:-http://hydra:4445}
- HYDRA_PUBLIC_URL=${HYDRA_PUBLIC_URL}
- DB_HOST=postgres
- CLICKHOUSE_HOST=clickhouse
- CLICKHOUSE_PORT=${CLICKHOUSE_PORT_NATIVE:-9000}
- CLICKHOUSE_USER=${CLICKHOUSE_USER:-baron}
- CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD:-password}
- SEED_TENANT_CSV_PATH=/app/seed-tenant.csv
depends_on:
clickhouse:
condition: service_healthy
redis:
condition: service_healthy
oathkeeper:
condition: service_healthy
kratos:
condition: service_started
hydra:
condition: service_started
keto:
condition: service_started
infra_check:
condition: service_started
networks:
- baron_net
- ory-net
volumes:
- ./backend:/app
- ./adminfront/seed-tenant.csv:/app/seed-tenant.csv:ro
command: ["go", "run", "./cmd/server"]
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
devfront:
build:
context: ./devfront
dockerfile: Dockerfile
container_name: baron_devfront
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-development}
- API_PROXY_TARGET=http://baron_backend:3000
ports:
- "${DEVFRONT_PORT:-5174}:5173"
volumes:
- ./devfront:/app
- /app/node_modules
networks:
- baron_net
adminfront:
build:
context: ./adminfront
dockerfile: Dockerfile
container_name: baron_adminfront
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-development}
- API_PROXY_TARGET=http://baron_backend:3000
ports:
- "${ADMINFRONT_PORT:-5173}:5173"
volumes:
- ./adminfront:/app
- /app/node_modules
networks:
- baron_net
orgfront:
build:
context: ./orgfront
dockerfile: Dockerfile
container_name: baron_orgfront
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-development}
- API_PROXY_TARGET=http://baron_backend:3000
- USERFRONT_URL=${USERFRONT_URL}
ports:
- "${ORGFRONT_PORT:-5175}:5175"
volumes:
- ./orgfront:/app
- /app/node_modules
networks:
- baron_net
devfront:
build:
context: ./devfront
dockerfile: Dockerfile
container_name: baron_devfront
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-development}
- API_PROXY_TARGET=http://baron_backend:3000
ports:
- "${DEVFRONT_PORT:-5174}:5173"
volumes:
- ./devfront:/app
- /app/node_modules
networks:
- baron_net
userfront:
build:
context: .
dockerfile: userfront/Dockerfile
container_name: baron_userfront
env_file:
- .env
environment:
- BACKEND_URL=${BACKEND_URL:-}
- USERFRONT_URL=${USERFRONT_URL}
- APP_ENV=${APP_ENV}
networks:
- baron_net
- ory-net
depends_on:
backend:
condition: service_healthy
command: >
/bin/sh -c "mkdir -p /usr/share/nginx/html/assets &&
echo \"BACKEND_URL=$${BACKEND_URL}\" >> /usr/share/nginx/html/assets/.env &&
echo \"USERFRONT_URL=$${USERFRONT_URL}\" >> /usr/share/nginx/html/assets/.env &&
echo \"APP_ENV=$${APP_ENV}\" >> /usr/share/nginx/html/assets/.env &&
cp /usr/share/nginx/html/assets/.env /usr/share/nginx/html/.env &&
nginx -g 'daemon off;'"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:5000/"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
orgfront:
build:
context: ./orgfront
dockerfile: Dockerfile
container_name: baron_orgfront
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-development}
- API_PROXY_TARGET=http://baron_backend:3000
- USERFRONT_URL=${USERFRONT_URL}
ports:
- "${ORGFRONT_PORT:-5175}:5175"
volumes:
- ./orgfront:/app
- /app/node_modules
networks:
- baron_net
infra_check:
image: alpine
command: ["echo", "Infrastructure assumed running"]
networks:
- baron_net
userfront:
build:
context: .
dockerfile: userfront/Dockerfile
container_name: baron_userfront
env_file:
- .env
environment:
- BACKEND_URL=${BACKEND_URL:-}
- USERFRONT_URL=${USERFRONT_URL}
- APP_ENV=${APP_ENV}
networks:
- baron_net
- ory-net
depends_on:
backend:
condition: service_healthy
command: >
/bin/sh -c "mkdir -p /usr/share/nginx/html/assets &&
echo \"BACKEND_URL=$${BACKEND_URL}\" >> /usr/share/nginx/html/assets/.env &&
echo \"USERFRONT_URL=$${USERFRONT_URL}\" >> /usr/share/nginx/html/assets/.env &&
echo \"APP_ENV=$${APP_ENV}\" >> /usr/share/nginx/html/assets/.env &&
cp /usr/share/nginx/html/assets/.env /usr/share/nginx/html/.env &&
nginx -g 'daemon off;'"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:5000/"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
infra_check:
image: alpine
command: ["echo", "Infrastructure assumed running"]
networks:
- baron_net
volumes:
postgres_data:
clickhouse_data:
redis_data:
ory_postgres_data:
ory_clickhouse_data:
oathkeeper_logs:
postgres_data:
clickhouse_data:
redis_data:
ory_postgres_data:
ory_clickhouse_data:
oathkeeper_logs:
networks:
baron_net:
external: true
name: baron_net
public_net:
external: true
name: public_net
ory-net:
external: true
name: ory-net
hydranet:
external: true
name: hydranet
kratosnet:
external: true
name: kratosnet
baron_net:
external: true
name: baron_net
public_net:
external: true
name: public_net
ory-net:
external: true
name: ory-net
hydranet:
external: true
name: hydranet
kratosnet:
external: true
name: kratosnet