АРХ - NODEDC PLATFORM: локальный Authentik и reverse proxy
This commit is contained in:
parent
0f89c4d126
commit
55db22b8d2
|
|
@ -52,6 +52,17 @@ task.local.nodedc -> Plane proxy/runtime
|
|||
|
||||
Все внешние запросы идут через reverse proxy.
|
||||
|
||||
На этом этапе reverse proxy реализуется через Caddy, а Authentik запускается за ним без прямой публикации host ports.
|
||||
|
||||
Текущие приложения подключаются как внешние upstream:
|
||||
|
||||
```text
|
||||
launcher.local.nodedc -> host.docker.internal:5173
|
||||
task.local.nodedc -> host.docker.internal:8090
|
||||
```
|
||||
|
||||
Это сохраняет Launcher и Plane в их текущих репозиториях и runtime-папках.
|
||||
|
||||
## Environment
|
||||
|
||||
Базовые переменные должны жить в:
|
||||
|
|
@ -66,11 +77,39 @@ platform/infra/.env
|
|||
platform/infra/.env.example
|
||||
```
|
||||
|
||||
Для генерации локальных secrets:
|
||||
|
||||
```bash
|
||||
cd /Users/dcconstructions/Downloads/mnt/NODEDC/platform
|
||||
./infra/scripts/init-dev-env.sh
|
||||
```
|
||||
|
||||
Скрипт создает `platform/infra/.env`, выставляет права `600` и не перезаписывает существующий файл.
|
||||
|
||||
## Start commands
|
||||
|
||||
```bash
|
||||
cd /Users/dcconstructions/Downloads/mnt/NODEDC/platform
|
||||
docker compose --env-file infra/.env -f infra/docker-compose.dev.yml up -d
|
||||
```
|
||||
|
||||
Проверка:
|
||||
|
||||
```bash
|
||||
docker compose --env-file infra/.env -f infra/docker-compose.dev.yml ps
|
||||
curl -I -H 'Host: auth.local.nodedc' http://127.0.0.1/
|
||||
curl -I -H 'Host: task.local.nodedc' http://127.0.0.1/
|
||||
```
|
||||
|
||||
## Authentik version note
|
||||
|
||||
Официальный compose Authentik для текущей ветки 2026.2 использует PostgreSQL, `server` и `worker`. Redis, указанный в раннем ТЗ как ожидаемый сервис, в актуальном официальном compose не используется. Если позже будет выбран старый pinned Authentik или отдельная HA-схема, Redis надо вернуть отдельной задачей.
|
||||
|
||||
## Implementation order
|
||||
|
||||
1. Согласовать локальные domain/port bindings.
|
||||
2. Добавить reverse proxy config.
|
||||
3. Поднять Authentik server, worker, Postgres и Redis.
|
||||
3. Поднять Authentik server, worker и Postgres.
|
||||
4. Прокинуть Authentik за proxy с корректными headers.
|
||||
5. Подключить текущий Launcher как внешний сервис или через compose service.
|
||||
6. Подключить текущий Plane runtime как внешний service target.
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
## Network
|
||||
|
||||
- [ ] Наружу опубликованы только reverse proxy ports.
|
||||
- [x] Local dev compose публикует только reverse proxy port.
|
||||
- [ ] Postgres не опубликован наружу в staging/production.
|
||||
- [ ] Redis не опубликован наружу в staging/production.
|
||||
- [ ] MinIO/storage не опубликован наружу в staging/production.
|
||||
- [ ] Внутренние API не доступны напрямую извне.
|
||||
- [ ] Authentik получает корректные `X-Forwarded-Proto`, `X-Forwarded-For`, `Host`.
|
||||
- [ ] WebSocket headers настроены для Authentik/Plane/live.
|
||||
- [x] Authentik получает `X-Forwarded-Proto`, `X-Forwarded-For`, `Host` через Caddy.
|
||||
- [x] Caddy reverse proxy сохраняет HTTP/1.1/WebSocket upgrade behavior для upstream.
|
||||
|
||||
## Authentik
|
||||
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
- [ ] Для каждого приложения задана отдельная access policy.
|
||||
- [ ] Группы app access заведены отдельно от app-local ролей.
|
||||
- [ ] MFA/enrollment policy вынесены в отдельный этап.
|
||||
- [x] Authentik local compose не публикует server/worker/Postgres ports напрямую.
|
||||
|
||||
## Launcher
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,28 @@ AUTH_DOMAIN=auth.local.nodedc
|
|||
LAUNCHER_DOMAIN=launcher.local.nodedc
|
||||
TASK_DOMAIN=task.local.nodedc
|
||||
|
||||
# proxy
|
||||
PLATFORM_HTTP_PORT=80
|
||||
LOCAL_LAUNCHER_UPSTREAM=host.docker.internal:5173
|
||||
LOCAL_TASK_MANAGER_UPSTREAM=host.docker.internal:8090
|
||||
|
||||
# authentik image
|
||||
AUTHENTIK_IMAGE=ghcr.io/goauthentik/server
|
||||
AUTHENTIK_TAG=2026.2.2
|
||||
|
||||
# authentik database
|
||||
PG_DB=authentik
|
||||
PG_USER=authentik
|
||||
PG_PASS=change-me-generate-with-infra-scripts-init-dev-env
|
||||
|
||||
# authentik
|
||||
AUTHENTIK_SECRET_KEY=
|
||||
AUTHENTIK_POSTGRES_PASSWORD=
|
||||
AUTHENTIK_REDIS_HOST=redis-authentik
|
||||
AUTHENTIK_SECRET_KEY=change-me-generate-with-infra-scripts-init-dev-env
|
||||
AUTHENTIK_ERROR_REPORTING__ENABLED=false
|
||||
|
||||
# optional first-start bootstrap
|
||||
# AUTHENTIK_BOOTSTRAP_EMAIL=admin@nodedc.local
|
||||
# AUTHENTIK_BOOTSTRAP_PASSWORD=
|
||||
# AUTHENTIK_BOOTSTRAP_TOKEN=
|
||||
|
||||
# launcher oidc
|
||||
LAUNCHER_OIDC_ISSUER=http://auth.local.nodedc/application/o/launcher/
|
||||
|
|
@ -21,10 +39,6 @@ PLANE_OIDC_CLIENT_SECRET=
|
|||
PLANE_OIDC_REDIRECT_URI=http://task.local.nodedc/auth/oidc/callback
|
||||
|
||||
# security
|
||||
SESSION_SECRET=
|
||||
SESSION_SECRET=change-me-generate-with-infra-scripts-init-dev-env
|
||||
COOKIE_DOMAIN=.local.nodedc
|
||||
COOKIE_SECURE=false
|
||||
|
||||
# current external local apps
|
||||
LOCAL_LAUNCHER_URL=http://localhost:5173
|
||||
LOCAL_TASK_MANAGER_URL=http://localhost:8090
|
||||
|
|
|
|||
|
|
@ -8,19 +8,57 @@
|
|||
- shared env examples;
|
||||
- будущие docker compose файлы.
|
||||
|
||||
На нулевом этапе здесь фиксируется только каркас. Рабочий `docker-compose.dev.yml` создается отдельным этапом после согласования ports/domains и стратегии подключения текущих Launcher/Plane runtime.
|
||||
Первый local dev слой проксирует текущие локальные приложения без физического переноса репозиториев:
|
||||
|
||||
- `auth.local.nodedc` -> `authentik-server:9000`;
|
||||
- `launcher.local.nodedc` -> `host.docker.internal:5173`;
|
||||
- `task.local.nodedc` -> `host.docker.internal:8090`.
|
||||
|
||||
Authentik построен по актуальной официальной Docker Compose схеме 2026.2: PostgreSQL 16, server и worker. Redis для Authentik в этой версии официального compose не используется.
|
||||
|
||||
## Expected files
|
||||
|
||||
```text
|
||||
infra/
|
||||
.env.example
|
||||
scripts/init-dev-env.sh
|
||||
docker-compose.dev.yml
|
||||
docker-compose.staging.yml
|
||||
reverse-proxy/
|
||||
authentik/
|
||||
```
|
||||
|
||||
## Local start
|
||||
|
||||
1. Add local domains to `/etc/hosts`:
|
||||
|
||||
```text
|
||||
127.0.0.1 auth.local.nodedc
|
||||
127.0.0.1 launcher.local.nodedc
|
||||
127.0.0.1 task.local.nodedc
|
||||
```
|
||||
|
||||
2. Generate local secrets:
|
||||
|
||||
```bash
|
||||
./infra/scripts/init-dev-env.sh
|
||||
```
|
||||
|
||||
3. Start infra:
|
||||
|
||||
```bash
|
||||
docker compose --env-file infra/.env -f infra/docker-compose.dev.yml up -d
|
||||
```
|
||||
|
||||
4. Check services:
|
||||
|
||||
```bash
|
||||
docker compose --env-file infra/.env -f infra/docker-compose.dev.yml ps
|
||||
curl -I -H 'Host: auth.local.nodedc' http://127.0.0.1/
|
||||
```
|
||||
|
||||
Generated Authentik bootstrap credentials are stored only in `infra/.env`.
|
||||
|
||||
## Current decision
|
||||
|
||||
Текущий Plane runtime не переносится в compose платформы до backup и отдельного шага миграции.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
# Authentik Local Bootstrap
|
||||
|
||||
This directory stores local Authentik bootstrap assets for NODE.DC.
|
||||
|
||||
## Current scope
|
||||
|
||||
The first infra pass runs Authentik from the official Docker Compose shape for the 2026.2 release line:
|
||||
|
||||
- PostgreSQL 16;
|
||||
- authentik server;
|
||||
- authentik worker;
|
||||
- no Redis service in the current official compose template;
|
||||
- Caddy reverse proxy in front of Authentik and current local apps.
|
||||
|
||||
## Bootstrap variables
|
||||
|
||||
For a first local install, put these variables in `infra/.env`:
|
||||
|
||||
```bash
|
||||
AUTHENTIK_BOOTSTRAP_EMAIL=admin@nodedc.local
|
||||
AUTHENTIK_BOOTSTRAP_PASSWORD=<local generated password>
|
||||
AUTHENTIK_BOOTSTRAP_TOKEN=<local generated token>
|
||||
```
|
||||
|
||||
These are read only on first startup. Do not commit `infra/.env`.
|
||||
|
||||
## Future blueprint work
|
||||
|
||||
Later phases should add reproducible configuration for:
|
||||
|
||||
- NODE.DC Launcher Application/Provider;
|
||||
- NODE.DC Task Manager Application/Provider;
|
||||
- groups and policies;
|
||||
- admin service token scope;
|
||||
- exports or blueprints for repeatable setup.
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
name: nodedc-platform
|
||||
|
||||
services:
|
||||
reverse-proxy:
|
||||
image: docker.io/library/caddy:2-alpine
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- path: .env
|
||||
required: false
|
||||
ports:
|
||||
- "${PLATFORM_HTTP_PORT:-80}:80"
|
||||
volumes:
|
||||
- ./reverse-proxy/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- caddy-data:/data
|
||||
- caddy-config:/config
|
||||
depends_on:
|
||||
authentik-server:
|
||||
condition: service_started
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
postgresql-authentik:
|
||||
image: docker.io/library/postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- path: .env
|
||||
required: false
|
||||
environment:
|
||||
POSTGRES_DB: ${PG_DB:-authentik}
|
||||
POSTGRES_PASSWORD: ${PG_PASS:?database password required}
|
||||
POSTGRES_USER: ${PG_USER:-authentik}
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
volumes:
|
||||
- authentik-database:/var/lib/postgresql/data
|
||||
|
||||
authentik-server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.2}
|
||||
command: server
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- path: .env
|
||||
required: false
|
||||
environment:
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql-authentik
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS:?database password required}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
|
||||
AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS: ${AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS:-127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,::1/128}
|
||||
depends_on:
|
||||
postgresql-authentik:
|
||||
condition: service_healthy
|
||||
expose:
|
||||
- "9000"
|
||||
- "9443"
|
||||
shm_size: 512mb
|
||||
volumes:
|
||||
- authentik-data:/data
|
||||
- ./authentik/custom-templates:/templates
|
||||
|
||||
authentik-worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.2}
|
||||
command: worker
|
||||
restart: unless-stopped
|
||||
user: root
|
||||
env_file:
|
||||
- path: .env
|
||||
required: false
|
||||
environment:
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql-authentik
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS:?database password required}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
|
||||
depends_on:
|
||||
postgresql-authentik:
|
||||
condition: service_healthy
|
||||
shm_size: 512mb
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- authentik-data:/data
|
||||
- authentik-certs:/certs
|
||||
- ./authentik/custom-templates:/templates
|
||||
|
||||
volumes:
|
||||
authentik-database:
|
||||
authentik-data:
|
||||
authentik-certs:
|
||||
caddy-data:
|
||||
caddy-config:
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
auto_https off
|
||||
}
|
||||
|
||||
http://{$AUTH_DOMAIN:auth.local.nodedc} {
|
||||
reverse_proxy authentik-server:9000 {
|
||||
header_up Host {host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
}
|
||||
}
|
||||
|
||||
http://{$LAUNCHER_DOMAIN:launcher.local.nodedc} {
|
||||
reverse_proxy {$LOCAL_LAUNCHER_UPSTREAM:host.docker.internal:5173} {
|
||||
header_up Host {host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
}
|
||||
}
|
||||
|
||||
http://{$TASK_DOMAIN:task.local.nodedc} {
|
||||
reverse_proxy {$LOCAL_TASK_MANAGER_UPSTREAM:host.docker.internal:8090} {
|
||||
header_up Host {host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
INFRA_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
|
||||
ENV_FILE="$INFRA_DIR/.env"
|
||||
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
echo "Refusing to overwrite existing $ENV_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rand() {
|
||||
openssl rand -base64 "$1" | tr -d '\n'
|
||||
}
|
||||
|
||||
cat > "$ENV_FILE" <<EOF
|
||||
# domains
|
||||
AUTH_DOMAIN=auth.local.nodedc
|
||||
LAUNCHER_DOMAIN=launcher.local.nodedc
|
||||
TASK_DOMAIN=task.local.nodedc
|
||||
|
||||
# proxy
|
||||
PLATFORM_HTTP_PORT=80
|
||||
LOCAL_LAUNCHER_UPSTREAM=host.docker.internal:5173
|
||||
LOCAL_TASK_MANAGER_UPSTREAM=host.docker.internal:8090
|
||||
|
||||
# authentik image
|
||||
AUTHENTIK_IMAGE=ghcr.io/goauthentik/server
|
||||
AUTHENTIK_TAG=2026.2.2
|
||||
|
||||
# authentik database
|
||||
PG_DB=authentik
|
||||
PG_USER=authentik
|
||||
PG_PASS=$(rand 36)
|
||||
|
||||
# authentik core
|
||||
AUTHENTIK_SECRET_KEY=$(rand 60)
|
||||
AUTHENTIK_ERROR_REPORTING__ENABLED=false
|
||||
AUTHENTIK_BOOTSTRAP_EMAIL=admin@nodedc.local
|
||||
AUTHENTIK_BOOTSTRAP_PASSWORD=$(rand 36)
|
||||
AUTHENTIK_BOOTSTRAP_TOKEN=$(rand 36)
|
||||
|
||||
# launcher oidc
|
||||
LAUNCHER_OIDC_ISSUER=http://auth.local.nodedc/application/o/launcher/
|
||||
LAUNCHER_OIDC_CLIENT_ID=
|
||||
LAUNCHER_OIDC_CLIENT_SECRET=
|
||||
LAUNCHER_OIDC_REDIRECT_URI=http://launcher.local.nodedc/auth/callback
|
||||
|
||||
# plane oidc
|
||||
PLANE_OIDC_ISSUER=http://auth.local.nodedc/application/o/task-manager/
|
||||
PLANE_OIDC_CLIENT_ID=
|
||||
PLANE_OIDC_CLIENT_SECRET=
|
||||
PLANE_OIDC_REDIRECT_URI=http://task.local.nodedc/auth/oidc/callback
|
||||
|
||||
# security
|
||||
SESSION_SECRET=$(rand 48)
|
||||
COOKIE_DOMAIN=.local.nodedc
|
||||
COOKIE_SECURE=false
|
||||
EOF
|
||||
|
||||
chmod 600 "$ENV_FILE"
|
||||
echo "Created $ENV_FILE"
|
||||
echo "Open $ENV_FILE to read the generated local akadmin bootstrap credentials."
|
||||
Loading…
Reference in New Issue