Skip to content

Hosting Models in ConnectSoft Microservice Template

Purpose & Overview

Hosting Models in the ConnectSoft Microservice Template refer to the various deployment environments and runtime configurations where microservices can be hosted. The template is designed to be hosting-model agnostic, providing a unified application codebase that adapts seamlessly to different hosting environments while maintaining consistent behavior and functionality.

Why Multiple Hosting Models?

Different hosting models offer distinct advantages:

  • Flexibility: Choose the hosting model that best fits organizational infrastructure
  • Cloud Portability: Deploy to different cloud providers or on-premises
  • Cost Optimization: Select hosting models based on cost and performance requirements
  • Operational Requirements: Support different operational models (containers, serverless, traditional)
  • Migration Path: Enable gradual migration between hosting models
  • Development Flexibility: Support different development and deployment workflows

Hosting Model Philosophy

The ConnectSoft Microservice Template is designed to be hosting-model agnostic. The same application code runs consistently across all hosting models, with environment-specific configuration handled through configuration files and environment variables. This ensures code portability and operational flexibility.

Supported Hosting Models

Overview

The template supports the following hosting models:

Hosting Model Platform Use Case Configuration
Kestrel Standalone Cross-platform Development, testing, simple deployments Direct Kestrel hosting
IIS (In-Process) Windows Server Windows Server deployments web.config with hostingModel="inprocess"
IIS (Out-of-Process) Windows Server Legacy Windows Server deployments web.config with hostingModel="outofprocess"
Docker Container Any Docker host Containerized deployments, Kubernetes base Dockerfile, Docker Compose
Linux systemd Linux servers Traditional Linux deployments systemd service file + Nginx
Azure App Service Azure cloud Managed Azure hosting ZIP deploy or container
Kubernetes Any Kubernetes cluster Container orchestration Kubernetes manifests
Azure Functions Azure cloud Serverless workloads Azure Functions host
Azure Container Apps Azure cloud Container-based serverless Container registry

Architecture Overview

Hosting Model Abstraction

Application Code (Hosting-Agnostic)
├── Program.cs (Host Builder)
├── Startup.cs (Service Registration)
├── Middleware Pipeline
└── Business Logic
Hosting Model Adapter
├── Kestrel Configuration
├── Environment Detection
├── Configuration Loading
└── Hosting-Specific Setup
Runtime Environment
├── Kestrel Standalone
├── IIS
├── Docker Container
├── Linux systemd
├── Azure App Service
├── Kubernetes
└── Azure Functions

Common Elements

All hosting models share:

  • Same Application Code: Identical Program.cs and Startup.cs
  • Kestrel Web Server: All models use Kestrel as the web server
  • Configuration System: Unified configuration via appsettings.json
  • Middleware Pipeline: Same middleware pipeline across all models
  • Service Registration: Consistent DI and service registration
  • Environment Awareness: Environment-specific configuration

Kestrel Standalone Hosting

Overview

Kestrel Standalone is the default hosting model where the application runs directly on Kestrel without a reverse proxy or hosting platform.

Characteristics

  • Direct Execution: Application runs directly on Kestrel
  • Development Default: Used by default in dotnet run
  • Cross-Platform: Works on Windows, Linux, and macOS
  • Simple Deployment: No additional infrastructure required
  • Full Control: Direct access to Kestrel configuration

Configuration

Kestrel Configuration (via appsettings.json):

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "Https": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "path/to/certificate.pfx",
          "Password": "password"
        }
      }
    },
    "Limits": {
      "MaxRequestBodySize": 104857600,
      "MaxConcurrentConnections": 100
    }
  }
}

Program.cs Configuration:

private static void DefineKestrel(IWebHostBuilder webBuilder)
{
    webBuilder.ConfigureKestrel((context, options) =>
    {
        IConfigurationSection kestrelSection = context.Configuration.GetRequiredSection("Kestrel");
        kestrelSection.Bind(options);

        options.ConfigureEndpointDefaults(listenOptions =>
        {
            listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
        });
    });
}

Running

Development:

dotnet run --project ConnectSoft.MicroserviceTemplate.Application

Production:

dotnet ConnectSoft.MicroserviceTemplate.Application.dll

Use Cases

  • Local development
  • Testing and CI/CD pipelines
  • Simple deployments without reverse proxy
  • Containerized applications (Kestrel is the web server in containers)

Advantages

  • ✅ Simple setup and configuration
  • ✅ Full control over Kestrel settings
  • ✅ Cross-platform compatibility
  • ✅ No additional infrastructure required

Disadvantages

  • ❌ No built-in reverse proxy features
  • ❌ Manual SSL certificate management
  • ❌ No automatic process management
  • ❌ Limited production-ready features

IIS Hosting

Overview

IIS (Internet Information Services) hosting runs the application on Windows Server with IIS as the reverse proxy and process manager.

Hosting Models

Configuration (web.config):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet"
                  arguments=".\ConnectSoft.MicroserviceTemplate.Application.dll"
                  stdoutLogEnabled="false"
                  stdoutLogFile=".\logs\stdout"
                  hostingModel="inprocess" />
    </system.webServer>
  </location>
</configuration>

Characteristics: - Performance: Faster than out-of-process (no inter-process communication) - Recommended: Default and recommended for .NET Core 3.1+ - Integration: Direct integration with IIS request pipeline - Process Management: IIS manages application lifecycle

Out-of-Process Model

Configuration:

<aspNetCore processPath="dotnet"
            arguments=".\ConnectSoft.MicroserviceTemplate.Application.dll"
            stdoutLogEnabled="true"
            stdoutLogFile=".\logs\stdout"
            hostingModel="outofprocess" />

Characteristics: - Compatibility: Matches Docker/Kestrel behavior - Isolation: Separate process from IIS - Debugging: Easier to debug (separate process) - Legacy: Used for compatibility with older deployments

IIS Integration

Auto-Detection:

// IIS integration is auto-detected when running under IIS
// No explicit configuration required in .NET 6+

Manual Configuration (if needed):

webBuilder.UseIISIntegration();

Enables: - Header forwarding (X-Forwarded-For, X-Forwarded-Proto) - Port resolution from IIS - Graceful shutdown support

Deployment

Publish to IIS:

# Publish application
dotnet publish -c Release -o C:\inetpub\wwwroot\MyMicroservice

# IIS Configuration
# - Create Application Pool (No Managed Code)
# - Create Application pointing to published folder
# - Configure bindings (HTTP/HTTPS)

Configuration

Environment Variables:

<aspNetCore>
  <environmentVariables>
    <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
    <environmentVariable name="ASPNETCORE_URLS" value="http://localhost:5000" />
  </environmentVariables>
</aspNetCore>

Connection Strings:

Configure via IIS Manager or web.config:

<connectionStrings>
  <add name="DefaultConnection" connectionString="Server=...;Database=...;" />
</connectionStrings>

Use Cases

  • Windows Server deployments
  • Enterprise on-premises hosting
  • Organizations with existing IIS infrastructure
  • Windows-specific integrations

Advantages

  • ✅ Enterprise-grade process management
  • ✅ Integrated Windows authentication
  • ✅ Built-in SSL termination
  • ✅ Application pool isolation
  • ✅ Health monitoring and recycling

Disadvantages

  • ❌ Windows-only
  • ❌ Requires IIS configuration
  • ❌ Additional infrastructure overhead
  • ❌ Licensing costs (Windows Server)

Docker Container Hosting

Overview

Docker Container hosting packages the application in a container image that can run on any Docker-compatible host.

See Containerization for detailed documentation.

Characteristics

  • Portability: Run anywhere Docker is supported
  • Isolation: Application and dependencies packaged together
  • Orchestration: Ready for Kubernetes, Docker Swarm, etc.
  • Consistency: Same environment across dev, staging, production

Configuration

Dockerfile:

FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
WORKDIR /app
EXPOSE 8081
EXPOSE 7279

FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
# ... build stages ...

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ConnectSoft.MicroserviceTemplate.Application.dll"]

Environment-Specific Configuration:

// appsettings.Docker.json
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://+:8081"
      },
      "Https": {
        "Url": "https://+:7279"
      }
    }
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=sql,1433;Database=MyDb;..."
  }
}

Environment Detection

// Container detection
if (Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true")
{
    // Container-specific logic
}

// Environment variable
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Docker"

Running

Docker Compose:

docker-compose up -d

Docker Run:

docker run -p 8081:8081 \
  -e ASPNETCORE_ENVIRONMENT=Docker \
  connectsoft.microservicetemplate.application:latest

Use Cases

  • Containerized deployments
  • Kubernetes base
  • Cloud container services (Azure Container Instances, AWS ECS)
  • Development environment consistency
  • CI/CD pipelines

Advantages

  • ✅ Portability across environments
  • ✅ Consistent runtime environment
  • ✅ Easy scaling and orchestration
  • ✅ Isolation and security
  • ✅ Version control for deployments

Disadvantages

  • ❌ Requires container runtime
  • ❌ Additional complexity in container management
  • ❌ Image size considerations
  • ❌ Network configuration complexity

Linux systemd Hosting

Overview

Linux systemd hosting runs the application as a systemd service on Linux servers, typically behind an Nginx reverse proxy.

systemd Service File

Service File (/etc/systemd/system/connectsoft-microservice.service):

[Unit]
Description=ConnectSoft Microservice Template
After=network.target

[Service]
Type=notify
WorkingDirectory=/opt/connectsoft/microservice
ExecStart=/usr/bin/dotnet /opt/connectsoft/microservice/ConnectSoft.MicroserviceTemplate.Application.dll
Restart=always
RestartSec=10
SyslogIdentifier=connectsoft-microservice
User=dotnet
Group=dotnet
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=ASPNETCORE_URLS=http://localhost:5000

# Resource limits
LimitNOFILE=65536
LimitNPROC=4096

# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/connectsoft/microservice

[Install]
WantedBy=multi-user.target

Deployment Steps

1. Publish Application:

dotnet publish -c Release -o /opt/connectsoft/microservice

2. Create systemd User (if needed):

sudo useradd -r -s /bin/false dotnet
sudo chown -R dotnet:dotnet /opt/connectsoft/microservice

3. Install Service:

sudo cp connectsoft-microservice.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable connectsoft-microservice
sudo systemctl start connectsoft-microservice

4. Verify Status:

sudo systemctl status connectsoft-microservice

5. View Logs:

sudo journalctl -u connectsoft-microservice -f

Nginx Reverse Proxy

Nginx Configuration (/etc/nginx/sites-available/microservice):

server {
    listen 80;
    server_name microservice.example.com;

    location / {
        proxy_pass         http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
        proxy_read_timeout 300s;
        proxy_connect_timeout 75s;
    }

    # Health check endpoint (bypass proxy)
    location /health {
        proxy_pass http://localhost:5000/health;
        access_log off;
    }
}

Enable Site:

sudo ln -s /etc/nginx/sites-available/microservice /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Configuration

Application Configuration:

// appsettings.Production.json
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      }
    }
  }
}

Forwarded Headers:

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | 
                               ForwardedHeaders.XForwardedProto |
                               ForwardedHeaders.XForwardedHost;
    options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("127.0.0.1"), 8));
});

Use Cases

  • Linux server deployments
  • Traditional VPS hosting
  • On-premises Linux infrastructure
  • Cost-effective hosting solutions

Advantages

  • ✅ Cost-effective (Linux servers)
  • ✅ Full control over infrastructure
  • ✅ systemd process management
  • ✅ Nginx performance and features
  • ✅ Security hardening options

Disadvantages

  • ❌ Manual infrastructure management
  • ❌ Requires Linux expertise
  • ❌ No automatic scaling
  • ❌ Manual SSL certificate management

Azure App Service Hosting

Overview

Azure App Service is a fully managed platform-as-a-service (PaaS) for hosting web applications in Azure.

Deployment Options

Method Tool Artifact Use Case
ZIP Deploy Azure CLI, Portal .zip archive Quick deployments
Docker Container Registry Docker image Containerized apps
GitHub Actions Azure Deploy Action Build artifact CI/CD integration
Azure DevOps Azure Web App Task Build artifact Enterprise CI/CD
VS Code Extension Azure App Service Local publish Development

Configuration

Required App Service Settings:

Setting Value Purpose
ASPNETCORE_ENVIRONMENT Production Environment name
WEBSITES_PORT 5000 Port Kestrel listens on
DOTNET_RUNNING_IN_CONTAINER false Container detection (if not using containers)
APPINSIGHTS_INSTRUMENTATIONKEY ... Application Insights integration
WEBSITES_ENABLE_APP_SERVICE_STORAGE false Disable shared storage

Connection Strings:

Configure via App Service Configuration:

ConnectionStrings__DefaultConnection = Server=tcp:...database.windows.net,1433;Database=...;User ID=...;Password=...;Encrypt=true;TrustServerCertificate=false;Connection Timeout=30;
ConnectionStrings__Redis = ...redis.cache.windows.net:6380,password=...,ssl=True,abortConnect=False

ZIP Deploy

Publish and Deploy:

# Publish application
dotnet publish -c Release -o ./publish

# Create ZIP archive
cd publish
zip -r ../app.zip .

# Deploy via Azure CLI
az webapp deployment source config-zip \
  --resource-group MyResourceGroup \
  --name MyAppService \
  --src app.zip

Deploy via Portal:

  1. Navigate to App Service → Deployment Center
  2. Select "Local Git" or "ZIP Deploy"
  3. Upload ZIP file or configure Git repository

Container Deploy

Deploy Docker Image:

# Build and push to Azure Container Registry
az acr build --registry myregistry \
  --image connectsoft-microservice:latest \
  --file Dockerfile .

# Configure App Service to use container
az webapp config container set \
  --resource-group MyResourceGroup \
  --name MyAppService \
  --docker-custom-image-name myregistry.azurecr.io/connectsoft-microservice:latest \
  --docker-registry-server-url https://myregistry.azurecr.io

HTTPS and SSL

Automatic HTTPS: - Azure App Service provides automatic HTTPS certificates via Let's Encrypt - Custom domains automatically get SSL certificates - HTTPS redirection can be configured

Custom Certificates:

# Upload custom certificate
az webapp config ssl upload \
  --resource-group MyResourceGroup \
  --name MyAppService \
  --certificate-file certificate.pfx \
  --certificate-password password

Scaling

Manual Scaling:

az appservice plan update \
  --resource-group MyResourceGroup \
  --name MyAppServicePlan \
  --number-of-workers 3

Auto-Scaling:

Configure via Azure Portal or Azure CLI:

az monitor autoscale create \
  --resource-group MyResourceGroup \
  --resource /subscriptions/.../Microsoft.Web/serverfarms/MyAppServicePlan \
  --name MyAutoScale \
  --min-count 1 \
  --max-count 10 \
  --count 2

Use Cases

  • Managed cloud hosting
  • Azure ecosystem integration
  • Quick deployments
  • Automatic scaling requirements
  • Managed SSL certificates

Advantages

  • ✅ Fully managed platform
  • ✅ Automatic scaling
  • ✅ Built-in SSL certificates
  • ✅ Azure integration (Key Vault, Application Insights)
  • ✅ Deployment slots for blue-green deployments
  • ✅ Automatic backups

Disadvantages

  • ❌ Platform-specific (Azure only)
  • ❌ Less control over infrastructure
  • ❌ Potential vendor lock-in
  • ❌ Cost considerations at scale

Kubernetes Hosting

Overview

Kubernetes hosting runs containerized applications in a Kubernetes cluster with orchestration, scaling, and service discovery.

See Kubernetes for detailed documentation.

Characteristics

  • Orchestration: Automatic container management and scaling
  • Service Discovery: Built-in DNS-based service discovery
  • Load Balancing: Automatic load balancing across pods
  • High Availability: Pod replication and health checks
  • Self-Healing: Automatic restart of failed containers

Deployment

Deployment Manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: connectsoft-microservice
  labels:
    app: connectsoft-microservice
spec:
  replicas: 3
  selector:
    matchLabels:
      app: connectsoft-microservice
  template:
    metadata:
      labels:
        app: connectsoft-microservice
    spec:
      containers:
      - name: microservice
        image: myregistry.azurecr.io/connectsoft-microservice:1.0.0
        ports:
        - containerPort: 8081
          name: http
        - containerPort: 7279
          name: https
        env:
        - name: ASPNETCORE_ENVIRONMENT
          value: "Production"
        - name: ASPNETCORE_URLS
          value: "http://+:8081;https://+:7279"
        livenessProbe:
          httpGet:
            path: /live
            port: 8081
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8081
          initialDelaySeconds: 10
          periodSeconds: 5
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"

Service Manifest:

apiVersion: v1
kind: Service
metadata:
  name: connectsoft-microservice
spec:
  type: ClusterIP
  selector:
    app: connectsoft-microservice
  ports:
  - port: 80
    targetPort: 8081
    protocol: TCP
    name: http
  - port: 443
    targetPort: 7279
    protocol: TCP
    name: https

Ingress Manifest:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: connectsoft-microservice
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - microservice.example.com
    secretName: microservice-tls
  rules:
  - host: microservice.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: connectsoft-microservice
            port:
              number: 80

Configuration

ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: microservice-config
data:
  appsettings.json: |
    {
      "Kestrel": {
        "Endpoints": {
          "Http": {
            "Url": "http://+:8081"
          }
        }
      }
    }

Secrets:

apiVersion: v1
kind: Secret
metadata:
  name: microservice-secrets
type: Opaque
stringData:
  ConnectionStrings__DefaultConnection: "Server=...;Database=...;..."

Use in Deployment:

spec:
  template:
    spec:
      containers:
      - name: microservice
        envFrom:
        - configMapRef:
            name: microservice-config
        - secretRef:
            name: microservice-secrets

Health Checks

Liveness Probe:

livenessProbe:
  httpGet:
    path: /live
    port: 8081
  initialDelaySeconds: 30
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3

Readiness Probe:

readinessProbe:
  httpGet:
    path: /ready
    port: 8081
  initialDelaySeconds: 10
  periodSeconds: 5
  timeoutSeconds: 3
  failureThreshold: 3

Startup Probe:

startupProbe:
  httpGet:
    path: /health
    port: 8081
  initialDelaySeconds: 0
  periodSeconds: 10
  timeoutSeconds: 3
  failureThreshold: 30  # Allow up to 5 minutes for startup

Scaling

Horizontal Pod Autoscaler:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: connectsoft-microservice-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: connectsoft-microservice
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Use Cases

  • Container orchestration at scale
  • Multi-cloud deployments
  • High availability requirements
  • Complex microservice architectures
  • Self-hosted Kubernetes clusters

Advantages

  • ✅ Automatic scaling and orchestration
  • ✅ High availability and self-healing
  • ✅ Service discovery and load balancing
  • ✅ Cloud-agnostic (runs anywhere)
  • ✅ Rich ecosystem and tooling

Disadvantages

  • ❌ Complex infrastructure management
  • ❌ Requires Kubernetes expertise
  • ❌ Operational overhead
  • ❌ Learning curve

Azure Functions Hosting

Overview

Azure Functions provides serverless hosting for event-driven workloads.

See Azure Functions for detailed documentation.

Characteristics

  • Serverless: No infrastructure management
  • Event-Driven: Triggered by events (HTTP, timer, queue, etc.)
  • Pay-per-Use: Cost based on execution time and invocations
  • Automatic Scaling: Scales automatically based on demand
  • Integration: Built-in integration with Azure services

Configuration

Function App Settings:

FUNCTIONS_WORKER_RUNTIME=dotnet-isolated
FUNCTIONS_EXTENSION_VERSION=~4
ASPNETCORE_ENVIRONMENT=Production

Use Cases

  • Event-driven workloads
  • Scheduled tasks
  • API endpoints with variable traffic
  • Integration with Azure services
  • Cost-effective for low-traffic scenarios

Advantages

  • ✅ No infrastructure management
  • ✅ Automatic scaling
  • ✅ Pay-per-use pricing
  • ✅ Azure service integration
  • ✅ Event-driven architecture

Disadvantages

  • ❌ Cold start latency
  • ❌ Execution time limits
  • ❌ Platform-specific (Azure)
  • ❌ Less control over runtime

Azure Container Apps

Overview

Azure Container Apps is a serverless container platform for running containerized applications.

Characteristics

  • Serverless Containers: Container-based serverless platform
  • Automatic Scaling: Scales containers based on HTTP traffic or events
  • Kubernetes-Based: Built on Kubernetes but abstracts complexity
  • Dapr Integration: Built-in Dapr support for microservices

Configuration

Container App Manifest:

apiVersion: 2022-03-01
type: Microsoft.App/containerApps
properties:
  managedEnvironmentId: /subscriptions/.../managedEnvironments/myenv
  configuration:
    ingress:
      external: true
      targetPort: 8081
      transport: http
      allowInsecure: false
  template:
    containers:
    - name: microservice
      image: myregistry.azurecr.io/connectsoft-microservice:1.0.0
      env:
      - name: ASPNETCORE_ENVIRONMENT
        value: Production
      resources:
        cpu: 0.5
        memory: 1.0Gi
    scale:
      minReplicas: 1
      maxReplicas: 10
      rules:
      - name: http-scale
        http:
          metadata:
            concurrentRequests: 100

Use Cases

  • Container-based serverless workloads
  • Microservices with variable traffic
  • Dapr-based architectures
  • Kubernetes-like features without Kubernetes complexity

Advantages

  • ✅ Serverless container platform
  • ✅ Automatic scaling
  • ✅ Built-in Dapr support
  • ✅ Kubernetes-based without complexity
  • ✅ Pay-per-use pricing

Disadvantages

  • ❌ Azure-only platform
  • ❌ Less control than Kubernetes
  • ❌ Newer platform (limited ecosystem)

Hosting Model Comparison

Feature Matrix

Feature Kestrel IIS Docker Linux systemd Azure App Service Kubernetes Azure Functions
Platform Cross-platform Windows Any Linux Azure Any Azure
Process Management Manual IIS Container runtime systemd Managed Kubernetes Managed
Scaling Manual Manual Orchestrator Manual Automatic Automatic Automatic
SSL/TLS Manual Built-in Manual Nginx Automatic Ingress Automatic
High Availability Manual IIS Orchestrator Manual Built-in Built-in Built-in
Cost Low Medium Low Low Medium-High Medium Pay-per-use
Complexity Low Medium Medium Medium Low High Low
Portability High Low High Low Low High Low

Selection Guide

Choose Kestrel Standalone When: - Local development - Simple deployments - Testing environments - Container base (Docker/Kubernetes)

Choose IIS When: - Windows Server infrastructure - Enterprise Windows environments - Windows-specific integrations - Existing IIS investments

Choose Docker When: - Containerized deployments - Kubernetes base - Cloud container services - Development environment consistency

Choose Linux systemd When: - Linux server deployments - Cost-effective hosting - Full infrastructure control - Traditional VPS hosting

Choose Azure App Service When: - Managed Azure hosting - Quick deployments - Automatic scaling needs - Azure ecosystem integration

Choose Kubernetes When: - Container orchestration at scale - Multi-cloud deployments - High availability requirements - Complex microservice architectures

Choose Azure Functions When: - Event-driven workloads - Variable traffic patterns - Serverless architecture - Cost optimization for low traffic

Choose Azure Container Apps When: - Container-based serverless - Dapr integration - Kubernetes-like features without complexity - Azure-native container hosting

Configuration Adaptations

Environment-Specific Configuration

appsettings.json (Base):

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      }
    }
  }
}

appsettings.Docker.json (Docker):

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://+:8081"
      }
    }
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=sql,1433;..."
  }
}

appsettings.Production.json (Production):

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      }
    }
  }
}

Forwarded Headers Configuration

Required for Reverse Proxies:

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | 
                               ForwardedHeaders.XForwardedProto |
                               ForwardedHeaders.XForwardedHost;

    // IIS
    options.KnownProxies.Add(IPAddress.Parse("127.0.0.1"));

    // Docker
    options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("172.16.0.0"), 12));

    // Kubernetes
    options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8));
});

Port Configuration

Environment Variable Override:

# Docker
ASPNETCORE_URLS=http://+:8081;https://+:7279

# Azure App Service
WEBSITES_PORT=5000

# Kubernetes
ASPNETCORE_URLS=http://+:8081

# Linux systemd
ASPNETCORE_URLS=http://localhost:5000

Migration Between Hosting Models

Migration Paths

IIS to Docker: 1. Containerize application (Dockerfile) 2. Test in Docker environment 3. Deploy to container registry 4. Update deployment pipeline 5. Deploy to container host

Docker to Kubernetes: 1. Create Kubernetes manifests 2. Configure ConfigMaps and Secrets 3. Set up ingress controller 4. Deploy to Kubernetes cluster 5. Configure monitoring and scaling

Kestrel to Azure App Service: 1. Publish application 2. Create App Service plan 3. Create App Service 4. Configure settings and connection strings 5. Deploy application

Code Compatibility

Hosting-Agnostic Code:

// ✅ GOOD - Works in all hosting models
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Service registration (hosting-agnostic)
        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app)
    {
        // Middleware pipeline (hosting-agnostic)
        app.UseRouting();
        app.UseEndpoints(endpoints => endpoints.MapControllers());
    }
}

Hosting-Specific Configuration:

// ✅ GOOD - Environment-specific configuration
if (Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true")
{
    // Container-specific setup
}

if (Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME") != null)
{
    // Azure App Service-specific setup
}

Best Practices

Do's

  1. Use Configuration Files for Hosting Differences

    // ✅ GOOD - Environment-specific configuration
    // appsettings.Docker.json
    {
      "Kestrel": {
        "Endpoints": {
          "Http": { "Url": "http://+:8081" }
        }
      }
    }
    

  2. Enable Forwarded Headers for Reverse Proxies

    // ✅ GOOD - Works with all reverse proxies
    application.UseForwardedHeaders();
    

  3. Use Environment Variables for Secrets

    # ✅ GOOD - Secrets via environment variables
    ConnectionStrings__DefaultConnection=Server=...;...
    

  4. Configure Health Checks

    // ✅ GOOD - Works in all hosting models
    services.AddHealthChecks()
        .AddCheck("self", () => HealthCheckResult.Healthy());
    

  5. Use Standard Ports or Configuration

    // ✅ GOOD - Configurable via appsettings.json
    "Kestrel": {
      "Endpoints": {
        "Http": { "Url": "http://+:8081" }
      }
    }
    

Don'ts

  1. Don't Hardcode Hosting-Specific Values

    // ❌ BAD - Hardcoded port
    webBuilder.UseUrls("http://localhost:5000");
    
    // ✅ GOOD - Configuration-driven
    // Use appsettings.json
    

  2. Don't Assume Process Management

    // ❌ BAD - Assumes manual process management
    // No graceful shutdown handling
    
    // ✅ GOOD - Use IHostApplicationLifetime
    hostApplicationLifetime.ApplicationStopping.Register(() => {
        // Cleanup logic
    });
    

  3. Don't Skip Forwarded Headers

    // ❌ BAD - Won't work behind reverse proxy
    // Missing UseForwardedHeaders()
    
    // ✅ GOOD - Always include
    application.UseForwardedHeaders();
    

  4. Don't Use Hosting-Specific APIs Directly

    // ❌ BAD - IIS-specific
    HttpContext.Current.Request.Url
    
    // ✅ GOOD - Hosting-agnostic
    HttpContext.Request.Path
    

Troubleshooting

Issue: Application Not Starting

Symptoms: Application fails to start in specific hosting model.

Solutions: 1. Check environment variables are set correctly 2. Verify configuration files are present 3. Review logs for specific errors 4. Check port binding and availability 5. Verify dependencies are accessible

Issue: Reverse Proxy Not Working

Symptoms: Headers not forwarded correctly.

Solutions: 1. Verify UseForwardedHeaders() is called 2. Check KnownProxies and KnownNetworks configuration 3. Verify reverse proxy is setting correct headers 4. Check network configuration

Issue: Port Conflicts

Symptoms: Port already in use errors.

Solutions: 1. Check port configuration in appsettings.json 2. Verify environment variable overrides 3. Check for other services using the port 4. Use dynamic port allocation where possible

Issue: Health Checks Failing

Symptoms: Health checks fail in orchestrator.

Solutions: 1. Verify health check endpoints are configured 2. Check health check paths match configuration 3. Verify startup probe timing (Kubernetes) 4. Review application startup logs

Summary

Hosting models in the ConnectSoft Microservice Template provide:

  • Hosting-Agnostic Code: Same codebase runs across all models
  • Flexible Deployment: Support for multiple deployment targets
  • Environment Configuration: Hosting-specific settings via configuration
  • Consistent Behavior: Unified behavior across hosting models
  • Migration Support: Easy migration between hosting models
  • Best Practices: Security and performance optimizations for each model

By following these patterns, teams can:

  • Choose Appropriately: Select hosting model based on requirements
  • Deploy Flexibly: Deploy to different environments as needed
  • Migrate Easily: Move between hosting models without code changes
  • Maintain Consistency: Same application behavior across models
  • Optimize Costs: Select hosting models based on cost and performance
  • Scale Effectively: Leverage hosting model features for scaling

The hosting model abstraction ensures that ConnectSoft microservices can run consistently across any hosting environment while taking advantage of platform-specific features when available.