In distributed enterprise engineering, “it works on my machine but fails on yours” is among the most pervasive productivity killers. This friction typically stems from three root causes:
- Container image drift: Using
:latestor mutable image tags causes developers to pull different versions of databases and message brokers over time, introducing hidden behavioral mismatches. - Hardcoded secrets: Committing development connection strings directly inside
appsettings.jsonintroduces grave security risks when accidentally propagated to upstream repositories. - Fragile database migration scripts: Relying on manual sequential SQL scripts frequently results in corrupted database states when interrupted during complex foreign key and multi-tenant seed execution.
BitzOrcas.Modern adheres to “Infrastructure-as-Code and Zero-Trust Configuration.” The local infrastructure stack relies on SHA-256 digest-pinned containers, while the core host contains a built-in compile-time schema initialization and seeding orchestrator, enabling any developer to establish a clean sandbox within three minutes.
Infrastructure Provisioning Sequence
The installation pipeline consists of four sequential, deterministic milestones:
Step 1: Clone Repository and Restore Dependencies
Clone the source repository and restore all NuGet dependencies required for .NET 10 and C# 14 compilation. BitzOrcas enables Central Package Management (CPM), locking dependency versions centrally inside the root Directory.Packages.props:
# Clone the repositorygit clone https://github.com/shbitz/BitzOrcas.Modern.gitcd BitzOrcas.Modern
# Restore all solution NuGet packages (.NET 10 SDK required)dotnet restoreStep 2: Spin Up Governed Docker Infrastructure
The repository root includes a pre-configured docker-compose.yml. To eliminate version drift across engineering environments, all critical images are pinned by their exact cryptographic digest:
# Launch local middleware containersdocker compose up -d
# Verify container runtime health (STATUS should indicate healthy or Up)docker compose psThe container matrix and port assignments are structured as follows:
| Service | Image & Tag | Host Port | Engineering Role & Rationale |
|---|---|---|---|
| SQL Server | mcr.microsoft.com/mssql/server:2022-latest | 1433 | Primary relational database; default SA password YourStrong!Passw0rd injected via environment |
| Redis | redis:7-alpine | 6379 | FusionCache L2 multi-tier cache, distributed locks, and idempotency key registry |
| RabbitMQ | rabbitmq:3.13-management-alpine | 5672 (AMQP)15672 (Dashboard) | Message transport for CAP Transactional Outbox integration events |
| AgileConfig | Lightweight distributed config server | 15000 | Centralized tenant dynamic configuration center (internal port 5000 mapped to 15000) |
| Qdrant | qdrant/qdrant:latest | 6333 | Vector database dedicated to knowledge base and AI retrieval features |
Step 3: Inject Local Configuration (Zero-Trust Principle)
Inside src/Hosts/BitzOrcas.Api/appsettings.json, the ConnectionStrings:Default value is intentionally left blank. Database connection strings are environment facts and must never be committed to source control.
During local development, inject configuration via environment variables in your active shell. In the .NET configuration provider hierarchy, colon delimiters are mapped using double underscores (__):
# macOS / Linux terminal syntaxexport ConnectionStrings__Default="Server=localhost,1433;Database=BitzOrcas_Dev;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True;MultipleActiveResultSets=True;"For Windows PowerShell environments:
$env:ConnectionStrings__Default="Server=localhost,1433;Database=BitzOrcas_Dev;User Id=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=True;MultipleActiveResultSets=True;"Key connection string parameters explained:
TrustServerCertificate=True: Trusts the self-signed TLS certificate generated inside the local SQL Server container.MultipleActiveResultSets=True(MARS): Enables interleaved execution of multiple active queries across a single physical connection, supporting complex aggregate hydration.
Step 4: Execute Idempotent Schema Provisioning & Seeding
The primary API host includes an embedded schema orchestration engine. It eliminates external migration CLI prerequisites by accepting direct startup arguments:
# Ensure all incremental source generators compile and binddotnet build
# Create tables, create indexes, generate CAP Outbox tables, and seed system datadotnet run --project src/Hosts/BitzOrcas.Api -- --init-schemaExecution Mechanics
-
--init-schema:- Verifies whether the target catalog exists; issues
CREATE DATABASEautomatically if absent. - Gathers Fluent mapping metadata from all registered modules, applying idempotent DDL statements and composite indexes.
- Instantiates CAP Transactional Outbox tables (
cap.publishedandcap.received). - Executes registered
ISeedStepimplementations, creating the built-in super administrator (admin/Admin@2026) and default tenant1000001(Demo Tenant). - Terminates gracefully upon completion with exit code
0.
- Verifies whether the target catalog exists; issues
-
--seed-only:- Designed for staging/production deployments where DBAs have pre-applied schemas, applying only dictionary lookups, permission policies, and seed data.
Once schema generation completes, launch the API host process:
dotnet run --project src/Hosts/BitzOrcas.ApiThe console outputs startup logs confirming active listener bindings:
[02:40:00 INF] Now listening on: http://localhost:6881[02:40:00 INF] Now listening on: https://localhost:6883[02:40:00 INF] Application started. Press Ctrl+C to shut down.[02:40:00 INF] Hosting environment: DevelopmentTroubleshooting Local Setup
1. Port 1433 Collision
If an existing native SQL Server instance is already running on your development host, the container will fail to bind port 1433:
# Check port 1433 listenerlsof -i :1433 # macOS / Linuxnetstat -ano | findstr 1433 # WindowsRemediation: Remap the host port in docker-compose.yml to 11433:1433, updating the environment connection string accordingly to Server=localhost,11433;....
2. Pre-Login Handshake Timeout (Container Not Ready)
The SQL Server engine requires 10 to 15 seconds after container initialization before accepting incoming TCP connections. Running --init-schema immediately after docker compose up may trigger a pre-login handshake timeout.
Remediation: Run docker compose ps to verify the SQL Server container reports (healthy) before invoking the database initialization command.