Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions apps/docs/docs/development/dev-stack.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,52 @@ The dev proxy forwards:
- `/password-manager-api/` to the bundled Password Manager API container
- `/ws/terminal/` to the local ingest container

## Connect Agents

Use public mode when you need real hosts or VMs to connect agents back to your
local development stack:

```bash
./dev-stack.sh --public-host 100.x.y.z
```

Use your Tailscale IP for `100.x.y.z` when possible. It is more reliable than a
changing Wi-Fi address and avoids exposing your development laptop to the public
internet. If you omit the host, `./dev-stack.sh --public` tries to pick a
Tailscale IP first, then a local network IP.

Public mode changes only the externally required ports:

- web proxy: `0.0.0.0:3000`
- ingest HTTP health/JWKS: `0.0.0.0:8080`
- ingest gRPC for agents: `0.0.0.0:9443`
- Postgres remains private on `127.0.0.1:55432`

The script updates `.dev/dev.env`, regenerates the development ingest TLS cert
when the public host changes, and prints the agent connection details:

```text
Agent ingest address: 100.x.y.z:9443
Agent CA cert: deploy/dev-tls/server.crt
```

Validate the reachable endpoints from your laptop:

```bash
./dev-stack.sh --check-public
```

Agents must be able to reach `100.x.y.z:9443` and trust the generated CA cert.
For browser-based agent install bundles, the app will use
`AGENT_DOWNLOAD_BASE_URL=http://100.x.y.z:3000`, so the remote host must also be
able to reach port `3000`.

Switch back to loopback-only mode with:

```bash
./dev-stack.sh --local
```

## Stop Or Reset

Stop the stack while preserving local database volumes:
Expand Down
47 changes: 46 additions & 1 deletion deploy/scripts/test-dev-stack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,52 @@ EOF
fi
}

run_public_config_generation_test() {
local tmpdir repo_dir

tmpdir="$(mktemp -d "${TMPDIR:-/tmp}/ct-ops-dev-stack-public-test.XXXXXX")"
trap 'rm -rf "'"$tmpdir"'"' RETURN

repo_dir="${tmpdir}/ct-ops"
mkdir -p "$repo_dir"
cp -R \
"${REPO_ROOT}/apps" \
"${REPO_ROOT}/deploy" \
"${REPO_ROOT}/dev-stack.sh" \
"${REPO_ROOT}/docker-compose.dev-stack.yml" \
"${REPO_ROOT}/package.json" \
"${REPO_ROOT}/Makefile" \
"$repo_dir/"
cp "${REPO_ROOT}/deploy/password-manager-release.json" "$repo_dir/deploy/password-manager-release.json"

(
cd "$repo_dir"
./dev-stack.sh --public-host 192.0.2.10 --write-config-only >/dev/null
)

assert_contains "${repo_dir}/.dev/dev.env" "CT_OPS_DEV_BIND_ADDR=0.0.0.0"
assert_contains "${repo_dir}/.dev/dev.env" "CT_OPS_DEV_PUBLIC_HOST=192.0.2.10"
assert_contains "${repo_dir}/.dev/dev.env" "BETTER_AUTH_URL=http://192.0.2.10:3000"
assert_contains "${repo_dir}/.dev/dev.env" "AGENT_DOWNLOAD_BASE_URL=http://192.0.2.10:3000"
assert_contains "${repo_dir}/.dev/dev.env" "CT_OPS_DEV_AGENT_INGEST_ADDRESS=192.0.2.10:9443"
assert_contains "${repo_dir}/.dev/dev.env" "BETTER_AUTH_TRUSTED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000,http://192.0.2.10:3000"
assert_contains "${repo_dir}/apps/web/.env.local" "BETTER_AUTH_URL=http://192.0.2.10:3000"

(
cd "$repo_dir"
./dev-stack.sh --local --write-config-only >/dev/null
)

assert_contains "${repo_dir}/.dev/dev.env" "CT_OPS_DEV_BIND_ADDR=127.0.0.1"
assert_contains "${repo_dir}/.dev/dev.env" "CT_OPS_DEV_PUBLIC_HOST="
assert_contains "${repo_dir}/.dev/dev.env" "BETTER_AUTH_URL=http://localhost:3000"
assert_contains "${repo_dir}/.dev/dev.env" "CT_OPS_DEV_AGENT_INGEST_ADDRESS=localhost:9443"
}

run_static_wiring_test() {
assert_contains "${REPO_ROOT}/docker-compose.dev-stack.yml" "127.0.0.1:\${CT_OPS_DEV_PROXY_PORT}:80"
assert_contains "${REPO_ROOT}/docker-compose.dev-stack.yml" "\${CT_OPS_DEV_BIND_ADDR}:\${CT_OPS_DEV_PROXY_PORT}:80"
assert_contains "${REPO_ROOT}/docker-compose.dev-stack.yml" "\${CT_OPS_DEV_BIND_ADDR}:\${CT_OPS_DEV_INGEST_HTTP_PORT}:8080"
assert_contains "${REPO_ROOT}/docker-compose.dev-stack.yml" "\${CT_OPS_DEV_BIND_ADDR}:\${CT_OPS_DEV_INGEST_GRPC_PORT}:9443"
assert_contains "${REPO_ROOT}/docker-compose.dev-stack.yml" "127.0.0.1:\${POSTGRES_PORT}:5432"
assert_contains "${REPO_ROOT}/docker-compose.dev-stack.yml" "host.docker.internal:host-gateway"
assert_contains "${REPO_ROOT}/docker-compose.dev-stack.yml" "CT_OPS_DEV_WEB_UPSTREAM: web-dev:3001"
Expand All @@ -102,6 +146,7 @@ run_static_wiring_test() {
}

run_config_generation_test
run_public_config_generation_test
run_static_wiring_test

echo "dev-stack tests passed"
Loading
Loading