DEV Community

abdulrahilsheikh
abdulrahilsheikh

Posted on

Fixing HTTPS Certificates in .NET Dev Containers (The Right Way)

Project Directory Structure
Before we dive into the commands, here is what your repository layout looks like, showing where the .NET backend code resides under the server/ folder and where the generated certificate will live:

dotnet_learning/
├── .devcontainer/
│   ├── devcontainer.json
│   └── docker-compose.yml
├── server/                    <-- .NET Backend Project Folder
│   ├── certs/
│   │   └── localhost.pfx      <-- Generated & mounted PFX certificate
│   ├── Controllers/
│   ├── Program.cs
│   └── Server.csproj
├── next_ui/                   <-- Frontend (React/Next.js)
└── README.md
Enter fullscreen mode Exit fullscreen mode

The Problem: Certificates in Isolated Environments

When you spin up a Dev Container, it runs inside an isolated Linux environment (usually Debian or Ubuntu). Your host machine's trusted certificate store isn't automatically shared with the container.

If you try to run the standard .NET certificate command:

dotnet dev-certs https --trust

Enter fullscreen mode Exit fullscreen mode

It might fail or fail to persist outside the container lifecycle, leaving your browser or API clients complaining about untrusted certificates (ERR_CERT_AUTHORITY_INVALID).


Step 1: Clean the Slate (Just in Case)

If you've been messing around with existing certificates and hitting weird errors, start by clearing out any corrupted state:

dotnet dev-certs https --clean

Enter fullscreen mode Exit fullscreen mode

(Note: If you run into a strange Interop.Sys.GetCwdHelper error on macOS/Linux while doing this, it usually means your terminal's current working directory got unlinked. Simply run cd ~ && cd - to reset your shell's path, then try again).


Step 2: Generate and Export a .pfx Certificate

Instead of relying solely on the container's auto-generated store, you can explicitly export a password-protected .pfx file from your host machine that you can mount into your container.

Open your terminal, make sure you are in your project's root folder (workspace root). Run the following command on your host machine to generate the cert and save it inside your project's server/certs/ folder:

dotnet dev-certs https -ep ./server/certs/localhost.pfx -p "Password"

Enter fullscreen mode Exit fullscreen mode
  • -ep ./server/certs/localhost.pfx: Exports the certificate to your project path.
  • -p "Password": Sets a password to protect the private key inside the PFX bundle.

Step 3: Trust the Certificate inside the Container

Right after generating your certificate runn the below command, to make sure your host machine trusts the development certificate so your browser and host tools don't throw security errors:

dotnet dev-certs https --trust

Enter fullscreen mode Exit fullscreen mode

(Note: Depending on your OS—macOS, Windows, or Linux—this will prompt you for your user password or system administrator permissions to install the development certificate into your host's trusted root authority store.)


Step 4: Configure it in your devcontainer.json

To make your container use this certificate automatically, you need to configure two things in your .devcontainer/devcontainer.json:

  1. mounts: To bind-mount the .pfx file from your host into the container's file system (e.g., /certs/localhost.pfx).
  2. containerEnv: To tell Kestrel where to find the certificate using ASP.NET Core environment variables.

Here is how your devcontainer.json should look with the certificate mounts and environment configurations injected:

// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet-postgres
{
    "name": "C# (.NET) and PostgreSQL",
    "dockerComposeFile": "docker-compose.yml",
    "service": "app",
    "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
    "features": {
        "ghcr.io/devcontainers/features/node:2": {
            "nodeGypDependencies": true,
            "version": "lts",
            "npmVersion": "lts",
            "pnpmVersion": "latest",
            "nvmVersion": "latest"
        }
    },
    "mounts": [
        "source=node_modules_vol,target=${containerWorkspaceFolder}/next_ui/node_modules,type=volume",
        // Mount your generated PFX certificate into the container
        "source=${localWorkspaceFolder}/server/certs/localhost.pfx,target=/certs/localhost.pfx,type=bind"
    ],
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-dotnettools.csharp",
                "ms-dotnettools.cs-dev-kit"
            ]
        }
    },
    "postCreateCommand": "sudo chown -R vscode:vscode /workspaces/dotnet_learning/next_ui/node_modules || true",

    // Configure Kestrel to use the mounted certificate via environment variables
    "containerEnv": {
        "ASPNETCORE_Kestrel__Certificates__Default__Path": "/certs/localhost.pfx",
        "ASPNETCORE_Kestrel__Certificates__Default__Password": "Password",
    }
}

Enter fullscreen mode Exit fullscreen mode

Wrapping Up

Handling SSL certificates in Docker containers can be frustrating, but by generating a .pfx file on your host, binding it via mounts, and configuring Kestrel through containerEnv, your .NET app will run smoothly with fully trusted HTTPS inside your Dev Container!

Top comments (0)