Files
git.stella-ops.org/docs/technical/architecture/port-registry.md
2026-02-04 19:59:20 +02:00

175 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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**: 1000010911
- **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) |