Initial commit

This commit is contained in:
2026-04-23 21:38:24 -04:00
commit 63e12a9636
1762 changed files with 1672620 additions and 0 deletions
+171
View File
@@ -0,0 +1,171 @@
# Azure Deployment Setup Guide
## Overview
The app uses environment-specific config layering:
- `appsettings.json` — base defaults (checked into source)
- `appsettings.Production.json` — production log levels (checked into source)
- **Azure App Service Configuration** — secrets and environment-specific values (overrides everything, never in source)
Azure App Service flattens nested JSON keys using `__` (double underscore).
For example, `Stripe:SecretKey` in JSON becomes `Stripe__SecretKey` in Azure.
---
## Step 1 — Create Azure Resources
You will need the following Azure resources:
| Resource | Purpose |
|---|---|
| App Service (Windows or Linux, .NET 8) | Hosts the web application |
| Azure SQL Database | Production database |
| Azure Storage Account (`powdercoatingappdev` or prod equivalent) | Blob storage for files + Data Protection keys |
### Storage containers to create (or they auto-create on first run):
| Container Name | Purpose |
|---|---|
| `profileimages` | User profile photos |
| `jobimages` | Job photos |
| `companylogos` | Company logo images |
| `manuals` | Equipment PDF manuals |
| `dataprotection` | ASP.NET Data Protection keys (auto-created on startup) |
---
## Step 2 — App Service Configuration (Application Settings)
Navigate to: **App Service → Configuration → Application Settings**
Add each of the following as individual Application Settings entries.
### Required — Environment
| Name | Value |
|---|---|
| `ASPNETCORE_ENVIRONMENT` | `Production` |
### Required — Database
| Name | Value |
|---|---|
| `ConnectionStrings__DefaultConnection` | `Server=<your-server>.database.windows.net;Database=PowderCoatingDb;User Id=<user>;Password=<password>;MultipleActiveResultSets=true;TrustServerCertificate=true;Encrypt=true` |
### Required — Azure Storage
| Name | Value |
|---|---|
| `Storage__ConnectionString` | `DefaultEndpointsProtocol=https;AccountName=<account>;AccountKey=<key>;EndpointSuffix=core.windows.net` |
The container names default to the values below and only need to be set here if you want to override them:
| Name | Default Value |
|---|---|
| `Storage__Containers__ProfileImages` | `profileimages` |
| `Storage__Containers__JobImages` | `jobimages` |
| `Storage__Containers__Manuals` | `manuals` |
| `Storage__Containers__CompanyLogos` | `companylogos` |
### Required — Stripe
Replace with your **live** keys (not test keys) for production.
| Name | Value |
|---|---|
| `Stripe__SecretKey` | `sk_live_...` |
| `Stripe__PublishableKey` | `pk_live_...` |
| `Stripe__WebhookSecret` | `whsec_...` |
| `Stripe__Prices__Basic` | `price_...` (your live Stripe price ID) |
| `Stripe__Prices__Pro` | `price_...` (your live Stripe price ID) |
| `Stripe__Prices__Enterprise` | `price_...` (your live Stripe price ID) |
### Required — SendGrid
| Name | Value |
|---|---|
| `SendGrid__ApiKey` | `SG....` |
| `SendGrid__FromEmail` | `noreply@yourdomain.com` |
| `SendGrid__FromName` | `Your Company Name` |
### Optional — Twilio (SMS)
Only needed if SMS notifications are enabled.
| Name | Value |
|---|---|
| `Twilio__AccountSid` | `AC...` |
| `Twilio__AuthToken` | `...` |
| `Twilio__FromNumber` | `+1XXXXXXXXXX` |
### Optional — App Settings Overrides
| Name | Value |
|---|---|
| `AppSettings__CompanyName` | `Your Powder Coating Company` |
| `AppSettings__BaseUrl` | `https://yourdomain.azurewebsites.net` |
| `AppSettings__TaxRate` | `0.0` |
| `AppSettings__Currency` | `USD` |
---
## Step 3 — Stripe Webhook (if using billing)
1. In the Stripe Dashboard, add a webhook endpoint pointing to:
`https://<your-domain>/stripe/webhook`
2. Select events: `customer.subscription.created`, `customer.subscription.updated`,
`customer.subscription.deleted`, `invoice.payment_succeeded`, `invoice.payment_failed`
3. Copy the webhook signing secret into `Stripe__WebhookSecret` above.
---
## Step 4 — Database
EF Core migrations run **automatically on startup** in Production.
No manual `dotnet ef database update` step is needed after the first deployment.
For the very first deployment only, ensure the Azure SQL firewall allows connections
from your App Service (or enable "Allow Azure services to access this server").
---
## Step 5 — Deploy
```bash
# Publish to a local folder
dotnet publish src/PowderCoating.Web -c Release -o ./publish
# Or use Azure CLI to deploy directly
az webapp deployment source config-zip \
--resource-group <rg> \
--name <app-service-name> \
--src publish.zip
```
Or connect the App Service to your git repo/GitHub Actions for CI/CD.
---
## Step 6 — First Run Checklist
After deploying and before handing off to users:
- [ ] App loads at the Azure URL without errors
- [ ] Log in with SuperAdmin credentials (`superadmin@powdercoating.com` / `SuperAdmin123!`) or company admin (`admin@demo.com` / `CompanyAdmin123!`)
- [ ] Platform Management → Seed Data → seed System Data
- [ ] Platform Management → Storage Migration → migrate any existing local files to Azure
- [ ] Verify a profile photo and job photo load correctly
- [ ] Verify Stripe webhook is receiving events (check Stripe Dashboard → Webhooks)
- [ ] Update SuperAdmin password to something strong
---
## Notes
- **Data Protection keys** are stored in the `dataprotection` Azure Blob container as `keys.xml`.
This allows auth cookies to survive app restarts and work across multiple instances.
- **Local development** is unaffected — it uses `appsettings.Development.json` and a local
filesystem key store. No Azure credentials are required for local dev (though the dev storage
account is already configured in `appsettings.Development.json`).
- **Logs** write to both console (captured by Azure Log Stream) and the `logs/` folder on the
App Service filesystem. View live logs via: **App Service → Log stream**.