# Docker ASP.NET Core SSL Certificate Configuration (Linux & Windows Containers)

> How to configure HTTPS and mount PFX SSL certificates in Dockerized ASP.NET Core applications on Linux and Windows Server containers.

- Canonical URL: <https://carlossura.com/blog/docker-aspnetcore-ssl-certificate/>
- Author: Carlos Sura
- Published: 2020-07-24
- Updated: 2026-10-20
- Tags: docker, windows, aspnetcore, ssl, dotnet

Running **ASP.NET Core** applications over HTTPS inside Docker requires mounting a PKCS#12 (`.pfx`) certificate into the container and passing Kestrel certificate environment variables. On Windows Server Nano Server containers, this often triggers cryptographic key permission errors if the default container user cannot read the imported certificate store.

Below is the step-by-step configuration for both local development and Windows/Linux container deployments.

---

## Generate a Local Development Certificate (Optional)

If you do not already have a production `.pfx` certificate issued by your CA, generate and trust a self-signed development certificate using the .NET CLI:

```powershell
dotnet dev-certs https -ep $env:USERPROFILE\.aspnet\https\aspnetapp.pfx -p "YourStrongPassword"
dotnet dev-certs https --trust
```

---

## Run the ASP.NET Core Container on Linux / macOS

On Linux hosts, mount the directory containing your `.pfx` file into `/https/` inside the container and configure Kestrel via environment variables:

```bash
docker pull mcr.microsoft.com/dotnet/samples:aspnetapp

docker run --rm -it \
  -p 8000:80 \
  -p 8001:443 \
  -e ASPNETCORE_URLS="https://+;http://+" \
  -e ASPNETCORE_HTTPS_PORT=8001 \
  -e ASPNETCORE_Kestrel__Certificates__Default__Password="YourStrongPassword" \
  -e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx \
  -v "${HOME}/.aspnet/https:/https/:ro" \
  mcr.microsoft.com/dotnet/samples:aspnetapp
```

---

## Resolving Certificate Permission Errors on Windows Server Containers

When running ASP.NET Core inside **Windows Server / Nano Server** containers (versions after Windows Server 2016), the default runtime account is `ContainerUser` rather than `ContainerAdministrator`. Because Windows imports `.pfx` private keys into the machine key store during Kestrel startup, `ContainerUser` can fail with an `Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Access is denied` error (tracked in [dotnet/dotnet-docker#915](https://github.com/dotnet/dotnet-docker/issues/915)).

To resolve this on Windows containers where Kestrel terminates TLS directly, run the container as `ContainerAdministrator` and bind-mount the host certificate folder:

```powershell
docker run -d `
  -u ContainerAdministrator `
  -p 8000:80 `
  -p 8001:443 `
  -e ASPNETCORE_URLS="https://+;http://+" `
  -e ASPNETCORE_HTTPS_PORT=443 `
  -e ASPNETCORE_Kestrel__Certificates__Default__Password="ssl-password" `
  -e ASPNETCORE_Kestrel__Certificates__Default__Path=C:\https\ssl-certificate.pfx `
  -v C:\path-to-ssl\ssl\https:C:\https `
  [image-name] [container-name]
```

---

## Production Security Best Practices

- **Prefer Reverse Proxy TLS Termination:** In production Kubernetes, Azure Container Apps, or Docker Swarm environments, terminate TLS at an ingress controller or reverse proxy (Nginx, Traefik, Envoy, or Azure Application Gateway) so containers can run as unprivileged non-root users (`USER $APP_UID` on Linux or `ContainerUser` on Windows).
- **Never Bake `.pfx` Files into Images:** Always mount certificates at runtime via read-only volumes or secret mounts (such as Docker Secrets, Kubernetes `tls` Secrets, or Azure Key Vault CSI drivers).

## References

- [Host ASP.NET Core images with Docker over HTTPS — Microsoft Learn](https://learn.microsoft.com/en-us/aspnet/core/security/docker-https)
- [Windows ContainerUser Certificate Permissions Issue — GitHub dotnet-docker #915](https://github.com/dotnet/dotnet-docker/issues/915)
