part #2
This commit is contained in:
171
devops/compose/.env
Normal file
171
devops/compose/.env
Normal file
@@ -0,0 +1,171 @@
|
||||
# =============================================================================
|
||||
# STELLA OPS ENVIRONMENT CONFIGURATION
|
||||
# =============================================================================
|
||||
# Main environment template for docker-compose.stella-ops.yml
|
||||
# Copy to .env and customize for your deployment.
|
||||
#
|
||||
# Usage:
|
||||
# cp env/stellaops.env.example .env
|
||||
# docker compose -f docker-compose.stella-ops.yml up -d
|
||||
#
|
||||
# =============================================================================
|
||||
|
||||
# =============================================================================
|
||||
# INFRASTRUCTURE
|
||||
# =============================================================================
|
||||
|
||||
# PostgreSQL Database
|
||||
POSTGRES_USER=stellaops
|
||||
POSTGRES_PASSWORD=stellaops
|
||||
POSTGRES_DB=stellaops_platform
|
||||
POSTGRES_PORT=5432
|
||||
|
||||
# Valkey (Redis-compatible cache and messaging)
|
||||
VALKEY_PORT=6379
|
||||
|
||||
# RustFS Object Storage
|
||||
RUSTFS_HTTP_PORT=8080
|
||||
|
||||
# =============================================================================
|
||||
# CORE SERVICES
|
||||
# =============================================================================
|
||||
|
||||
# Authority (OAuth2/OIDC)
|
||||
AUTHORITY_ISSUER=https://authority.stella-ops.local
|
||||
AUTHORITY_PORT=8440
|
||||
AUTHORITY_OFFLINE_CACHE_TOLERANCE=00:30:00
|
||||
|
||||
# Signer
|
||||
SIGNER_POE_INTROSPECT_URL=http://authority.stella-ops.local/.well-known/openid-configuration
|
||||
SIGNER_PORT=8441
|
||||
|
||||
# Attestor
|
||||
ATTESTOR_PORT=8442
|
||||
|
||||
# Issuer Directory
|
||||
ISSUER_DIRECTORY_PORT=8447
|
||||
ISSUER_DIRECTORY_SEED_CSAF=true
|
||||
|
||||
# Concelier
|
||||
CONCELIER_PORT=8445
|
||||
|
||||
# Notify
|
||||
NOTIFY_WEB_PORT=8446
|
||||
|
||||
# Web UI
|
||||
UI_PORT=8443
|
||||
|
||||
# =============================================================================
|
||||
# SCANNER CONFIGURATION
|
||||
# =============================================================================
|
||||
|
||||
SCANNER_WEB_PORT=8444
|
||||
|
||||
# Queue configuration (Valkey only - NATS removed)
|
||||
SCANNER__QUEUE__BROKER=valkey://cache.stella-ops.local:6379
|
||||
|
||||
# Event streaming
|
||||
SCANNER_EVENTS_ENABLED=false
|
||||
SCANNER_EVENTS_DRIVER=valkey
|
||||
SCANNER_EVENTS_DSN=cache.stella-ops.local:6379
|
||||
SCANNER_EVENTS_STREAM=stella.events
|
||||
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
||||
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
||||
|
||||
# Surface cache configuration
|
||||
SCANNER_SURFACE_FS_ENDPOINT=http://s3.stella-ops.local
|
||||
SCANNER_SURFACE_FS_BUCKET=surface-cache
|
||||
SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface
|
||||
SCANNER_SURFACE_CACHE_QUOTA_MB=4096
|
||||
SCANNER_SURFACE_PREFETCH_ENABLED=false
|
||||
SCANNER_SURFACE_TENANT=default
|
||||
SCANNER_SURFACE_FEATURES=
|
||||
SCANNER_SURFACE_SECRETS_PROVIDER=file
|
||||
SCANNER_SURFACE_SECRETS_NAMESPACE=
|
||||
SCANNER_SURFACE_SECRETS_ROOT=/etc/stellaops/secrets
|
||||
SCANNER_SURFACE_SECRETS_FALLBACK_PROVIDER=
|
||||
SCANNER_SURFACE_SECRETS_ALLOW_INLINE=false
|
||||
SURFACE_SECRETS_HOST_PATH=./offline/surface-secrets
|
||||
|
||||
# Offline Kit configuration
|
||||
SCANNER_OFFLINEKIT_ENABLED=false
|
||||
SCANNER_OFFLINEKIT_REQUIREDSSE=true
|
||||
SCANNER_OFFLINEKIT_REKOROFFLINEMODE=true
|
||||
SCANNER_OFFLINEKIT_TRUSTROOTDIRECTORY=/etc/stellaops/trust-roots
|
||||
SCANNER_OFFLINEKIT_REKORSNAPSHOTDIRECTORY=/var/lib/stellaops/rekor-snapshot
|
||||
SCANNER_OFFLINEKIT_TRUSTROOTS_HOST_PATH=./offline/trust-roots
|
||||
SCANNER_OFFLINEKIT_REKOR_SNAPSHOT_HOST_PATH=./offline/rekor-snapshot
|
||||
|
||||
# =============================================================================
|
||||
# SCHEDULER CONFIGURATION
|
||||
# =============================================================================
|
||||
|
||||
# Queue configuration (Valkey only - NATS removed)
|
||||
SCHEDULER__QUEUE__KIND=Valkey
|
||||
SCHEDULER__QUEUE__VALKEY__URL=cache.stella-ops.local:6379
|
||||
SCHEDULER_SCANNER_BASEADDRESS=http://scanner.stella-ops.local
|
||||
|
||||
# =============================================================================
|
||||
# REKOR / SIGSTORE CONFIGURATION
|
||||
# =============================================================================
|
||||
|
||||
# Rekor server URL (default: public Sigstore, use http://rekor-v2:3000 for local)
|
||||
REKOR_SERVER_URL=https://rekor.sigstore.dev
|
||||
REKOR_VERSION=V2
|
||||
REKOR_TILE_BASE_URL=
|
||||
REKOR_LOG_ID=c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d
|
||||
REKOR_TILES_IMAGE=ghcr.io/sigstore/rekor-tiles:latest
|
||||
|
||||
# =============================================================================
|
||||
# ADVISORY AI CONFIGURATION
|
||||
# =============================================================================
|
||||
|
||||
ADVISORY_AI_WEB_PORT=8448
|
||||
ADVISORY_AI_SBOM_BASEADDRESS=http://scanner.stella-ops.local
|
||||
ADVISORY_AI_INFERENCE_MODE=Local
|
||||
ADVISORY_AI_REMOTE_BASEADDRESS=
|
||||
ADVISORY_AI_REMOTE_APIKEY=
|
||||
|
||||
# =============================================================================
|
||||
# CRYPTO CONFIGURATION
|
||||
# =============================================================================
|
||||
|
||||
# Crypto profile: default, china, russia, eu
|
||||
STELLAOPS_CRYPTO_PROFILE=default
|
||||
|
||||
# Enable crypto simulation (for testing)
|
||||
STELLAOPS_CRYPTO_ENABLE_SIM=0
|
||||
STELLAOPS_CRYPTO_SIM_URL=http://sim-crypto:8080
|
||||
|
||||
# CryptoPro (Russia only) - requires EULA acceptance
|
||||
CRYPTOPRO_PORT=18080
|
||||
CRYPTOPRO_ACCEPT_EULA=0
|
||||
CRYPTOPRO_CONTAINER_NAME=stellaops-signing
|
||||
CRYPTOPRO_USE_MACHINE_STORE=true
|
||||
CRYPTOPRO_PROVIDER_TYPE=80
|
||||
|
||||
# SM Remote (China only)
|
||||
SM_REMOTE_PORT=56080
|
||||
SM_SOFT_ALLOWED=1
|
||||
SM_REMOTE_HSM_URL=
|
||||
SM_REMOTE_HSM_API_KEY=
|
||||
SM_REMOTE_HSM_TIMEOUT=30000
|
||||
|
||||
# =============================================================================
|
||||
# NETWORKING
|
||||
# =============================================================================
|
||||
|
||||
# External reverse proxy network (Traefik, Envoy, etc.)
|
||||
FRONTDOOR_NETWORK=stellaops_frontdoor
|
||||
|
||||
# =============================================================================
|
||||
# TELEMETRY (optional)
|
||||
# =============================================================================
|
||||
|
||||
OTEL_GRPC_PORT=4317
|
||||
OTEL_HTTP_PORT=4318
|
||||
OTEL_PROMETHEUS_PORT=9464
|
||||
PROMETHEUS_PORT=9090
|
||||
TEMPO_PORT=3200
|
||||
LOKI_PORT=3100
|
||||
PROMETHEUS_RETENTION=15d
|
||||
@@ -10,9 +10,11 @@
|
||||
# docker compose -f docker-compose.dev.yml up -d
|
||||
#
|
||||
# This provides:
|
||||
# - PostgreSQL 18.1 on port 5432
|
||||
# - Valkey 9.0.1 on port 6379
|
||||
# - RustFS on port 8080
|
||||
# - PostgreSQL 18.1 on 127.1.1.1:5432 (db.stella-ops.local)
|
||||
# - Valkey 9.0.1 on 127.1.1.2:6379 (cache.stella-ops.local)
|
||||
# - SeaweedFS (S3) on 127.1.1.3:8080 (s3.stella-ops.local)
|
||||
# - Rekor v2 (tiles) on 127.1.1.4:3322 (rekor.stella-ops.local)
|
||||
# - Zot (OCI registry) on 127.1.1.5:80 (registry.stella-ops.local)
|
||||
# =============================================================================
|
||||
|
||||
services:
|
||||
@@ -27,7 +29,7 @@ services:
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5432}:5432"
|
||||
- "127.1.1.1:${POSTGRES_PORT:-5432}:5432"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-stellaops}"]
|
||||
interval: 10s
|
||||
@@ -42,7 +44,7 @@ services:
|
||||
volumes:
|
||||
- valkey-data:/data
|
||||
ports:
|
||||
- "${VALKEY_PORT:-6379}:6379"
|
||||
- "127.1.1.2:${VALKEY_PORT:-6379}:6379"
|
||||
healthcheck:
|
||||
test: ["CMD", "valkey-cli", "ping"]
|
||||
interval: 10s
|
||||
@@ -50,24 +52,52 @@ services:
|
||||
retries: 5
|
||||
|
||||
rustfs:
|
||||
image: registry.stella-ops.org/stellaops/rustfs:2025.09.2
|
||||
image: chrislusf/seaweedfs:latest
|
||||
container_name: stellaops-dev-rustfs
|
||||
restart: unless-stopped
|
||||
command: ["serve", "--listen", "0.0.0.0:8080", "--root", "/data"]
|
||||
environment:
|
||||
RUSTFS__LOG__LEVEL: info
|
||||
RUSTFS__STORAGE__PATH: /data
|
||||
command: ["server", "-s3", "-s3.port=8080", "-dir=/data"]
|
||||
volumes:
|
||||
- rustfs-data:/data
|
||||
ports:
|
||||
- "${RUSTFS_PORT:-8080}:8080"
|
||||
- "127.1.1.3:${RUSTFS_PORT:-8080}:8080"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
test: ["CMD", "wget", "-qO-", "http://localhost:8080/status"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
rekor-v2:
|
||||
image: ${REKOR_TILES_IMAGE:-ghcr.io/sigstore/rekor-tiles:latest}
|
||||
container_name: stellaops-dev-rekor
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- rekor-tiles-data:/var/lib/rekor-tiles
|
||||
ports:
|
||||
- "127.1.1.4:${REKOR_PORT:-3322}:3322"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3322/healthz"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
registry:
|
||||
image: ghcr.io/project-zot/zot-linux-amd64:v2.1.3
|
||||
container_name: stellaops-dev-registry
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- registry-data:/var/lib/registry
|
||||
- ./zot-config.json:/etc/zot/config.json:ro
|
||||
ports:
|
||||
- "127.1.1.5:80:5000"
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://localhost:5000/v2/"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
valkey-data:
|
||||
rustfs-data:
|
||||
rekor-tiles-data:
|
||||
registry-data:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
14
devops/compose/postgres-init/01-create-schemas.sql
Normal file
14
devops/compose/postgres-init/01-create-schemas.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
-- Pre-create schemas referenced by Stella Ops services.
|
||||
-- Runs once on first PostgreSQL container start via docker-entrypoint-initdb.d.
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS scanner;
|
||||
CREATE SCHEMA IF NOT EXISTS vex;
|
||||
CREATE SCHEMA IF NOT EXISTS scheduler;
|
||||
CREATE SCHEMA IF NOT EXISTS policy;
|
||||
CREATE SCHEMA IF NOT EXISTS notify;
|
||||
CREATE SCHEMA IF NOT EXISTS notifier;
|
||||
CREATE SCHEMA IF NOT EXISTS evidence;
|
||||
CREATE SCHEMA IF NOT EXISTS findings;
|
||||
CREATE SCHEMA IF NOT EXISTS timeline;
|
||||
CREATE SCHEMA IF NOT EXISTS doctor;
|
||||
CREATE SCHEMA IF NOT EXISTS issuer_directory;
|
||||
16
devops/compose/zot-config.json
Normal file
16
devops/compose/zot-config.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"distSpecVersion": "1.1.0",
|
||||
"storage": {
|
||||
"rootDirectory": "/var/lib/registry",
|
||||
"gc": true,
|
||||
"gcDelay": "1h",
|
||||
"gcInterval": "24h"
|
||||
},
|
||||
"http": {
|
||||
"address": "0.0.0.0",
|
||||
"port": "5000"
|
||||
},
|
||||
"log": {
|
||||
"level": "info"
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,29 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
# Multi-stage Angular console image with non-root runtime (DOCKER-44-001)
|
||||
ARG NODE_IMAGE=node:20-bullseye-slim
|
||||
ARG NODE_IMAGE=node:20-bookworm-slim
|
||||
ARG NGINX_IMAGE=nginxinc/nginx-unprivileged:1.27-alpine
|
||||
ARG APP_DIR=src/Web/StellaOps.Web
|
||||
ARG DIST_DIR=dist
|
||||
ARG APP_PORT=8080
|
||||
|
||||
FROM ${NODE_IMAGE} AS build
|
||||
ARG APP_DIR
|
||||
ARG DIST_DIR
|
||||
ENV npm_config_fund=false npm_config_audit=false SOURCE_DATE_EPOCH=1704067200
|
||||
WORKDIR /app
|
||||
COPY ${APP_DIR}/package*.json ./
|
||||
RUN npm ci --prefer-offline --no-progress --cache .npm
|
||||
RUN npm install --no-progress
|
||||
COPY ${APP_DIR}/ ./
|
||||
RUN npm run build -- --configuration=production --output-path=${DIST_DIR}
|
||||
|
||||
FROM ${NGINX_IMAGE} AS runtime
|
||||
ARG APP_PORT
|
||||
ARG APP_PORT=8080
|
||||
ARG DIST_DIR=dist
|
||||
ENV APP_PORT=${APP_PORT}
|
||||
USER 101
|
||||
WORKDIR /
|
||||
COPY --from=build /app/${DIST_DIR}/ /usr/share/nginx/html/
|
||||
COPY ops/devops/docker/healthcheck-frontend.sh /usr/local/bin/healthcheck-frontend.sh
|
||||
COPY devops/docker/healthcheck-frontend.sh /usr/local/bin/healthcheck-frontend.sh
|
||||
RUN rm -f /etc/nginx/conf.d/default.conf && \
|
||||
cat > /etc/nginx/conf.d/default.conf <<CONF
|
||||
server {
|
||||
@@ -29,7 +32,7 @@ server {
|
||||
server_name _;
|
||||
root /usr/share/nginx/html;
|
||||
location / {
|
||||
try_files $$uri $$uri/ /index.html;
|
||||
try_files \$uri \$uri/ /index.html;
|
||||
}
|
||||
}
|
||||
CONF
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
# Hardened multi-stage template for StellaOps services
|
||||
# Parameters are build-time ARGs so this file can be re-used across services.
|
||||
|
||||
ARG SDK_IMAGE=mcr.microsoft.com/dotnet/sdk:10.0-bookworm-slim
|
||||
ARG RUNTIME_IMAGE=mcr.microsoft.com/dotnet/aspnet:10.0-bookworm-slim
|
||||
ARG SDK_IMAGE=mcr.microsoft.com/dotnet/sdk:10.0-noble
|
||||
ARG RUNTIME_IMAGE=mcr.microsoft.com/dotnet/aspnet:10.0-noble
|
||||
ARG APP_PROJECT=src/Service/Service.csproj
|
||||
ARG CONFIGURATION=Release
|
||||
ARG PUBLISH_DIR=/app/publish
|
||||
@@ -14,17 +14,26 @@ ARG APP_GID=10001
|
||||
ARG APP_PORT=8080
|
||||
|
||||
FROM ${SDK_IMAGE} AS build
|
||||
ARG APP_PROJECT
|
||||
ARG CONFIGURATION
|
||||
ARG PUBLISH_DIR
|
||||
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 \
|
||||
DOTNET_NOLOGO=1 \
|
||||
SOURCE_DATE_EPOCH=1704067200
|
||||
WORKDIR /src
|
||||
# Expect restore sources to be available offline via /.nuget/
|
||||
COPY . .
|
||||
RUN dotnet restore ${APP_PROJECT} --packages /.nuget/packages && \
|
||||
RUN dotnet restore ${APP_PROJECT} && \
|
||||
dotnet publish ${APP_PROJECT} -c ${CONFIGURATION} -o ${PUBLISH_DIR} \
|
||||
/p:UseAppHost=true /p:PublishTrimmed=false
|
||||
|
||||
FROM ${RUNTIME_IMAGE} AS runtime
|
||||
ARG APP_USER=stella
|
||||
ARG APP_UID=10001
|
||||
ARG APP_GID=10001
|
||||
ARG APP_PORT=8080
|
||||
ARG APP_BINARY=StellaOps.Service
|
||||
ARG PUBLISH_DIR=/app/publish
|
||||
# Create non-root user/group with stable ids for auditability
|
||||
RUN groupadd -r -g ${APP_GID} ${APP_USER} && \
|
||||
useradd -r -u ${APP_UID} -g ${APP_GID} -d /var/lib/${APP_USER} ${APP_USER} && \
|
||||
@@ -34,23 +43,27 @@ RUN groupadd -r -g ${APP_GID} ${APP_USER} && \
|
||||
WORKDIR /app
|
||||
COPY --from=build --chown=${APP_UID}:${APP_GID} ${PUBLISH_DIR}/ ./
|
||||
# Ship healthcheck helper; callers may override with their own script
|
||||
COPY --chown=${APP_UID}:${APP_GID} ops/devops/docker/healthcheck.sh /usr/local/bin/healthcheck.sh
|
||||
COPY --chown=${APP_UID}:${APP_GID} devops/docker/healthcheck.sh /usr/local/bin/healthcheck.sh
|
||||
|
||||
ENV ASPNETCORE_URLS=http://+:${APP_PORT} \
|
||||
DOTNET_EnableDiagnostics=0 \
|
||||
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 \
|
||||
COMPlus_EnableDiagnostics=0 \
|
||||
APP_BINARY=${APP_BINARY}
|
||||
|
||||
# Harden filesystem; deploys should also set readOnlyRootFilesystem true
|
||||
# Keep the native AppHost binary (+x) and DLLs read-only (400)
|
||||
RUN chmod 500 /app && \
|
||||
chmod +x /usr/local/bin/healthcheck.sh && \
|
||||
find /app -maxdepth 1 -type f -name '*.dll' -exec chmod 400 {} \; && \
|
||||
find /app -maxdepth 1 -type f -name '*.json' -exec chmod 400 {} \; && \
|
||||
find /app -maxdepth 1 -type f -name '*.pdb' -exec chmod 400 {} \; && \
|
||||
find /app -maxdepth 1 -type d -exec chmod 500 {} \; && \
|
||||
chmod 500 /app/${APP_BINARY} 2>/dev/null || true
|
||||
|
||||
USER ${APP_UID}:${APP_GID}
|
||||
EXPOSE ${APP_PORT}
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
||||
CMD /usr/local/bin/healthcheck.sh
|
||||
|
||||
# Harden filesystem; deploys should also set readOnlyRootFilesystem true
|
||||
RUN chmod 500 /app && \
|
||||
find /app -maxdepth 1 -type f -exec chmod 400 {} \; && \
|
||||
find /app -maxdepth 1 -type d -exec chmod 500 {} \;
|
||||
|
||||
# Use shell form so APP_BINARY env can be expanded without duplicating the template per service
|
||||
ENTRYPOINT ["sh","-c","exec ./\"$APP_BINARY\""]
|
||||
|
||||
106
devops/docker/build-all.ps1
Normal file
106
devops/docker/build-all.ps1
Normal file
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env pwsh
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Build hardened Docker images for all Stella Ops services using the shared template/matrix.
|
||||
.DESCRIPTION
|
||||
PowerShell port of build-all.sh. Reads services-matrix.env (pipe-delimited) and builds
|
||||
each service image using Dockerfile.hardened.template (or Dockerfile.console for Angular).
|
||||
.PARAMETER Registry
|
||||
Docker image registry prefix. Default: stellaops
|
||||
.PARAMETER TagSuffix
|
||||
Tag suffix for built images. Default: dev
|
||||
.PARAMETER SdkImage
|
||||
.NET SDK base image. Default: mcr.microsoft.com/dotnet/sdk:10.0-noble
|
||||
.PARAMETER RuntimeImage
|
||||
.NET runtime base image. Default: mcr.microsoft.com/dotnet/aspnet:10.0-noble
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$Registry = $env:REGISTRY ?? 'stellaops',
|
||||
[string]$TagSuffix = $env:TAG_SUFFIX ?? 'dev',
|
||||
[string]$SdkImage = $env:SDK_IMAGE ?? 'mcr.microsoft.com/dotnet/sdk:10.0-noble',
|
||||
[string]$RuntimeImage = $env:RUNTIME_IMAGE ?? 'mcr.microsoft.com/dotnet/aspnet:10.0-noble'
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Continue'
|
||||
|
||||
$Root = git rev-parse --show-toplevel 2>$null
|
||||
if (-not $Root) {
|
||||
Write-Error 'Not inside a git repository.'
|
||||
exit 1
|
||||
}
|
||||
$Root = $Root.Trim()
|
||||
|
||||
$MatrixPath = Join-Path $Root 'devops/docker/services-matrix.env'
|
||||
if (-not (Test-Path $MatrixPath)) {
|
||||
Write-Error "Matrix file not found: $MatrixPath"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Building services from $MatrixPath -> ${Registry}/<service>:${TagSuffix}" -ForegroundColor Cyan
|
||||
|
||||
$succeeded = @()
|
||||
$failed = @()
|
||||
|
||||
foreach ($line in Get-Content $MatrixPath) {
|
||||
$line = $line.Trim()
|
||||
if (-not $line -or $line.StartsWith('#')) { continue }
|
||||
|
||||
$parts = $line -split '\|'
|
||||
if ($parts.Count -lt 5) { continue }
|
||||
|
||||
$service = $parts[0]
|
||||
$dockerfile = $parts[1]
|
||||
$project = $parts[2]
|
||||
$binary = $parts[3]
|
||||
$port = $parts[4]
|
||||
|
||||
$image = "${Registry}/${service}:${TagSuffix}"
|
||||
$dfPath = Join-Path $Root $dockerfile
|
||||
|
||||
if (-not (Test-Path $dfPath)) {
|
||||
Write-Warning "Skipping ${service}: dockerfile missing ($dfPath)"
|
||||
continue
|
||||
}
|
||||
|
||||
if ($dockerfile -like '*Dockerfile.console*') {
|
||||
Write-Host "[console] $service -> $image" -ForegroundColor Yellow
|
||||
docker build `
|
||||
-f $dfPath $Root `
|
||||
--build-arg "APP_DIR=$project" `
|
||||
--build-arg "APP_PORT=$port" `
|
||||
-t $image
|
||||
}
|
||||
else {
|
||||
Write-Host "[service] $service -> $image" -ForegroundColor Green
|
||||
docker build `
|
||||
-f $dfPath $Root `
|
||||
--build-arg "SDK_IMAGE=$SdkImage" `
|
||||
--build-arg "RUNTIME_IMAGE=$RuntimeImage" `
|
||||
--build-arg "APP_PROJECT=$project" `
|
||||
--build-arg "APP_BINARY=$binary" `
|
||||
--build-arg "APP_PORT=$port" `
|
||||
-t $image
|
||||
}
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
$succeeded += $service
|
||||
}
|
||||
else {
|
||||
$failed += $service
|
||||
Write-Host "FAILED: $service" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host '=== BUILD RESULTS ===' -ForegroundColor Cyan
|
||||
Write-Host "Succeeded ($($succeeded.Count)): $($succeeded -join ', ')" -ForegroundColor Green
|
||||
Write-Host "Failed ($($failed.Count)): $($failed -join ', ')" -ForegroundColor $(if ($failed.Count -gt 0) { 'Red' } else { 'Green' })
|
||||
Write-Host ''
|
||||
|
||||
if ($failed.Count -gt 0) {
|
||||
Write-Error 'Some builds failed. Fix the issues and re-run.'
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host 'Build complete. Remember to enforce readOnlyRootFilesystem at deploy time and run sbom_attest.sh (DOCKER-44-002).' -ForegroundColor Cyan
|
||||
@@ -1,13 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build hardened images for the core services using the shared template/matrix (DOCKER-44-001)
|
||||
set -euo pipefail
|
||||
set -uo pipefail
|
||||
FAILED=()
|
||||
SUCCEEDED=()
|
||||
|
||||
ROOT=${ROOT:-"$(git rev-parse --show-toplevel)"}
|
||||
MATRIX=${MATRIX:-"${ROOT}/ops/devops/docker/services-matrix.env"}
|
||||
MATRIX=${MATRIX:-"${ROOT}/devops/docker/services-matrix.env"}
|
||||
REGISTRY=${REGISTRY:-"stellaops"}
|
||||
TAG_SUFFIX=${TAG_SUFFIX:-"dev"}
|
||||
SDK_IMAGE=${SDK_IMAGE:-"mcr.microsoft.com/dotnet/sdk:10.0-bookworm-slim"}
|
||||
RUNTIME_IMAGE=${RUNTIME_IMAGE:-"mcr.microsoft.com/dotnet/aspnet:10.0-bookworm-slim"}
|
||||
SDK_IMAGE=${SDK_IMAGE:-"mcr.microsoft.com/dotnet/sdk:10.0-noble"}
|
||||
RUNTIME_IMAGE=${RUNTIME_IMAGE:-"mcr.microsoft.com/dotnet/aspnet:10.0-noble"}
|
||||
|
||||
if [[ ! -f "${MATRIX}" ]]; then
|
||||
echo "matrix file not found: ${MATRIX}" >&2
|
||||
@@ -45,6 +47,22 @@ while IFS='|' read -r service dockerfile project binary port; do
|
||||
-t "${image}"
|
||||
fi
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
SUCCEEDED+=("${service}")
|
||||
else
|
||||
FAILED+=("${service}")
|
||||
echo "FAILED: ${service}" >&2
|
||||
fi
|
||||
|
||||
done < "${MATRIX}"
|
||||
|
||||
echo "" >&2
|
||||
echo "=== BUILD RESULTS ===" >&2
|
||||
echo "Succeeded (${#SUCCEEDED[@]}): ${SUCCEEDED[*]:-none}" >&2
|
||||
echo "Failed (${#FAILED[@]}): ${FAILED[*]:-none}" >&2
|
||||
echo "" >&2
|
||||
if [[ ${#FAILED[@]} -gt 0 ]]; then
|
||||
echo "Some builds failed. Fix the issues and re-run." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Build complete. Remember to enforce readOnlyRootFilesystem at deploy time and run sbom_attest.sh (DOCKER-44-002)." >&2
|
||||
|
||||
@@ -1,12 +1,112 @@
|
||||
# service|dockerfile|project|binary|port
|
||||
# Paths are relative to repo root; dockerfile is usually the shared hardened template.
|
||||
api|ops/devops/docker/Dockerfile.hardened.template|src/VulnExplorer/StellaOps.VulnExplorer.Api/StellaOps.VulnExplorer.Api.csproj|StellaOps.VulnExplorer.Api|8080
|
||||
orchestrator|ops/devops/docker/Dockerfile.hardened.template|src/Orchestrator/StellaOps.Orchestrator.WebService/StellaOps.Orchestrator.WebService.csproj|StellaOps.Orchestrator.WebService|8080
|
||||
task-runner|ops/devops/docker/Dockerfile.hardened.template|src/Orchestrator/StellaOps.Orchestrator.Worker/StellaOps.Orchestrator.Worker.csproj|StellaOps.Orchestrator.Worker|8081
|
||||
concelier|ops/devops/docker/Dockerfile.hardened.template|src/Concelier/StellaOps.Concelier.WebService/StellaOps.Concelier.WebService.csproj|StellaOps.Concelier.WebService|8080
|
||||
excititor|ops/devops/docker/Dockerfile.hardened.template|src/Excititor/StellaOps.Excititor.WebService/StellaOps.Excititor.WebService.csproj|StellaOps.Excititor.WebService|8080
|
||||
policy|ops/devops/docker/Dockerfile.hardened.template|src/Policy/StellaOps.Policy.Gateway/StellaOps.Policy.Gateway.csproj|StellaOps.Policy.Gateway|8084
|
||||
notify|ops/devops/docker/Dockerfile.hardened.template|src/Notify/StellaOps.Notify.WebService/StellaOps.Notify.WebService.csproj|StellaOps.Notify.WebService|8080
|
||||
export|ops/devops/docker/Dockerfile.hardened.template|src/ExportCenter/StellaOps.ExportCenter.WebService/StellaOps.ExportCenter.WebService.csproj|StellaOps.ExportCenter.WebService|8080
|
||||
advisoryai|ops/devops/docker/Dockerfile.hardened.template|src/AdvisoryAI/StellaOps.AdvisoryAI.WebService/StellaOps.AdvisoryAI.WebService.csproj|StellaOps.AdvisoryAI.WebService|8080
|
||||
console|ops/devops/docker/Dockerfile.console|src/Web/StellaOps.Web|StellaOps.Web|8080
|
||||
# Ordered by port-registry slot number. All services use port 8080 internally
|
||||
# unless they have a legacy port assignment (authority=8440, signer=8441, etc.).
|
||||
#
|
||||
# ── Slot 0: Router Gateway ──────────────────────────────────────────────────────
|
||||
router-gateway|devops/docker/Dockerfile.hardened.template|src/Router/StellaOps.Gateway.WebService/StellaOps.Gateway.WebService.csproj|StellaOps.Gateway.WebService|8080
|
||||
# ── Slot 1: Platform ────────────────────────────────────────────────────────────
|
||||
platform|devops/docker/Dockerfile.hardened.template|src/Platform/StellaOps.Platform.WebService/StellaOps.Platform.WebService.csproj|StellaOps.Platform.WebService|8080
|
||||
# ── Slot 2: Authority ───────────────────────────────────────────────────────────
|
||||
authority|devops/docker/Dockerfile.hardened.template|src/Authority/StellaOps.Authority/StellaOps.Authority/StellaOps.Authority.csproj|StellaOps.Authority|8440
|
||||
# ── Slot 3: Gateway ─────────────────────────────────────────────────────────────
|
||||
gateway|devops/docker/Dockerfile.hardened.template|src/Gateway/StellaOps.Gateway.WebService/StellaOps.Gateway.WebService.csproj|StellaOps.Gateway.WebService|8080
|
||||
# ── Slot 4: Attestor ────────────────────────────────────────────────────────────
|
||||
attestor|devops/docker/Dockerfile.hardened.template|src/Attestor/StellaOps.Attestor/StellaOps.Attestor.WebService/StellaOps.Attestor.WebService.csproj|StellaOps.Attestor.WebService|8442
|
||||
# ── Slot 5: Attestor TileProxy ──────────────────────────────────────────────────
|
||||
attestor-tileproxy|devops/docker/Dockerfile.hardened.template|src/Attestor/StellaOps.Attestor.TileProxy/StellaOps.Attestor.TileProxy.csproj|StellaOps.Attestor.TileProxy|8080
|
||||
# ── Slot 6: Evidence Locker ─────────────────────────────────────────────────────
|
||||
evidence-locker-web|devops/docker/Dockerfile.hardened.template|src/EvidenceLocker/StellaOps.EvidenceLocker/StellaOps.EvidenceLocker.WebService/StellaOps.EvidenceLocker.WebService.csproj|StellaOps.EvidenceLocker.WebService|8080
|
||||
evidence-locker-worker|devops/docker/Dockerfile.hardened.template|src/EvidenceLocker/StellaOps.EvidenceLocker/StellaOps.EvidenceLocker.Worker/StellaOps.EvidenceLocker.Worker.csproj|StellaOps.EvidenceLocker.Worker|8080
|
||||
# ── Slot 8: Scanner ─────────────────────────────────────────────────────────────
|
||||
scanner-web|devops/docker/Dockerfile.hardened.template|src/Scanner/StellaOps.Scanner.WebService/StellaOps.Scanner.WebService.csproj|StellaOps.Scanner.WebService|8444
|
||||
scanner-worker|devops/docker/Dockerfile.hardened.template|src/Scanner/StellaOps.Scanner.Worker/StellaOps.Scanner.Worker.csproj|StellaOps.Scanner.Worker|8080
|
||||
# ── Slot 9: Concelier ───────────────────────────────────────────────────────────
|
||||
concelier|devops/docker/Dockerfile.hardened.template|src/Concelier/StellaOps.Concelier.WebService/StellaOps.Concelier.WebService.csproj|StellaOps.Concelier.WebService|8080
|
||||
# ── Slot 10: Excititor ──────────────────────────────────────────────────────────
|
||||
excititor|devops/docker/Dockerfile.hardened.template|src/Excititor/StellaOps.Excititor.WebService/StellaOps.Excititor.WebService.csproj|StellaOps.Excititor.WebService|8080
|
||||
excititor-worker|devops/docker/Dockerfile.hardened.template|src/Excititor/StellaOps.Excititor.Worker/StellaOps.Excititor.Worker.csproj|StellaOps.Excititor.Worker|8080
|
||||
# ── Slot 11: VexHub ─────────────────────────────────────────────────────────────
|
||||
vexhub-web|devops/docker/Dockerfile.hardened.template|src/VexHub/StellaOps.VexHub.WebService/StellaOps.VexHub.WebService.csproj|StellaOps.VexHub.WebService|8080
|
||||
# ── Slot 12: VexLens ────────────────────────────────────────────────────────────
|
||||
vexlens-web|devops/docker/Dockerfile.hardened.template|src/VexLens/StellaOps.VexLens.WebService/StellaOps.VexLens.WebService.csproj|StellaOps.VexLens.WebService|8080
|
||||
# ── Slot 13: VulnExplorer (api) ─────────────────────────────────────────────────
|
||||
api|devops/docker/Dockerfile.hardened.template|src/VulnExplorer/StellaOps.VulnExplorer.Api/StellaOps.VulnExplorer.Api.csproj|StellaOps.VulnExplorer.Api|8080
|
||||
# ── Slot 14: Policy Engine ──────────────────────────────────────────────────────
|
||||
policy-engine|devops/docker/Dockerfile.hardened.template|src/Policy/StellaOps.Policy.Engine/StellaOps.Policy.Engine.csproj|StellaOps.Policy.Engine|8080
|
||||
# ── Slot 15: Policy Gateway ─────────────────────────────────────────────────────
|
||||
policy|devops/docker/Dockerfile.hardened.template|src/Policy/StellaOps.Policy.Gateway/StellaOps.Policy.Gateway.csproj|StellaOps.Policy.Gateway|8084
|
||||
# ── Slot 16: RiskEngine ─────────────────────────────────────────────────────────
|
||||
riskengine-web|devops/docker/Dockerfile.hardened.template|src/RiskEngine/StellaOps.RiskEngine/StellaOps.RiskEngine.WebService/StellaOps.RiskEngine.WebService.csproj|StellaOps.RiskEngine.WebService|8080
|
||||
riskengine-worker|devops/docker/Dockerfile.hardened.template|src/RiskEngine/StellaOps.RiskEngine/StellaOps.RiskEngine.Worker/StellaOps.RiskEngine.Worker.csproj|StellaOps.RiskEngine.Worker|8080
|
||||
# ── Slot 17: Orchestrator ───────────────────────────────────────────────────────
|
||||
orchestrator|devops/docker/Dockerfile.hardened.template|src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.WebService/StellaOps.Orchestrator.WebService.csproj|StellaOps.Orchestrator.WebService|8080
|
||||
orchestrator-worker|devops/docker/Dockerfile.hardened.template|src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Worker/StellaOps.Orchestrator.Worker.csproj|StellaOps.Orchestrator.Worker|8080
|
||||
# ── Slot 18: TaskRunner ─────────────────────────────────────────────────────────
|
||||
taskrunner-web|devops/docker/Dockerfile.hardened.template|src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.WebService/StellaOps.TaskRunner.WebService.csproj|StellaOps.TaskRunner.WebService|8080
|
||||
taskrunner-worker|devops/docker/Dockerfile.hardened.template|src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Worker/StellaOps.TaskRunner.Worker.csproj|StellaOps.TaskRunner.Worker|8080
|
||||
# ── Slot 19: Scheduler ──────────────────────────────────────────────────────────
|
||||
scheduler-web|devops/docker/Dockerfile.hardened.template|src/Scheduler/StellaOps.Scheduler.WebService/StellaOps.Scheduler.WebService.csproj|StellaOps.Scheduler.WebService|8080
|
||||
scheduler-worker|devops/docker/Dockerfile.hardened.template|src/Scheduler/StellaOps.Scheduler.Worker.Host/StellaOps.Scheduler.Worker.Host.csproj|StellaOps.Scheduler.Worker.Host|8080
|
||||
# ── Slot 20: Graph ──────────────────────────────────────────────────────────────
|
||||
graph-api|devops/docker/Dockerfile.hardened.template|src/Graph/StellaOps.Graph.Api/StellaOps.Graph.Api.csproj|StellaOps.Graph.Api|8080
|
||||
# ── Slot 21: Cartographer ───────────────────────────────────────────────────────
|
||||
cartographer|devops/docker/Dockerfile.hardened.template|src/Cartographer/StellaOps.Cartographer/StellaOps.Cartographer.csproj|StellaOps.Cartographer|8080
|
||||
# ── Slot 22: ReachGraph ─────────────────────────────────────────────────────────
|
||||
reachgraph-web|devops/docker/Dockerfile.hardened.template|src/ReachGraph/StellaOps.ReachGraph.WebService/StellaOps.ReachGraph.WebService.csproj|StellaOps.ReachGraph.WebService|8080
|
||||
# ── Slot 23: Timeline Indexer ───────────────────────────────────────────────────
|
||||
timeline-indexer-web|devops/docker/Dockerfile.hardened.template|src/TimelineIndexer/StellaOps.TimelineIndexer/StellaOps.TimelineIndexer.WebService/StellaOps.TimelineIndexer.WebService.csproj|StellaOps.TimelineIndexer.WebService|8080
|
||||
timeline-indexer-worker|devops/docker/Dockerfile.hardened.template|src/TimelineIndexer/StellaOps.TimelineIndexer/StellaOps.TimelineIndexer.Worker/StellaOps.TimelineIndexer.Worker.csproj|StellaOps.TimelineIndexer.Worker|8080
|
||||
# ── Slot 24: Timeline ───────────────────────────────────────────────────────────
|
||||
timeline-web|devops/docker/Dockerfile.hardened.template|src/Timeline/StellaOps.Timeline.WebService/StellaOps.Timeline.WebService.csproj|StellaOps.Timeline.WebService|8080
|
||||
# ── Slot 25: Findings Ledger ────────────────────────────────────────────────────
|
||||
findings-ledger-web|devops/docker/Dockerfile.hardened.template|src/Findings/StellaOps.Findings.Ledger.WebService/StellaOps.Findings.Ledger.WebService.csproj|StellaOps.Findings.Ledger.WebService|8080
|
||||
# ── Slot 26: Doctor ─────────────────────────────────────────────────────────────
|
||||
doctor-web|devops/docker/Dockerfile.hardened.template|src/Doctor/StellaOps.Doctor.WebService/StellaOps.Doctor.WebService.csproj|StellaOps.Doctor.WebService|8080
|
||||
doctor-scheduler|devops/docker/Dockerfile.hardened.template|src/Doctor/StellaOps.Doctor.Scheduler/StellaOps.Doctor.Scheduler.csproj|StellaOps.Doctor.Scheduler|8080
|
||||
# ── Slot 27: OpsMemory ──────────────────────────────────────────────────────────
|
||||
opsmemory-web|devops/docker/Dockerfile.hardened.template|src/OpsMemory/StellaOps.OpsMemory.WebService/StellaOps.OpsMemory.WebService.csproj|StellaOps.OpsMemory.WebService|8080
|
||||
# ── Slot 28: Notifier ───────────────────────────────────────────────────────────
|
||||
notifier-web|devops/docker/Dockerfile.hardened.template|src/Notifier/StellaOps.Notifier/StellaOps.Notifier.WebService/StellaOps.Notifier.WebService.csproj|StellaOps.Notifier.WebService|8080
|
||||
notifier-worker|devops/docker/Dockerfile.hardened.template|src/Notifier/StellaOps.Notifier/StellaOps.Notifier.Worker/StellaOps.Notifier.Worker.csproj|StellaOps.Notifier.Worker|8080
|
||||
# ── Slot 29: Notify ─────────────────────────────────────────────────────────────
|
||||
notify-web|devops/docker/Dockerfile.hardened.template|src/Notify/StellaOps.Notify.WebService/StellaOps.Notify.WebService.csproj|StellaOps.Notify.WebService|8080
|
||||
# ── Slot 30: Signer ─────────────────────────────────────────────────────────────
|
||||
signer|devops/docker/Dockerfile.hardened.template|src/Signer/StellaOps.Signer/StellaOps.Signer.WebService/StellaOps.Signer.WebService.csproj|StellaOps.Signer.WebService|8441
|
||||
# ── Slot 31: SmRemote ───────────────────────────────────────────────────────────
|
||||
smremote|devops/docker/Dockerfile.hardened.template|src/SmRemote/StellaOps.SmRemote.Service/StellaOps.SmRemote.Service.csproj|StellaOps.SmRemote.Service|8080
|
||||
# ── Slot 32: AirGap Controller ──────────────────────────────────────────────────
|
||||
airgap-controller|devops/docker/Dockerfile.hardened.template|src/AirGap/StellaOps.AirGap.Controller/StellaOps.AirGap.Controller.csproj|StellaOps.AirGap.Controller|8080
|
||||
# ── Slot 33: AirGap Time ────────────────────────────────────────────────────────
|
||||
airgap-time|devops/docker/Dockerfile.hardened.template|src/AirGap/StellaOps.AirGap.Time/StellaOps.AirGap.Time.csproj|StellaOps.AirGap.Time|8080
|
||||
# ── Slot 34: PacksRegistry ──────────────────────────────────────────────────────
|
||||
packsregistry-web|devops/docker/Dockerfile.hardened.template|src/PacksRegistry/StellaOps.PacksRegistry/StellaOps.PacksRegistry.WebService/StellaOps.PacksRegistry.WebService.csproj|StellaOps.PacksRegistry.WebService|8080
|
||||
packsregistry-worker|devops/docker/Dockerfile.hardened.template|src/PacksRegistry/StellaOps.PacksRegistry/StellaOps.PacksRegistry.Worker/StellaOps.PacksRegistry.Worker.csproj|StellaOps.PacksRegistry.Worker|8080
|
||||
# ── Slot 35: Registry Token ─────────────────────────────────────────────────────
|
||||
registry-token|devops/docker/Dockerfile.hardened.template|src/Registry/StellaOps.Registry.TokenService/StellaOps.Registry.TokenService.csproj|StellaOps.Registry.TokenService|8080
|
||||
# ── Slot 36: BinaryIndex ────────────────────────────────────────────────────────
|
||||
binaryindex-web|devops/docker/Dockerfile.hardened.template|src/BinaryIndex/StellaOps.BinaryIndex.WebService/StellaOps.BinaryIndex.WebService.csproj|StellaOps.BinaryIndex.WebService|8080
|
||||
# ── Slot 37: IssuerDirectory ────────────────────────────────────────────────────
|
||||
issuer-directory-web|devops/docker/Dockerfile.hardened.template|src/IssuerDirectory/StellaOps.IssuerDirectory/StellaOps.IssuerDirectory.WebService/StellaOps.IssuerDirectory.WebService.csproj|StellaOps.IssuerDirectory.WebService|8080
|
||||
# ── Slot 38: Symbols ────────────────────────────────────────────────────────────
|
||||
symbols|devops/docker/Dockerfile.hardened.template|src/Symbols/StellaOps.Symbols.Server/StellaOps.Symbols.Server.csproj|StellaOps.Symbols.Server|8080
|
||||
# ── Slot 39: SbomService ────────────────────────────────────────────────────────
|
||||
sbomservice|devops/docker/Dockerfile.hardened.template|src/SbomService/StellaOps.SbomService/StellaOps.SbomService.csproj|StellaOps.SbomService|8080
|
||||
# ── Slot 40: ExportCenter ───────────────────────────────────────────────────────
|
||||
export|devops/docker/Dockerfile.hardened.template|src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.WebService/StellaOps.ExportCenter.WebService.csproj|StellaOps.ExportCenter.WebService|8080
|
||||
export-worker|devops/docker/Dockerfile.hardened.template|src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Worker/StellaOps.ExportCenter.Worker.csproj|StellaOps.ExportCenter.Worker|8080
|
||||
# ── Slot 41: Replay ─────────────────────────────────────────────────────────────
|
||||
replay-web|devops/docker/Dockerfile.hardened.template|src/Replay/StellaOps.Replay.WebService/StellaOps.Replay.WebService.csproj|StellaOps.Replay.WebService|8080
|
||||
# ── Slot 42: Integrations ───────────────────────────────────────────────────────
|
||||
integrations-web|devops/docker/Dockerfile.hardened.template|src/Integrations/StellaOps.Integrations.WebService/StellaOps.Integrations.WebService.csproj|StellaOps.Integrations.WebService|8080
|
||||
# ── Slot 43: Zastava ────────────────────────────────────────────────────────────
|
||||
zastava-webhook|devops/docker/Dockerfile.hardened.template|src/Zastava/StellaOps.Zastava.Webhook/StellaOps.Zastava.Webhook.csproj|StellaOps.Zastava.Webhook|8080
|
||||
# ── Slot 44: Signals ────────────────────────────────────────────────────────────
|
||||
signals|devops/docker/Dockerfile.hardened.template|src/Signals/StellaOps.Signals/StellaOps.Signals.csproj|StellaOps.Signals|8080
|
||||
# ── Slot 45: AdvisoryAI ─────────────────────────────────────────────────────────
|
||||
advisory-ai-web|devops/docker/Dockerfile.hardened.template|src/AdvisoryAI/StellaOps.AdvisoryAI.WebService/StellaOps.AdvisoryAI.WebService.csproj|StellaOps.AdvisoryAI.WebService|8080
|
||||
advisory-ai-worker|devops/docker/Dockerfile.hardened.template|src/AdvisoryAI/StellaOps.AdvisoryAI.Worker/StellaOps.AdvisoryAI.Worker.csproj|StellaOps.AdvisoryAI.Worker|8080
|
||||
# ── Slot 46: Unknowns ───────────────────────────────────────────────────────────
|
||||
unknowns-web|devops/docker/Dockerfile.hardened.template|src/Unknowns/StellaOps.Unknowns.WebService/StellaOps.Unknowns.WebService.csproj|StellaOps.Unknowns.WebService|8080
|
||||
# ── Console (Angular frontend) ──────────────────────────────────────────────────
|
||||
console|devops/docker/Dockerfile.console|src/Web/StellaOps.Web|StellaOps.Web|8080
|
||||
|
||||
Reference in New Issue
Block a user