Skip to content

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 to main
  • build-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:

  1. Install .NET 8 runtime + PostgreSQL + Redis on the VM
  2. Create a systemd service pointing to the published DLL
  3. Set environment variables in the service file (connection strings, JWT key, OAuth secrets)
  4. Open port 5000 in the OS firewall and cloud security list
  5. Create a GitHub Actions workflow with ORACLE_HOST, ORACLE_USER, ORACLE_SSH_KEY secrets

Database Migrations

EF Core migrations run automatically at startup when RUN_MIGRATIONS=true:

// Program.cs
if (app.Configuration["RUN_MIGRATIONS"] == "true")
    await db.Database.MigrateAsync();

To generate a new migration locally:

cd SimCopilot.Api/src/SimCopilot.Api
dotnet ef migrations add <MigrationName>

Healthchecks

Endpoint Returns
GET /health { "status": "Healthy" }
GET /health/ready Database healthy status
GET /health/live 200 OK