Skip to content

Commit 04d57d9

Browse files
authored
fix(emulator): move mock OAuth off 8114 to avoid pnpm dev conflict (#1385)
## Summary - The emulator's mock OAuth server bound to `${PORT_PREFIX}14` (8114) inside the VM and the host forwarded the same port, colliding with `pnpm dev`'s mock-oauth-server on 8114. - Moves the emulator's mock OAuth to `EMULATOR_MOCK_OAUTH_PORT` (default `26704`, joining the existing `267xx` host port block) and binds the VM-internal mock to the same port. Same port on both sides keeps the OIDC issuer URL (`http://localhost:26704`) resolvable identically from the browser and from the backend inside the VM. - Plumbed via `runtime-config.iso` as `STACK_EMULATOR_MOCK_OAUTH_HOST_PORT`, read by cloud-init into `STACK_OAUTH_MOCK_URL` + new `STACK_OAUTH_MOCK_PORT`; `mock-oauth-server` now prefers `STACK_OAUTH_MOCK_PORT` so `pnpm dev` (which doesn't set it) stays on 8114. ## Files - `docker/local-emulator/qemu/run-emulator.sh` — new `EMULATOR_MOCK_OAUTH_PORT`, hostfwd/ensure_ports_free/runtime.env updates - `docker/local-emulator/qemu/cloud-init/emulator/user-data` — reads the host port, sets `STACK_OAUTH_MOCK_URL` + `STACK_OAUTH_MOCK_PORT` - `apps/mock-oauth-server/src/index.ts` — honors `STACK_OAUTH_MOCK_PORT` - `packages/stack-cli/src/commands/emulator.ts` — default + runtime.env entry ## Test plan - [ ] `pnpm emulator:build` succeeds and new snapshot boots - [ ] `stack emulator start` with `pnpm dev` running on 8114 — no port collision - [ ] OAuth sign-in via mock provider completes end-to-end in the emulator - [ ] `pnpm dev` mock OAuth unchanged (still 8114) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * The mock OAuth server port is now configurable in the local emulator with a sensible default, allowing custom port assignments via environment variable. * **Improvements** * Updated port forwarding and environment variable handling to ensure consistent mock OAuth endpoint configuration across host and guest systems in the emulator. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 2f71990 commit 04d57d9

4 files changed

Lines changed: 21 additions & 9 deletions

File tree

apps/mock-oauth-server/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Provider, { errors } from 'oidc-provider';
55

66
const stackPortPrefix = process.env.NEXT_PUBLIC_STACK_PORT_PREFIX ?? "81";
77
const defaultMockOAuthPort = Number(`${stackPortPrefix}14`);
8-
const port = Number(process.env.PORT ?? defaultMockOAuthPort);
8+
const port = Number(process.env.STACK_OAUTH_MOCK_PORT ?? process.env.PORT ?? defaultMockOAuthPort);
99
const backendPortForRedirects = `${stackPortPrefix}02`;
1010
const emulatorBackendPort = process.env.STACK_EMULATOR_BACKEND_PORT ?? "32102";
1111
const providerIds = [

docker/local-emulator/qemu/cloud-init/emulator/user-data

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ write_files:
130130
HP_DASHBOARD="$STACK_EMULATOR_DASHBOARD_HOST_PORT"
131131
HP_MINIO="$STACK_EMULATOR_MINIO_HOST_PORT"
132132
HP_INBUCKET="$STACK_EMULATOR_INBUCKET_HOST_PORT"
133+
# Mock OAuth binds to this port inside the VM and the host forwards the
134+
# same port through, so the OIDC issuer URL is reachable identically
135+
# from the browser and from the backend. Falls back to ${P}14 for
136+
# older ISOs that don't set it.
137+
HP_MOCK_OAUTH="${STACK_EMULATOR_MOCK_OAUTH_HOST_PORT:-${P}14}"
133138

134139
cat <<COMPUTED
135140
STACK_SKIP_MIGRATIONS=true
@@ -153,7 +158,8 @@ write_files:
153158
STACK_CLICKHOUSE_URL=http://${DEPS_HOST}:8123
154159
STACK_EMAIL_MONITOR_VERIFICATION_CALLBACK_URL=http://localhost:${HP_DASHBOARD}/handler/email-verification
155160
STACK_EMAIL_MONITOR_INBUCKET_API_URL=http://${DEPS_HOST}:9001
156-
STACK_OAUTH_MOCK_URL=http://localhost:${P}14
161+
STACK_OAUTH_MOCK_URL=http://localhost:${HP_MOCK_OAUTH}
162+
STACK_OAUTH_MOCK_PORT=${HP_MOCK_OAUTH}
157163
STACK_FREESTYLE_API_ENDPOINT=http://${DEPS_HOST}:8180
158164
STACK_STRIPE_MOCK_PORT=12111
159165
NEXT_PUBLIC_STACK_STRIPE_PUBLISHABLE_KEY=pk_test_mock_publishable_key_for_local_emulator

docker/local-emulator/qemu/run-emulator.sh

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ EMULATOR_DASHBOARD_PORT="${EMULATOR_DASHBOARD_PORT:-26700}"
3535
EMULATOR_BACKEND_PORT="${EMULATOR_BACKEND_PORT:-26701}"
3636
EMULATOR_MINIO_PORT="${EMULATOR_MINIO_PORT:-26702}"
3737
EMULATOR_INBUCKET_PORT="${EMULATOR_INBUCKET_PORT:-26703}"
38+
EMULATOR_MOCK_OAUTH_PORT="${EMULATOR_MOCK_OAUTH_PORT:-26704}"
3839

3940
RED='\033[0;31m'
4041
GREEN='\033[0;32m'
@@ -214,6 +215,7 @@ write_runtime_config_iso() {
214215
printf "STACK_EMULATOR_BACKEND_HOST_PORT=%s\n" "$EMULATOR_BACKEND_PORT"
215216
printf "STACK_EMULATOR_MINIO_HOST_PORT=%s\n" "$EMULATOR_MINIO_PORT"
216217
printf "STACK_EMULATOR_INBUCKET_HOST_PORT=%s\n" "$EMULATOR_INBUCKET_PORT"
218+
printf "STACK_EMULATOR_MOCK_OAUTH_HOST_PORT=%s\n" "$EMULATOR_MOCK_OAUTH_PORT"
217219
printf "STACK_EMULATOR_VM_DIR_HOST=%s\n" "$vm_dir_host"
218220
} > "$cfg_dir/runtime.env"
219221
cp "$base_env" "$cfg_dir/base.env"
@@ -351,11 +353,12 @@ build_qemu_cmd() {
351353
netdev+=",hostfwd=tcp:127.0.0.1:${EMULATOR_BACKEND_PORT}-:${PORT_PREFIX}02"
352354
netdev+=",hostfwd=tcp:127.0.0.1:${EMULATOR_MINIO_PORT}-:9090"
353355
netdev+=",hostfwd=tcp:127.0.0.1:${EMULATOR_INBUCKET_PORT}-:9001"
354-
# Mock OAuth server: browser redirects land on `localhost:${PORT_PREFIX}14`
355-
# (backend sets STACK_OAUTH_MOCK_URL to that value), so we forward host:port
356-
# ↔ VM:port on the same number. Collides with pnpm dev, but the two modes
357-
# are mutually exclusive.
358-
netdev+=",hostfwd=tcp:127.0.0.1:${PORT_PREFIX}14-:${PORT_PREFIX}14"
356+
# Mock OAuth server: the VM-internal mock binds to $EMULATOR_MOCK_OAUTH_PORT
357+
# (overrides the pnpm-dev default of ${PORT_PREFIX}14 via STACK_OAUTH_MOCK_PORT
358+
# threaded through runtime-config.iso). Host and guest use the same port so
359+
# the OIDC issuer URL `http://localhost:${EMULATOR_MOCK_OAUTH_PORT}` resolves
360+
# identically from the browser and from the backend inside the VM.
361+
netdev+=",hostfwd=tcp:127.0.0.1:${EMULATOR_MOCK_OAUTH_PORT}-:${EMULATOR_MOCK_OAUTH_PORT}"
359362

360363
# In snapshot-resume mode the QEMU command-line MUST match the device set
361364
# used at snapshot capture time, otherwise migration replay fails (broken
@@ -499,7 +502,7 @@ tail_vm_logs() {
499502
}
500503

501504
ensure_ports_free() {
502-
local ports=("$EMULATOR_DASHBOARD_PORT" "$EMULATOR_BACKEND_PORT" "$EMULATOR_MINIO_PORT" "$EMULATOR_INBUCKET_PORT" "${PORT_PREFIX}14")
505+
local ports=("$EMULATOR_DASHBOARD_PORT" "$EMULATOR_BACKEND_PORT" "$EMULATOR_MINIO_PORT" "$EMULATOR_INBUCKET_PORT" "$EMULATOR_MOCK_OAUTH_PORT")
503506
local port
504507
for port in "${ports[@]}"; do
505508
if lsof -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1; then
@@ -761,7 +764,7 @@ cmd_start() {
761764

762765
info "Starting QEMU local emulator"
763766
info "Arch: $ARCH | Accel: $ACCEL"
764-
info "Ports: Dashboard=$EMULATOR_DASHBOARD_PORT Backend=$EMULATOR_BACKEND_PORT MinIO=$EMULATOR_MINIO_PORT Inbucket=$EMULATOR_INBUCKET_PORT"
767+
info "Ports: Dashboard=$EMULATOR_DASHBOARD_PORT Backend=$EMULATOR_BACKEND_PORT MinIO=$EMULATOR_MINIO_PORT Inbucket=$EMULATOR_INBUCKET_PORT MockOAuth=$EMULATOR_MOCK_OAUTH_PORT"
765768

766769
local using_snapshot=0
767770
if snapshot_available; then

packages/stack-cli/src/commands/emulator.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const DEFAULT_EMULATOR_BACKEND_PORT = 26701;
1414
const DEFAULT_EMULATOR_DASHBOARD_PORT = 26700;
1515
const DEFAULT_EMULATOR_MINIO_PORT = 26702;
1616
const DEFAULT_EMULATOR_INBUCKET_PORT = 26703;
17+
const DEFAULT_EMULATOR_MOCK_OAUTH_PORT = 26704;
1718
const DEFAULT_PORT_PREFIX = "81";
1819
const GITHUB_API = "https://api.github.com";
1920
const DEFAULT_REPO = "stack-auth/stack-auth";
@@ -188,13 +189,15 @@ function prepareRuntimeConfigIso(): void {
188189
const backendPort = envPort("EMULATOR_BACKEND_PORT", DEFAULT_EMULATOR_BACKEND_PORT);
189190
const minioPort = envPort("EMULATOR_MINIO_PORT", DEFAULT_EMULATOR_MINIO_PORT);
190191
const inbucketPort = envPort("EMULATOR_INBUCKET_PORT", DEFAULT_EMULATOR_INBUCKET_PORT);
192+
const mockOAuthPort = envPort("EMULATOR_MOCK_OAUTH_PORT", DEFAULT_EMULATOR_MOCK_OAUTH_PORT);
191193

192194
const runtimeEnv = [
193195
`STACK_EMULATOR_PORT_PREFIX=${portPrefix}`,
194196
`STACK_EMULATOR_DASHBOARD_HOST_PORT=${dashboardPort}`,
195197
`STACK_EMULATOR_BACKEND_HOST_PORT=${backendPort}`,
196198
`STACK_EMULATOR_MINIO_HOST_PORT=${minioPort}`,
197199
`STACK_EMULATOR_INBUCKET_HOST_PORT=${inbucketPort}`,
200+
`STACK_EMULATOR_MOCK_OAUTH_HOST_PORT=${mockOAuthPort}`,
198201
`STACK_EMULATOR_VM_DIR_HOST=${vmDir}`,
199202
"",
200203
].join("\n");

0 commit comments

Comments
 (0)