HTTPS & Certificates

Add TLS with a development self‑signed certificate or an existing PFX.

Prerequisites: see Certificates section for creating a self‑signed cert.

Full source

File: pwsh/tutorial/examples/7.3-Https.ps1

<#
    Sample Kestrun Server - HTTPS
    Demonstrates adding an HTTPS listener with a development self-signed certificate.
    For production use a proper certificate and secure secret storage.
    FileName: 7.3-Https.ps1
#>

[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')]
param(
    [int]$Port = $env:PORT ?? 5000
)

# (Optional) Configure console logging
New-KrLogger |
    Add-KrSinkConsole |
    Register-KrLogger -Name 'console' -SetAsDefault | Out-Null

# Ensure a development certificate exists (self-signed) - dev ONLY
$certPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath 'devcert.pfx'
$pw = ConvertTo-SecureString -String 'P@ssw0rd!' -AsPlainText -Force
if (-not (Test-Path $certPath)) {
    Write-Host 'Creating development self-signed certificate devcert.pfx'
    New-KrSelfSignedCertificate -DnsName 'localhost' -Exportable -ValidDays 30 |
        Export-KrCertificate -FilePath $certPath -Format Pfx -IncludePrivateKey -Password $pw | Out-Null
}

$port2 = $Port + 1
# Create a new Kestrun server
New-KrServer -Name 'Endpoints Https'


# HTTP listener (optional)
$httpEndpoints = Add-KrEndpoint -Port $Port -PassThru

# HTTPS listener
$httpsEndpoints = Add-KrEndpoint -Port $port2 -CertPath $certPath -CertPassword $pw -PassThru


# Enable configuration
Enable-KrConfiguration

# Secure route
Add-KrMapRoute -Verbs Get -Pattern '/secure' -Endpoints $httpsEndpoints -ScriptBlock {
    Write-KrLog -Level Information -Message 'Secure endpoint invoked'
    Write-KrTextResponse -InputObject 'Secure hello' -StatusCode 200
}

# Unsecure route (available on HTTP listener)
Add-KrMapRoute -Verbs Get -Pattern '/unsecure' -Endpoints $httpEndpoints -ScriptBlock {
    Write-KrLog -Level Information -Message 'Unsecure endpoint invoked'
    Write-KrTextResponse -InputObject 'Unsecure hello' -StatusCode 200
}

Write-KrLog -Level Information -Message 'HTTP listener active on {Port}' -Values $Port
Write-KrLog -Level Information -Message 'HTTPS listener active on {Port2}' -Values $port2

# Start the server
Start-KrServer -CloseLogsOnExit

Step-by-step

  1. Ensure / create PFX (dev only) with New-KrSelfSignedCertificate.
    • For localhost, include localhost, 127.0.0.1, and ::1.
    • For RSA TLS server certs, prefer -KeyUsage DigitalSignature,KeyEncipherment.
    • For ECDSA TLS server certs, prefer -KeyUsage DigitalSignature.
  2. Add HTTP listener (optional) and HTTPS listener with -CertPath/-CertPassword.
  3. Capture the listener endpoint specs via Add-KrEndpoint -PassThru.
  4. Enable configuration.
  5. Map /secure route with -Endpoints parameter to bind to HTTPS listener only.
  6. Map /unsecure route with -Endpoints parameter to bind to HTTP listener only.
  7. Start server.
  8. (Optional) Tune via Set-KrServerHttpsOptions for protocols or client certificate mode.

Endpoint-specific routing

The -Endpoints parameter in Add-KrMapRoute allows you to bind routes to specific listeners:

# Capture endpoint specs directly from the listener definitions
$httpEndpoints = Add-KrEndpoint -Port 5000 -PassThru
$httpsEndpoints = Add-KrEndpoint -Port 5001 -CertPath .\devcert.pfx -CertPassword $pw -PassThru

# Secure route - only available on HTTPS listener
Add-KrMapRoute -Verbs Get -Pattern '/secure' -Endpoints $httpsEndpoints -ScriptBlock {
    Write-KrTextResponse -InputObject 'Secure hello' -StatusCode 200
}

# Unsecure route - only available on HTTP listener
Add-KrMapRoute -Verbs Get -Pattern '/unsecure' -Endpoints $httpEndpoints -ScriptBlock {
    Write-KrTextResponse -InputObject 'Unsecure hello' -StatusCode 200
}

Key points:

  • Add-KrEndpoint -PassThru returns endpoint specs that Add-KrMapRoute -Endpoints accepts directly
  • Returned values may include localhost and loopback IP forms so route restrictions stay aligned with listener binding
  • Without -Endpoints, routes are available on all listeners
  • Use this to enforce HTTPS-only routes or separate HTTP/HTTPS functionality

Try it

curl -k https://127.0.0.1:5001/secure

Invoke-WebRequest -Uri https://127.0.0.1:5001/secure -SkipCertificateCheck | Select-Object -ExpandProperty Content

-k skips trust validation for an untrusted self‑signed cert.

For Chromium-family browsers on Windows, trusting a local dev CA is usually more reliable than trusting only a raw self-signed localhost leaf.

Troubleshooting

Symptom Cause Fix
curl cert warning Self-signed cert Use -k or trust cert locally
HTTPS listener fails Wrong password Re-enter secure string / recreate PFX
Route works on HTTP not HTTPS Only added HTTP listener Add second listener before enabling config
Route not accessible on expected endpoint Wrong -Endpoints parameter Prefer Add-KrEndpoint -PassThru to avoid mismatches
Route accessible on wrong protocol Missing -Endpoints parameter Add -Endpoints to bind to specific listener
Edge / Brave reject localhost cert Chromium trust behavior differs from Firefox Prefer a dev CA + localhost leaf workflow on Windows

See also: Certificates · Logging


References

Previous / Next

Previous: Multiple Listeners Next: Named Pipes