# Deterministic Port Registry All Stella Ops web services are assigned deterministic HTTPS/HTTP port pairs to avoid collisions during local development and simplify service discovery configuration. ## Port Assignment Scheme - **Formula**: Service at slot N → HTTPS = `10000 + N×10`, HTTP = `10000 + N×10 + 1` - **Range**: 10000–10911 - **Local alias**: Each service additionally binds `https://{name}.stella-ops.local` (port 443) and `http://{name}.stella-ops.local` (port 80) — no port in URL ## Port Table | Slot | HTTPS | HTTP | Service | Hostname | Path | Env Var | |------|-------|------|---------|----------|------|---------| | 0 | 10000 | 10001 | Router Gateway | `router.stella-ops.local` | `src/Router/StellaOps.Gateway.WebService` | `STELLAOPS_ROUTER_URL` | | 1 | 10010 | 10011 | Platform | `platform.stella-ops.local` | `src/Platform/StellaOps.Platform.WebService` | `STELLAOPS_PLATFORM_URL` | | 2 | 10020 | 10021 | Authority | `authority.stella-ops.local` | `src/Authority/StellaOps.Authority/StellaOps.Authority` | `STELLAOPS_AUTHORITY_URL` | | 3 | 10030 | 10031 | Gateway | `gateway.stella-ops.local` | `src/Gateway/StellaOps.Gateway.WebService` | `STELLAOPS_GATEWAY_URL` | | 4 | 10040 | 10041 | Attestor | `attestor.stella-ops.local` | `src/Attestor/StellaOps.Attestor/StellaOps.Attestor.WebService` | `STELLAOPS_ATTESTOR_URL` | | 5 | 10050 | 10051 | Attestor TileProxy | — | `src/Attestor/StellaOps.Attestor.TileProxy` | `STELLAOPS_ATTESTOR_TILEPROXY_URL` | | 6 | 10060 | 10061 | Evidence Locker | `evidencelocker.stella-ops.local` | `src/EvidenceLocker/StellaOps.EvidenceLocker/StellaOps.EvidenceLocker.WebService` | `STELLAOPS_EVIDENCELOCKER_URL` | | 7 | 10070 | 10071 | Evidence Locker Aggregator | — | `src/EvidenceLocker/StellaOps.EvidenceLocker` | `STELLAOPS_EVIDENCELOCKER_AGGREGATOR_URL` | | 8 | 10080 | 10081 | Scanner | `scanner.stella-ops.local` | `src/Scanner/StellaOps.Scanner.WebService` | `STELLAOPS_SCANNER_URL` | | 9 | 10090 | 10091 | Concelier | `concelier.stella-ops.local` | `src/Concelier/StellaOps.Concelier.WebService` | `STELLAOPS_CONCELIER_URL` | | 10 | 10100 | 10101 | Excititor | `excititor.stella-ops.local` | `src/Excititor/StellaOps.Excititor.WebService` | `STELLAOPS_EXCITITOR_URL` | | 11 | 10110 | 10111 | VexHub | `vexhub.stella-ops.local` | `src/VexHub/StellaOps.VexHub.WebService` | `STELLAOPS_VEXHUB_URL` | | 12 | 10120 | 10121 | VexLens | `vexlens.stella-ops.local` | `src/VexLens/StellaOps.VexLens.WebService` | `STELLAOPS_VEXLENS_URL` | | 13 | 10130 | 10131 | VulnExplorer | `vulnexplorer.stella-ops.local` | `src/VulnExplorer/StellaOps.VulnExplorer.Api` | `STELLAOPS_VULNEXPLORER_URL` | | 14 | 10140 | 10141 | Policy Engine | `policy-engine.stella-ops.local` | `src/Policy/StellaOps.Policy.Engine` | `STELLAOPS_POLICY_ENGINE_URL` | | 15 | 10150 | 10151 | Policy Gateway | `policy-gateway.stella-ops.local` | `src/Policy/StellaOps.Policy.Gateway` | `STELLAOPS_POLICY_GATEWAY_URL` | | 16 | 10160 | 10161 | RiskEngine | `riskengine.stella-ops.local` | `src/RiskEngine/StellaOps.RiskEngine/StellaOps.RiskEngine.WebService` | `STELLAOPS_RISKENGINE_URL` | | 17 | 10170 | 10171 | Orchestrator | `orchestrator.stella-ops.local` | `src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.WebService` | `STELLAOPS_ORCHESTRATOR_URL` | | 18 | 10180 | 10181 | TaskRunner | `taskrunner.stella-ops.local` | `src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.WebService` | `STELLAOPS_TASKRUNNER_URL` | | 19 | 10190 | 10191 | Scheduler | `scheduler.stella-ops.local` | `src/Scheduler/StellaOps.Scheduler.WebService` | `STELLAOPS_SCHEDULER_URL` | | 20 | 10200 | 10201 | Graph API | `graph.stella-ops.local` | `src/Graph/StellaOps.Graph.Api` | `STELLAOPS_GRAPH_URL` | | 21 | 10210 | 10211 | Cartographer | `cartographer.stella-ops.local` | `src/Cartographer/StellaOps.Cartographer` | `STELLAOPS_CARTOGRAPHER_URL` | | 22 | 10220 | 10221 | ReachGraph | `reachgraph.stella-ops.local` | `src/ReachGraph/StellaOps.ReachGraph.WebService` | `STELLAOPS_REACHGRAPH_URL` | | 23 | 10230 | 10231 | Timeline Indexer | `timelineindexer.stella-ops.local` | `src/TimelineIndexer/StellaOps.TimelineIndexer/StellaOps.TimelineIndexer.WebService` | `STELLAOPS_TIMELINEINDEXER_URL` | | 24 | 10240 | 10241 | Timeline | `timeline.stella-ops.local` | `src/Timeline/StellaOps.Timeline.WebService` | `STELLAOPS_TIMELINE_URL` | | 25 | 10250 | 10251 | Findings Ledger | `findings.stella-ops.local` | `src/Findings/StellaOps.Findings.Ledger.WebService` | `STELLAOPS_FINDINGS_LEDGER_URL` | | 26 | 10260 | 10261 | Doctor | `doctor.stella-ops.local` | `src/Doctor/StellaOps.Doctor.WebService` | `STELLAOPS_DOCTOR_URL` | | 27 | 10270 | 10271 | OpsMemory | `opsmemory.stella-ops.local` | `src/OpsMemory/StellaOps.OpsMemory.WebService` | `STELLAOPS_OPSMEMORY_URL` | | 28 | 10280 | 10281 | Notifier | `notifier.stella-ops.local` | `src/Notifier/StellaOps.Notifier/StellaOps.Notifier.WebService` | `STELLAOPS_NOTIFIER_URL` | | 29 | 10290 | 10291 | Notify | `notify.stella-ops.local` | `src/Notify/StellaOps.Notify.WebService` | `STELLAOPS_NOTIFY_URL` | | 30 | 10300 | 10301 | Signer | `signer.stella-ops.local` | `src/Signer/StellaOps.Signer/StellaOps.Signer.WebService` | `STELLAOPS_SIGNER_URL` | | 31 | 10310 | 10311 | SmRemote | `smremote.stella-ops.local` | `src/SmRemote/StellaOps.SmRemote.Service` | `STELLAOPS_SMREMOTE_URL` | | 32 | 10320 | 10321 | AirGap Controller | `airgap-controller.stella-ops.local` | `src/AirGap/StellaOps.AirGap.Controller` | `STELLAOPS_AIRGAP_CONTROLLER_URL` | | 33 | 10330 | 10331 | AirGap Time | `airgap-time.stella-ops.local` | `src/AirGap/StellaOps.AirGap.Time` | `STELLAOPS_AIRGAP_TIME_URL` | | 34 | 10340 | 10341 | PacksRegistry | `packsregistry.stella-ops.local` | `src/PacksRegistry/StellaOps.PacksRegistry/StellaOps.PacksRegistry.WebService` | `STELLAOPS_PACKSREGISTRY_URL` | | 35 | 10350 | 10351 | Registry Token | `registry-token.stella-ops.local` | `src/Registry/StellaOps.Registry.TokenService` | `STELLAOPS_REGISTRY_TOKENSERVICE_URL` | | 36 | 10360 | 10361 | BinaryIndex | `binaryindex.stella-ops.local` | `src/BinaryIndex/StellaOps.BinaryIndex.WebService` | `STELLAOPS_BINARYINDEX_URL` | | 37 | 10370 | 10371 | IssuerDirectory | `issuerdirectory.stella-ops.local` | `src/IssuerDirectory/StellaOps.IssuerDirectory/StellaOps.IssuerDirectory.WebService` | `STELLAOPS_ISSUERDIRECTORY_URL` | | 38 | 10380 | 10381 | Symbols | `symbols.stella-ops.local` | `src/Symbols/StellaOps.Symbols.Server` | `STELLAOPS_SYMBOLS_URL` | | 39 | 10390 | 10391 | SbomService | `sbomservice.stella-ops.local` | `src/SbomService/StellaOps.SbomService` | `STELLAOPS_SBOMSERVICE_URL` | | 40 | 10400 | 10401 | ExportCenter | `exportcenter.stella-ops.local` | `src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.WebService` | `STELLAOPS_EXPORTCENTER_URL` | | 41 | 10410 | 10411 | Replay | `replay.stella-ops.local` | `src/Replay/StellaOps.Replay.WebService` | `STELLAOPS_REPLAY_URL` | | 42 | 10420 | 10421 | Integrations | `integrations.stella-ops.local` | `src/Integrations/StellaOps.Integrations.WebService` | `STELLAOPS_INTEGRATIONS_URL` | | 43 | 10430 | 10431 | Zastava | — | `src/Zastava/StellaOps.Zastava.Webhook` | `STELLAOPS_ZASTAVA_URL` | | 44 | 10440 | 10441 | Signals | `signals.stella-ops.local` | `src/Signals/StellaOps.Signals` | `STELLAOPS_SIGNALS_URL` | | 45 | 10450 | 10451 | AdvisoryAI | `advisoryai.stella-ops.local` | `src/AdvisoryAI/StellaOps.AdvisoryAI.WebService` | `STELLAOPS_ADVISORYAI_URL` | | 46 | 10460 | 10461 | Unknowns | `unknowns.stella-ops.local` | `src/Unknowns/StellaOps.Unknowns.WebService` | `STELLAOPS_UNKNOWNS_URL` | | 90 | 10900 | 10901 | Examples.Gateway | — | `src/Router/examples/Examples.Gateway` | — | | 91 | 10910 | 10911 | Examples.MultiTransport | — | `src/Router/examples/Examples.MultiTransport.Gateway` | — | ## Worker Services Worker services associated with a web service use ports offset by +2/+3 from the web service slot: | HTTPS | HTTP | Service | Path | |-------|------|---------|------| | 10062 | 10063 | EvidenceLocker Worker | `src/EvidenceLocker/StellaOps.EvidenceLocker/StellaOps.EvidenceLocker.Worker` | | 10162 | 10163 | RiskEngine Worker | `src/RiskEngine/StellaOps.RiskEngine/StellaOps.RiskEngine.Worker` | | 10172 | 10173 | Orchestrator Worker | `src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Worker` | | 10182 | 10183 | TaskRunner Worker | `src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Worker` | | 10232 | 10233 | TimelineIndexer Worker | `src/TimelineIndexer/StellaOps.TimelineIndexer/StellaOps.TimelineIndexer.Worker` | | 10282 | 10283 | Notifier Worker | `src/Notifier/StellaOps.Notifier/StellaOps.Notifier.Worker` | | 10342 | 10343 | PacksRegistry Worker | `src/PacksRegistry/StellaOps.PacksRegistry/StellaOps.PacksRegistry.Worker` | | 10402 | 10403 | ExportCenter Worker | `src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Worker` | ## Environment Variable Convention Each web service has a corresponding `STELLAOPS_{SERVICE}_URL` environment variable. The Platform service reads these at startup (Layer 1 of the 3-layer configuration) and maps them into `ApiBaseUrls` for the Angular frontend. Example: `STELLAOPS_SCANNER_URL=https://scanner.internal:10080` maps to `ApiBaseUrls["scanner"]`. See also: [3-Layer Service URL Configuration](../../modules/platform/architecture-overview.md) ## Friendly Hostnames (`.stella-ops.local`) Each service can be reached via `https://{name}.stella-ops.local` (port 443) and `http://{name}.stella-ops.local` (port 80) — no port in the URL. The HTTPS/HTTP dev ports (10000+) are bound to `localhost` only; the `.stella-ops.local` hostnames use standard ports. Each hostname resolves to a **unique loopback IP** (`127.1.0.x`) so every service can bind ports 443/80 simultaneously without collisions. The entire `127.0.0.0/8` range is loopback on all platforms, so `127.1.0.x` addresses work the same as `127.0.0.1`. The Angular UI (`ng serve`) binds to `https://stella-ops.local` (port 443 on `127.1.0.1`). At startup each service resolves its hostname to its dedicated loopback IP and binds ports 443/80 on that IP. It logs the result: - **Resolves, ports free**: `INFO Also accessible at https://{name}.stella-ops.local and http://{name}.stella-ops.local` - **Resolves, ports taken**: `INFO Hostname {name}.stella-ops.local resolves but ports 443/80 are unavailable; use the dev port instead.` - **Does not resolve**: `WARN Hostname {name}.stella-ops.local does not resolve. To enable friendly .stella-ops.local URLs, add hosts-file entries as described in docs/technical/architecture/port-registry.md.` ### Hosts file setup Each service gets a unique loopback IP in the `127.1.0.x` range so ports 443/80 never collide. Add the following to your hosts file (`C:\Windows\System32\drivers\etc\hosts` on Windows, `/etc/hosts` on Linux/macOS): ``` # Stella Ops local development hostnames # Each service gets a unique loopback IP so all can bind :443/:80 simultaneously. 127.1.0.1 stella-ops.local 127.1.0.2 router.stella-ops.local 127.1.0.3 platform.stella-ops.local 127.1.0.4 authority.stella-ops.local 127.1.0.5 gateway.stella-ops.local 127.1.0.6 attestor.stella-ops.local 127.1.0.7 evidencelocker.stella-ops.local 127.1.0.8 scanner.stella-ops.local 127.1.0.9 concelier.stella-ops.local 127.1.0.10 excititor.stella-ops.local 127.1.0.11 vexhub.stella-ops.local 127.1.0.12 vexlens.stella-ops.local 127.1.0.13 vulnexplorer.stella-ops.local 127.1.0.14 policy-engine.stella-ops.local 127.1.0.15 policy-gateway.stella-ops.local 127.1.0.16 riskengine.stella-ops.local 127.1.0.17 orchestrator.stella-ops.local 127.1.0.18 taskrunner.stella-ops.local 127.1.0.19 scheduler.stella-ops.local 127.1.0.20 graph.stella-ops.local 127.1.0.21 cartographer.stella-ops.local 127.1.0.22 reachgraph.stella-ops.local 127.1.0.23 timelineindexer.stella-ops.local 127.1.0.24 timeline.stella-ops.local 127.1.0.25 findings.stella-ops.local 127.1.0.26 doctor.stella-ops.local 127.1.0.27 opsmemory.stella-ops.local 127.1.0.28 notifier.stella-ops.local 127.1.0.29 notify.stella-ops.local 127.1.0.30 signer.stella-ops.local 127.1.0.31 smremote.stella-ops.local 127.1.0.32 airgap-controller.stella-ops.local 127.1.0.33 airgap-time.stella-ops.local 127.1.0.34 packsregistry.stella-ops.local 127.1.0.35 registry-token.stella-ops.local 127.1.0.36 binaryindex.stella-ops.local 127.1.0.37 issuerdirectory.stella-ops.local 127.1.0.38 symbols.stella-ops.local 127.1.0.39 sbomservice.stella-ops.local 127.1.0.40 exportcenter.stella-ops.local 127.1.0.41 replay.stella-ops.local 127.1.0.42 integrations.stella-ops.local 127.1.0.43 signals.stella-ops.local 127.1.0.44 advisoryai.stella-ops.local 127.1.0.45 unknowns.stella-ops.local # Stella Ops infrastructure (local dev containers) 127.1.1.1 db.stella-ops.local 127.1.1.2 cache.stella-ops.local 127.1.1.3 s3.stella-ops.local 127.1.1.4 rekor.stella-ops.local 127.1.1.5 registry.stella-ops.local ``` ### Infrastructure services Infrastructure containers (databases, caches, object storage, transparency logs) use a separate loopback range (`127.1.1.x`) to avoid collisions with application services. | IP | Hostname | Service | Port | |----|----------|---------|------| | `127.1.1.1` | `db.stella-ops.local` | PostgreSQL 18.1 | 5432 | | `127.1.1.2` | `cache.stella-ops.local` | Valkey 9.0.1 | 6379 | | `127.1.1.3` | `s3.stella-ops.local` | SeaweedFS (S3-compatible) | 8080 | | `127.1.1.4` | `rekor.stella-ops.local` | Rekor v2 (tiles) | 3322 | | `127.1.1.5` | `registry.stella-ops.local` | Zot (OCI registry) | 80 (→5000) |