Skip to main content

Local Emulator Edge (nginx)

Port-free browser URLs for MiniStack and LocalStack apps. nginx terminates HTTP on :80, routes by Host (*.cloudforge.localhost) to Docker-published ECS ports on the host.

See also: Local hostnames · Quick Start · StackPort


nginx vs Caddy (and “web console”)

nginx (this guide)CaddyTraefik
Reverse proxy by HostExcellentExcellentExcellent
Auto HTTPS / ACMEManual or certbotBuilt-inBuilt-in / labels
Config styleFamiliar server { }CaddyfileDynamic file/labels
Built-in app consoleNo (OSS)NoDashboard of routers, not app UIs
Commercial dashboardnginx Plus (paid)

Neither nginx nor Caddy opens a console “into” Jenkins/Grafana. They only proxy HTTP.

NeedUse
Browse CloudFormation / ECS / RDS in the emulatorStackPort on :8888
Manage proxy hostnames in a GUIOptional later: nginx Proxy Manager (separate product)
Day-to-day CloudForge edgenginx + generated conf.d (this doc)

We chose nginx because CloudForge operators often already know it, configs are easy to audit in git, and the “deep dive” into apps is already covered by StackPort + Manager — not by the reverse proxy.


Architecture

http://jenkins.cloudforge.localhost/ ← no port


/etc/hosts → 127.0.0.1


cfc-emulator-edge (nginx :80)
│ proxy_pass http://host.docker.internal:8080

ECS task on Docker host (MiniStack or LocalStack)

Prerequisites

  1. Install hostnames: ./scripts/setup-cloudforge-local-hosts.sh
  2. One emulator running on :4566
  3. Docker (edge runs as cfc-emulator-edge)

Quick start (Maven — preferred)

ministack-start / localstack-start bring up the full local stack in one process: emulator on :4566, StackPort (simulated AWS console) on :8888, and nginx edge on :80. Companion lifecycle (start / stop / restart / status) is owned by EmulatorLifecycle in cloudforge-core. After a local deploy, CloudForgeDeployment reconciles edge vhosts automatically.

# From repository root — once
./scripts/setup-cloudforge-local-hosts.sh

cd cfc-testing && java -cp "target/classes:target/dependency/*" \
com.cloudforgeci.samples.app.InteractiveDeployer --platform

# Deploy apps (Interactive Deployer option 6 / 8) — edge reconciles after deploy
open "http://localstack.cloudforge.localhost/"
open "http://stackport.cloudforge.localhost/"
open "http://nginx.cloudforge.localhost/"
open "http://jenkins.cloudforge.localhost/" # after Jenkins publish

Opt out of companions: CFC_EMULATOR_COMPANIONS=false, or individually CFC_STACKPORT_AUTOSTART=false / CFC_EDGE_AUTOSTART=false. Alternate HTTP port: CFC_EDGE_HTTP_PORT=8088.

Edge lifecycle goals (also driven by emulator start/stop)

GoalAction
cloudforge:emulator-edge-startCreate/start cfc-emulator-edge
cloudforge:emulator-edge-stopRemove edge container
cloudforge:emulator-edge-restartStop + start
cloudforge:emulator-edge-rebuildPull image, recreate
cloudforge:emulator-edge-statusRunning / healthy + routes
cloudforge:emulator-edge-reconcileRewrite vhosts from live host ports
cloudforge:emulator-edge-reloadnginx -s reload

Shell scripts under scripts/emulator-edge-*.sh call these Maven goals (no parallel Docker logic).

Generated files live under .emulator-edge/ (gitignored).


How reconcile maps apps

Reconcile scans docker ps for host port publishes and matches container ports to the same table as LOCAL_EMULATOR_HOSTS:

Container portHostname
4566localstack.cloudforge.localhost and/or ministack.cloudforge.localhost (+ emulator.cloudforge.localhost)
8888stackport.cloudforge.localhost
(edge self)nginx.cloudforge.localhost — status page, not a proxy
1958manager.cloudforge.localhost
8080jenkins.cloudforge.localhost
3000grafana.cloudforge.localhost (first occupant wins if clash)
9090prometheus.cloudforge.localhost
8200vault.cloudforge.localhost
8081nexus.cloudforge.localhost
9000sonarqube.cloudforge.localhost

Always available when the platform is up: localstack / ministack / emulator, stackport, and nginx (edge status).

Route53 (next phase)

Emulator Route53 records already exist for stacks with domain / subdomain. A later reconcile pass will:

  1. route53 list-resource-record-sets against :4566
  2. Map FQDN → stack → ECS host port
  3. Emit server_name blocks for those FQDNs (in addition to *.cloudforge.localhost)

Until then, use the shared *.cloudforge.localhost names.


LocalStack Jenkins note

If Jenkins was adapted with a path --prefix, prefer the direct ECS host port (reconcile does this). Opening http://jenkins.cloudforge.localhost/ should hit that port without the ELB path prefix.


Troubleshooting

SymptomCheck
Connection refused on :80mvn -f cfc-testing cloudforge:emulator-edge-status — is Docker running?
502 Bad GatewayBackend port down — docker ps / reconcile again
Wrong app on hostnamePort collision (e.g. two apps on 3000) — stop one stack
Name does not resolveRe-run ./scripts/setup-cloudforge-local-hosts.sh
macOS “port 80 in use”Something else bound :80 (AirPlay Receiver on some macOS versions) — disable or set CFC_EDGE_HTTP_PORT=8088

What this does not do

  • TLS / HTTPS (HTTP-only for local; mkcert optional later)
  • ALB OIDC / Cognito (still stripped / deferred on MiniStack)
  • Replace StackPort or CloudForge Manager
  • Fix host-port collisions between apps