-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.auth.yml
More file actions
151 lines (140 loc) · 6.82 KB
/
Copy pathdocker-compose.auth.yml
File metadata and controls
151 lines (140 loc) · 6.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# Identity overlay — the IAP part, for real:
#
# make up-auth (docker compose -f docker-compose.yml -f docker-compose.auth.yml up)
#
# Adds oauth2-proxy (the OIDC-enforcing proxy) and dex (a local OIDC provider
# standing in for Google Workspace / Okta), and swaps nginx's auth include to
# auth-on.conf so every request must be authenticated. Sign in locally as
# dev@example.com / password.
#
# All secrets in this file are local-development placeholders. In production:
# point OAUTH2_PROXY_OIDC_ISSUER_URL at your real provider (and drop dex),
# use real client credentials and a random cookie secret, serve HTTPS, set
# OAUTH2_PROXY_COOKIE_SECURE=true, and restrict OAUTH2_PROXY_EMAIL_DOMAINS
# to your company domain.
name: click
services:
# Creates the MinIO identity clickd assumes to mint per-site deploy tokens:
# a non-root user (root can't call STS AssumeRole) whose policy allows all of
# sites/*, which the per-request session policy then narrows to one site.
# Mirrors giving clickd's task role sts:AssumeRole on a deploy role in AWS.
minio-deployer-init:
image: minio/mc:latest
depends_on:
- minio
entrypoint: >
/bin/sh -c "
until mc alias set local http://minio:9000 minioadmin minioadmin; do sleep 1; done &&
mc admin user add local clickdeployer clickdeployer123 &&
mc admin policy create local click-deployer /policy.json 2>/dev/null || true &&
mc admin policy attach local click-deployer --user clickdeployer 2>/dev/null || true &&
echo 'clickdeployer ready'
"
volumes:
- ./auth/minio-deployer-policy.json:/policy.json:ro
# Per-site document databases: one libSQL (SQLite) database per site instead
# of the shared Postgres table, so app data is isolated by a physical database
# boundary. Namespaces are the databases; clickd signs Ed25519 JWTs scoped to
# one namespace (read-only for browser SDK tokens). Self-hosted here; the same
# engine backs Turso cloud. See docs/turso-data-plane.md.
libsql:
image: ghcr.io/tursodatabase/libsql-server:latest
entrypoint: ["sqld"]
command:
- "--http-listen-addr=0.0.0.0:8080"
- "--admin-listen-addr=0.0.0.0:9090"
- "--enable-namespaces"
- "--db-path=/var/lib/sqld/data.sqld"
environment:
# The Ed25519 PUBLIC key; clickd holds the matching private key below.
# Local-dev placeholder — generate a fresh pair for production.
SQLD_AUTH_JWT_KEY: "15G4IpSjMxHcSw6DBNnT_j5kGprhZ2h0TT-9wfrCfU8"
# Persist databases so namespaces survive a restart, keeping libSQL and the
# Postgres site→db registry consistent (as postgres/minio also persist).
volumes:
- libsql-data:/var/lib/sqld
restart: unless-stopped
clickd:
environment:
# Turns on ownership + scoped deploy tokens. CLICK_DEPLOY_KEY/SECRET are
# the base identity clickd assumes from; CLICK_STS_ENDPOINT is MinIO's STS
# (its S3 endpoint). In production: set CLICK_DEPLOY_ROLE_ARN to a real
# IAM role, drop the key/secret (use clickd's own task role), and clear
# CLICK_STS_ENDPOINT to hit real AWS STS.
CLICK_DEPLOY_ROLE_ARN: arn:minio:iam:::role/click-deployer
CLICK_DEPLOY_KEY: clickdeployer
CLICK_DEPLOY_SECRET: clickdeployer123
CLICK_STS_ENDPOINT: http://minio:9000
# Per-site libSQL document backend. CLICK_LIBSQL_JWT_KEY is the Ed25519
# PRIVATE key (matches libsql's public key above) clickd signs tokens with.
# Local-dev placeholder.
CLICK_LIBSQL_JWT_KEY: "bUHiW41KFjLMG5qVF3ebSJ_OYxoNHbsU27P2j2Odkc_XkbgilKMzEdxLDoME2dP-PmQamuFnaHRNP73B-sJ9Tw"
CLICK_LIBSQL_URL: http://libsql:8080
CLICK_LIBSQL_ADMIN_URL: http://libsql:9090
CLICK_LIBSQL_SUFFIX: libsql
depends_on:
minio-deployer-init:
condition: service_completed_successfully
libsql:
condition: service_started
dex:
image: ghcr.io/dexidp/dex:v2.45.1
command: ["dex", "serve", "/etc/dex/dex.yml"]
volumes:
- ./auth/dex.yml:/etc/dex/dex.yml:ro
# Browsers reach dex via host port 5556 (*.localhost resolves to loopback
# natively); oauth2-proxy reaches it via this network alias. Both use the
# same URL, so the OIDC issuer check holds everywhere.
ports:
- "5556:5556"
networks:
default:
aliases:
- dex.click.localhost
restart: unless-stopped
oauth2-proxy:
image: quay.io/oauth2-proxy/oauth2-proxy:v7.15.3
environment:
OAUTH2_PROXY_HTTP_ADDRESS: 0.0.0.0:4180
OAUTH2_PROXY_REVERSE_PROXY: "true" # it only ever sits behind nginx
# Provider: dex locally; swap these three for Google/Okta in production.
OAUTH2_PROXY_PROVIDER: oidc
OAUTH2_PROXY_PROVIDER_DISPLAY_NAME: Dex (local)
OAUTH2_PROXY_OIDC_ISSUER_URL: http://dex.click.localhost:5556/dex
OAUTH2_PROXY_CLIENT_ID: click
OAUTH2_PROXY_CLIENT_SECRET: click-local-dev-secret
OAUTH2_PROXY_COOKIE_SECRET: 0123456789abcdef0123456789abcdef # dev only!
# One session for the whole platform: the cookie lives on the parent
# domain, the callback is registered once on the apex, and post-login
# redirects may target any site subdomain.
OAUTH2_PROXY_COOKIE_DOMAINS: .click.localhost
OAUTH2_PROXY_COOKIE_SECURE: "false" # local is plain http
OAUTH2_PROXY_REDIRECT_URL: http://click.localhost:8080/oauth2/callback
OAUTH2_PROXY_WHITELIST_DOMAINS: .click.localhost,.click.localhost:8080,click.localhost:8080
OAUTH2_PROXY_EMAIL_DOMAINS: "*" # dex only knows dev@example.com; restrict in production
# oauth2-proxy defaults to approval_prompt=force, which makes dex show
# a "Grant Access" consent screen even with skipApprovalScreen on.
OAUTH2_PROXY_APPROVAL_PROMPT: auto
OAUTH2_PROXY_SET_XAUTHREQUEST: "true" # answer nginx auth_request with X-Auth-Request-*
OAUTH2_PROXY_SKIP_PROVIDER_BUTTON: "true" # single provider — no interstitial page
OAUTH2_PROXY_UPSTREAMS: static://202 # auth_request mode; never proxies content
# Accept the click CLI's ID token as a bearer (issuer=audience pair): a
# request carrying `Authorization: Bearer <token>` for the click-cli
# client is authenticated straight from the token, no browser session.
# This is what lets `click rm` purge data as a real employee.
OAUTH2_PROXY_SKIP_JWT_BEARER_TOKENS: "true"
OAUTH2_PROXY_EXTRA_JWT_ISSUERS: "http://dex.click.localhost:5556/dex=click-cli"
depends_on:
- dex
# oauth2-proxy exits if OIDC discovery fails at boot (dex still starting);
# the restart policy retries until it comes up.
restart: unless-stopped
nginx:
volumes:
- ./nginx/click.conf:/etc/nginx/conf.d/default.conf:ro
- ./nginx/auth-on.conf:/etc/nginx/click-auth.conf:ro
- ./nginx/security-headers.conf:/etc/nginx/security-headers.conf:ro
depends_on:
- oauth2-proxy
volumes:
libsql-data: