-
Notifications
You must be signed in to change notification settings - Fork 0
Deployment
UncannyPrompt is packaged as one WebApp container plus SQL Server. The development reference is docker-compose.yml; production can start from docker-compose.prod.example.yml, which uses the pre-built WebApp image from GHCR.
Browser / API caller
-> reverse proxy / TLS termination
-> UncannyPrompt.WebApp
-> SQL Server
The MVP has no background worker and no external search engine. All application behavior runs in the WebApp process.
Bring the stack up:
docker compose up --build -d
docker compose logs -f webappServices:
| Service | Purpose |
|---|---|
webapp |
ASP.NET Core Razor Pages and API host |
sqlserver |
SQL Server database |
Compose reads .env from the repository root. See Configuration for the key naming convention.
The Compose project name is defined by:
COMPOSE_PROJECT_NAME=uncannyprompt
DOTNET_ENVIRONMENT=Development
ASPNETCORE_URLS=http://+:8080This keeps generated container, network, and volume names stable across local folders, and makes the runtime environment and WebApp container listener explicit.
The production example is intentionally a starting point, not a mandatory topology.
cp docker-compose.prod.example.yml docker-compose.ymlThe real production docker-compose.yml should stay local to the server. The example differs from the development stack in a few important ways:
| Concern | Development | Production example |
|---|---|---|
| WebApp image | built locally from infra/Dockerfile.webapp
|
pulled from ghcr.io/ryadel/uncannyprompt-webapp:latest
|
| Restart policy | developer-controlled | restart: unless-stopped |
| SQL Server port | configurable host bind | bound to 127.0.0.1
|
| Data Protection keys | container-local unless configured | persisted in the dataprotection-keys volume |
Standard production startup:
docker compose pull
docker compose up -dApplication-only rollout after CI publishes a new image:
docker compose pull webapp
docker compose up -d --no-deps --remove-orphans webapp
docker image prune -fThe same routine is wrapped by infra/deploy.sh. First-time bootstrap or full stack refresh is wrapped by infra/bootstrap.sh.
See CI/CD for the full build-and-pull flow.
infra/Dockerfile.webapp builds and publishes src/UncannyPrompt.WebApp/UncannyPrompt.WebApp.csproj using a multi-stage .NET 10 image.
The runtime container listens on:
http://+:8080
The published host port is configured by:
Docker__WebAppPort=8080In production, terminate TLS in front of the WebApp with a reverse proxy or platform ingress.
Recommended controls:
- terminate HTTPS before traffic reaches the app;
- set
DOTNET_ENVIRONMENT=Production; - preserve
X-Forwarded-ProtoandX-Forwarded-Forif hosted behind a proxy; - restrict direct access to SQL Server from outside the private network.
The app already enables HTTPS redirect and HSTS outside development.
- Use production-grade SQL Server credentials, and prefer a dedicated application login when connecting to a shared or managed SQL Server instance.
- Store
Database:Password,Security:SecretEncryptionKey,Security:ApiKeyHashKey, and provider client secrets in a secret manager or orchestrator-level environment variables. - Set complete provider settings only for the sign-in methods you want enabled.
- Use real Entra ID redirect URLs matching
Authentication:EntraId:CallbackPath. - Rotate API/hash/encryption keys using an explicit migration plan when existing protected data exists.
-
Database:ApplyMigrationsOnStartup=false; apply EF migrations out-of-band before deploying new application versions. - Keep
.envout of production images and source control. - Keep the production
docker-compose.ymlserver-local. Commit onlydocker-compose.prod.example.yml. - Persist Data Protection keys if more than one WebApp instance exists, or when container replacement must not invalidate cookies.
webapp can be scaled horizontally behind a load balancer, but production deployments must account for:
| Concern | Requirement |
|---|---|
| Cookie/session protection | shared ASP.NET Data Protection key ring for multiple instances |
| Database concurrency | SQL Server sized for listing/search/audit workload |
| Public links | shared database is enough; tokens are stateless from the WebApp perspective |
| Rate limiting | current fixed-window limiters are per-process; use an external limiter for strict cluster-wide limits |
SQL Server is the system of record. Back up:
- full database backups;
- transaction logs for point-in-time restore;
- migration history;
- operational
.env/secret inventory outside source control.
The most important tables for recovery validation are prompts, versions, variables, share grants, public links, users, memberships, and audit events.
Recommended flow:
- Let GitHub Actions build and publish the WebApp image.
- Apply EF migrations against the production database.
- Deploy the new WebApp version.
- Verify
/health. - Check logs for migration/configuration/authentication errors.
Avoid running schema-changing migrations automatically at startup in production unless the deployment platform guarantees singleton startup and rollback behavior.