Deployment¶
The API is deployed on Railway using Docker. Every push to main triggers a GitHub Actions workflow that builds and deploys automatically.
Production Stack¶
| Service | Provider | Notes |
|---|---|---|
| Compute | Railway | Docker container, .NET 8 |
| Database | Neon Postgres | Serverless, auto-scaling |
| Cache | Redis | Leaderboard ranking cache |
| Logging | Serilog | Compact JSON → Railway stdout |
| Errors | Sentry | Exception tracking |
| Metrics | Prometheus | /metrics endpoint |
Dockerfile¶
The Dockerfile at the repo root builds SimCopilot.Api:
# Build stage
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish SimCopilot.Api/src/SimCopilot.Api/SimCopilot.Api.csproj \
-c Release -o /app/publish
# Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "SimCopilot.Api.dll"]
GitHub Actions — API Deploy¶
The .github/workflows/ directory contains:
deploy-api.yml— builds and deploys to Railway on push tomainbuild-client.yml— builds and tests the WPF client on push
CI/CD Workflow¶
git push main
→ GitHub Actions
→ dotnet publish (linux-x64)
→ Railway detects new Docker build
→ Container replaces running instance (zero-downtime)
Self-Hosted (Oracle Cloud / Linux VM)¶
For self-hosted deployments (Oracle Free Tier, VPS, etc.) see the legacy setup guide preserved in docs/SETUP_GIT_CICD.md in git history. Key steps:
- Install .NET 8 runtime + PostgreSQL + Redis on the VM
- Create a systemd service pointing to the published DLL
- Set environment variables in the service file (connection strings, JWT key, OAuth secrets)
- Open port 5000 in the OS firewall and cloud security list
- Create a GitHub Actions workflow with
ORACLE_HOST,ORACLE_USER,ORACLE_SSH_KEYsecrets
Database Migrations¶
EF Core migrations run automatically at startup when RUN_MIGRATIONS=true:
To generate a new migration locally:
Healthchecks¶
| Endpoint | Returns |
|---|---|
GET /health |
{ "status": "Healthy" } |
GET /health/ready |
Database healthy status |
GET /health/live |
200 OK |