Gongomat Dokumentation

Azure Deployment Anleitung - Gongomat Testsystem

Übersicht

Diese Anleitung beschreibt das Deployment der Gongomat Blazor Server-Anwendung auf ein Azure-Testsystem.

TODO: Beschreibung Übernahme GongomatUhr Projekt

Projektbeschreibung

  • Typ: Blazor Server (.NET 8)
  • Framework: ASP.NET Core 8.0
  • Authentifizierung: ASP.NET Core Identity mit Rollen
  • Datenbanken: 2 SQL Server-Datenbanken (Identity + Gongomat)
  • Features: SignalR (ClientHub), Web APIs, QR-Code-Generierung, Lokalisierung (de-CH, en-US)

Benötigte Azure-Ressourcen

1. Azure App Service

  • Service Plan: B1 oder höher (Basic oder Standard empfohlen für Testsystem)
  • Runtime Stack: .NET 8 (LTS)
  • Operating System: Linux oder Windows
  • Region: West Europe (für EU-Daten) oder nach Bedarf

2. Azure SQL Database

Zwei Datenbanken werden benötigt:

  • ApplicationDB: Für ASP.NET Core Identity (Benutzer, Rollen)
  • GongomatDB: Für Anwendungsdaten (Clients, Gongs, Patterns, Exams)

Empfohlene Konfiguration für Testsystem:

  • Service Tier: Basic oder S0 (Standard)
  • Compute Tier: Serverless (kosteneffizient für Tests)
  • Backup: Geo-redundant für Production, lokal-redundant für Test

Deployment-Schritte

Schritt 1: Azure-Ressourcen erstellen

Option A: Über Azure Portal

  1. Resource Group erstellen

    • Portal → Resource Groups → Create
    • Name: rg-gongomat-test
    • Region: West Europe
  2. SQL Server erstellen

    • Portal → SQL servers → Create
    • Server Name: sql-gongomat-test (muss global eindeutig sein)
    • Authentication: SQL authentication + Azure AD authentication (empfohlen)
    • Firewall: "Allow Azure services and resources to access this server" aktivieren
  3. Datenbanken erstellen

    • Zwei Datenbanken auf dem erstellten SQL Server:
      • db-gongomat-identity-test
      • db-gongomat-data-test
  4. App Service Plan erstellen

    • Portal → App Service Plans → Create
    • Name: asp-gongomat-test
    • OS: Linux (günstiger) oder Windows
    • Pricing Tier: B1 oder S1
  5. App Service (Web App) erstellen

    • Portal → App Services → Create → Web App
    • Name: app-gongomat-test (wird zu app-gongomat-test.azurewebsites.net)
    • Runtime stack: .NET 8 (LTS)
    • Operating System: Linux oder Windows (muss zum App Service Plan passen)
    • App Service Plan: asp-gongomat-test (vorher erstellt)

Option B: Über Azure CLI

# Login
az login

# Resource Group erstellen
az group create --name rg-gongomat-test --location westeurope

# SQL Server erstellen
az sql server create \
  --name sql-gongomat-test \
  --resource-group rg-gongomat-test \
  --location westeurope \
  --admin-user gongomat-admin \
  --admin-password "IhrSicheresPasswort123!"

# Firewall-Regel für Azure Services
az sql server firewall-rule create \
  --resource-group rg-gongomat-test \
  --server sql-gongomat-test \
  --name AllowAzureServices \
  --start-ip-address 0.0.0.0 \
  --end-ip-address 0.0.0.0

# Datenbanken erstellen
az sql db create \
  --resource-group rg-gongomat-test \
  --server sql-gongomat-test \
  --name db-gongomat-identity-test \
  --service-objective S0

az sql db create \
  --resource-group rg-gongomat-test \
  --server sql-gongomat-test \
  --name db-gongomat-data-test \
  --service-objective S0

# App Service Plan erstellen
az appservice plan create \
  --name asp-gongomat-test \
  --resource-group rg-gongomat-test \
  --sku B1 \
  --is-linux

# Web App erstellen
az webapp create \
  --resource-group rg-gongomat-test \
  --plan asp-gongomat-test \
  --name app-gongomat-test \
  --runtime "DOTNETCORE:8.0"

Schritt 2: Connection Strings konfigurieren

Im Azure Portal:

  1. App Service öffnen → Configuration → Connection strings
  2. Zwei Connection Strings hinzufügen:

DefaultConnection (Type: SQLAzure):

Server=tcp:sql-gongomat-test.database.windows.net,1433;Initial Catalog=db-gongomat-identity-test;Persist Security Info=False;User ID=gongomat-admin;Password=IhrSicheresPasswort123!;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;

GongomatConnection (Type: SQLAzure):

Server=tcp:sql-gongomat-test.database.windows.net,1433;Initial Catalog=db-gongomat-data-test;Persist Security Info=False;User ID=gongomat-admin;Password=IhrSicheresPasswort123!;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;

Über Azure CLI:

az webapp config connection-string set \
  --resource-group rg-gongomat-test \
  --name app-gongomat-test \
  --connection-string-type SQLAzure \
  --settings DefaultConnection="Server=tcp:sql-gongomat-test.database.windows.net,1433;Initial Catalog=db-gongomat-identity-test;Persist Security Info=False;User ID=gongomat-admin;Password=IhrSicheresPasswort123!;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" \
             GongomatConnection="Server=tcp:sql-gongomat-test.database.windows.net,1433;Initial Catalog=db-gongomat-data-test;Persist Security Info=False;User ID=gongomat-admin;Password=IhrSicheresPasswort123!;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"

Schritt 3: Application Settings konfigurieren

Im Azure Portal → App Service → Configuration → Application settings:

ASPNETCORE_ENVIRONMENT = Staging (oder Production)
WEBSITE_TIME_ZONE = W. Europe Standard Time

Wichtig für SignalR:

WEBSITE_ENABLE_SYNC_UPDATE_SITE = true
WEBSITE_ADD_SITENAME_BINDINGS_IN_APPHOST_CONFIG = 1

Für WebSocket-Support (SignalR):

Im Azure Portal → Configuration → General settings:
- Web sockets: On

Schritt 4: Anwendung vorbereiten

4.1 appsettings.Production.json erstellen

Erstellen Sie eine neue Datei im Projekt:

{
  "ConnectionStrings": {
    "DefaultConnection": "",
    "GongomatConnection": ""
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.EntityFrameworkCore.Database.Command": "Warning"
    }
  },
  "AllowedHosts": "*"
}

4.2 Anwendung veröffentlichen

Option A: Visual Studio

  1. Rechtsklick auf Projekt → Publish
  2. Target: Azure → Azure App Service (Linux/Windows)
  3. Subscription auswählen
  4. App Service auswählen: app-gongomat-test
  5. Publish klicken

Option B: Visual Studio Code / CLI

# Im Projektverzeichnis
dotnet publish -c Release -o ./publish

# ZIP erstellen
cd publish
Compress-Archive -Path * -DestinationPath ../gongomat.zip

# Mit Azure CLI deployen
az webapp deployment source config-zip \
  --resource-group rg-gongomat-test \
  --name app-gongomat-test \
  --src gongomat.zip

Option C: GitHub Actions (CI/CD)

Erstellen Sie .github/workflows/azure-deploy.yml:

name: Deploy to Azure

on:
  push:
    branches:
      - GomgomatV2  # Ihr Branch

env:
  AZURE_WEBAPP_NAME: app-gongomat-test
  AZURE_WEBAPP_PACKAGE_PATH: './Gongomat'
  DOTNET_VERSION: '8.0.x'

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup .NET
        uses: actions/setup-dotnet@v3
        with:
          dotnet-version: ${{ env.DOTNET_VERSION }}
      
      - name: Restore dependencies
        run: dotnet restore
        working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
      
      - name: Build
        run: dotnet build --configuration Release --no-restore
        working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
      
      - name: Publish
        run: dotnet publish -c Release -o ${{env.DOTNET_ROOT}}/gongomat
        working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
      
      - name: Deploy to Azure Web App
        uses: azure/webapps-deploy@v2
        with:
          app-name: ${{ env.AZURE_WEBAPP_NAME }}
          publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
          package: ${{env.DOTNET_ROOT}}/gongomat

Schritt 5: Datenbank-Migrationen ausführen

Option A: Über lokale Entwicklungsumgebung

Passen Sie temporär die appsettings.json an oder verwenden Sie User Secrets:

# Connection Strings setzen
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=tcp:sql-gongomat-test.database.windows.net,1433;..."
dotnet user-secrets set "ConnectionStrings:GongomatConnection" "Server=tcp:sql-gongomat-test.database.windows.net,1433;..."

# Migrationen ausführen
dotnet ef database update --context ApplicationDbContext
dotnet ef database update --context GongomatContext

Option B: Startup-Migration (in Program.cs)

Fügen Sie vor app.Run() hinzu (nur für Test, nicht für Production empfohlen):

// Automatische Migration beim Start (nur für Testsystem)
using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    try
    {
        var identityDb = services.GetRequiredService<ApplicationDbContext>();
        var gongomatDb = services.GetRequiredService<GongomatContext>();
        
        identityDb.Database.Migrate();
        gongomatDb.Database.Migrate();
    }
    catch (Exception ex)
    {
        var logger = services.GetRequiredService<ILogger<Program>>();
        logger.LogError(ex, "An error occurred while migrating the database.");
    }
}

Option C: Azure App Service SSH/Console

Im Portal → App Service → SSH/Advanced Tools (Kudu) → SSH:

cd /home/site/wwwroot
dotnet Gongomat.dll --migrate

Schritt 6: Erste Benutzer anlegen

Da die Anwendung RequireConfirmedAccount = true verwendet, müssen Sie initial einen Admin-User erstellen.

Option 1: Temporär RequireConfirmedAccount deaktivieren

  • In Program.cs ändern: options.SignIn.RequireConfirmedAccount = false
  • Deployen, registrieren, Admin-Rolle zuweisen
  • Zurück auf true setzen

Option 2: Direkt in Datenbank

-- Verbindung zur Identity-Datenbank
-- User und Admin-Rolle erstellen
-- (Beispiel-SQL-Skripte im Anhang)

Schritt 7: Konfiguration überprüfen

App Service Logs aktivieren

Azure Portal → App Service → Monitoring → App Service Logs:

  • Application Logging: File System (Information)
  • Detailed Error Messages: On
  • Failed Request Tracing: On

Logs ansehen

az webapp log tail --name app-gongomat-test --resource-group rg-gongomat-test

Oder im Portal → Log Stream

Wichtige Besonderheiten für Gongomat

1. SignalR (ClientHub)

  • WebSockets müssen aktiviert sein (siehe Schritt 3)
  • In Azure skaliert SignalR mit Azure SignalR Service besser (optional für Test)

2. SkiaSharp (QR-Code / Grafik)

Falls SkiaSharp-Fehler auftreten:

  • Bei Linux App Service: SkiaSharp.NativeAssets.Linux.NoDependencies ist bereits im Projekt
  • Bei Windows: Standard SkiaSharp funktioniert

3. Kestrel IPv4 Configuration

Die Zeile serverOptions.Listen(IPAddress.Any, 5226); in Program.cs sollte für Azure entfernt oder bedingt sein:

if (builder.Environment.IsDevelopment())
{
    builder.WebHost.ConfigureKestrel(serverOptions =>
    {
        serverOptions.Listen(IPAddress.Any, 5226);
    });
}

Sicherheitsempfehlungen für Testsystem

1. SQL-Zugriff beschränken

# Nur spezifische IPs erlauben
az sql server firewall-rule create \
  --resource-group rg-gongomat-test \
  --server sql-gongomat-test \
  --name AllowMyIP \
  --start-ip-address <IhreIP> \
  --end-ip-address <IhreIP>

2. Managed Identity verwenden (empfohlen)

Statt SQL-Authentication:

  • System-assigned Managed Identity für App Service aktivieren
  • SQL-Datenbank mit Azure AD-User für Managed Identity konfigurieren
  • Connection String anpassen: Server=...; Authentication=Active Directory Default; Database=...

3. Azure Key Vault (Optional, für Secrets)

az keyvault create \
  --name kv-gongomat-test \
  --resource-group rg-gongomat-test \
  --location westeurope

# Secrets hinzufügen
az keyvault secret set \
  --vault-name kv-gongomat-test \
  --name "DefaultConnection" \
  --value "Server=tcp:..."

In App Service Configuration:

@Microsoft.KeyVault(SecretUri=https://kv-gongomat-test.vault.azure.net/secrets/DefaultConnection/)

Monitoring & Troubleshooting

Application Insights (empfohlen)

  1. Application Insights Ressource erstellen
  2. Connection String in App Service Configuration:
    APPLICATIONINSIGHTS_CONNECTION_STRING = <connection-string>
    
  3. NuGet-Package hinzufügen:
    dotnet add package Microsoft.ApplicationInsights.AspNetCore
    
  4. In Program.cs:
    builder.Services.AddApplicationInsightsTelemetry();
    

Häufige Probleme

Problem: HTTP 500 Fehler

  • Lösung: Logs in Log Stream prüfen, DeveloperPageException aktivieren für mehr Details

Problem: Datenbank-Verbindungsfehler

  • Firewall-Regeln prüfen
  • Connection String validieren
  • SQL Server erreichbar? Test-NetConnection sql-gongomat-test.database.windows.net -Port 1433

Problem: SignalR funktioniert nicht

  • WebSockets aktiviert?
  • ARR Affinity für Sticky Sessions: On (bei Scale-out)

Problem: 503 Service Unavailable

  • App startet nicht → Startup-Logs prüfen
  • Migrations-Fehler? → Manuell ausführen

Kosten-Übersicht (Testsystem, ca.)

  • App Service B1: ~13 EUR/Monat
  • SQL Database S0 x2: ~30 EUR/Monat
  • Application Insights: ~5 EUR/Monat (bei geringem Traffic)
  • Gesamt: ~50 EUR/Monat

Spar-Tipps:

  • Serverless SQL Database für Test
  • App Service außerhalb der Testzeiten stoppen
  • Free-Tier von Application Insights nutzen

Nützliche CLI-Befehle

# App starten/stoppen
az webapp start --name app-gongomat-test --resource-group rg-gongomat-test
az webapp stop --name app-gongomat-test --resource-group rg-gongomat-test

# Logs streamen
az webapp log tail --name app-gongomat-test --resource-group rg-gongomat-test

# App neustarten
az webapp restart --name app-gongomat-test --resource-group rg-gongomat-test

# Deployment-Status
az webapp deployment list-publishing-profiles --name app-gongomat-test --resource-group rg-gongomat-test

# App-Settings auflisten
az webapp config appsettings list --name app-gongomat-test --resource-group rg-gongomat-test

Checkliste vor Go-Live (Test)

  • Azure-Ressourcen erstellt (App Service, SQL Databases)
  • Connection Strings konfiguriert
  • WebSockets aktiviert
  • Datenbank-Migrationen ausgeführt
  • Admin-Benutzer erstellt
  • App erfolgreich deployed
  • Logs aktiviert
  • Health-Check: Anwendung erreichbar unter https://app-gongomat-test.azurewebsites.net
  • SignalR-Verbindung funktioniert (ClientHub)
  • Authentifizierung/Autorisierung funktioniert
  • API-Endpunkte erreichbar (/api/exams, /api/sounds, /api/gongs)
  • QR-Code-Generierung funktioniert

Support & Weitere Informationen

Anhang: SQL-Skripte für Initial Setup

Admin-User erstellen (in Identity DB)

-- Beispiel: Password: Admin123! (Hash muss mit ASP.NET Core Identity übereinstimmen)
-- Verwenden Sie lieber die Registrierungs-UI oder ein Setup-Skript in C#

-- Rollen erstellen
INSERT INTO AspNetRoles (Id, Name, NormalizedName, ConcurrencyStamp)
VALUES 
  (NEWID(), 'Admin', 'ADMIN', NEWID()),
  (NEWID(), 'User', 'USER', NEWID());

-- User manuell zu erstellen ist komplex wegen Password-Hashing
-- Empfehlung: Startup-Code für Seed-Data verwenden

Besser: Startup-Seed in Program.cs:

using (var scope = app.Services.CreateScope())
{
    var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
    var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
    
    // Rollen erstellen
    if (!await roleManager.RoleExistsAsync("Admin"))
    {
        await roleManager.CreateAsync(new IdentityRole("Admin"));
    }
    
    // Admin-User erstellen
    var adminEmail = "admin@gongomat.test";
    var adminUser = await userManager.FindByEmailAsync(adminEmail);
    if (adminUser == null)
    {
        adminUser = new ApplicationUser 
        { 
            UserName = adminEmail, 
            Email = adminEmail,
            EmailConfirmed = true 
        };
        await userManager.CreateAsync(adminUser, "Admin123!");
        await userManager.AddToRoleAsync(adminUser, "Admin");
    }
}

Version: 1.0
Stand: 2024
Projekt: Gongomat V2


An unhandled error has occurred. Reload 🗙