Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating certificate for local dev environment in WSL2

Having difficulty getting a certificate installed in a local development environment that is isolated to WSL2. I've done the exact same steps in macOS and Linux, and have had zero issues.

The steps are the following:

# Download and install mkcert
if [[ `uname` = "Darwin" ]] then
    brew install mkcert
    brew install nss
else
    curl -Lo mkcert https://github.com/FiloSottile/mkcert/releases/download/v1.4.3/mkcert-v1.4.3-linux-amd64 && \
        sudo install mkcert /usr/local/bin/
fi

# Installing tls certificate
mkcert -install

# Installing tls certificate
mkcert localhost 127.0.0.1 ::1

# Installing cert-manager locally
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.2.0/cert-manager.yaml

# Add the certificates to secrets
kubectl create secret tls tls-localhost-dev --key=localhost+2-key.pem --cert=localhost+2.pem -n dev

# Create the tls service that will attach to ingress-nginx
kubectl apply -f k8s/dev/tls.yaml
# k8s/dev/tls.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-dev-issuer
  namespace: cert-manager
spec:
  ca:
    secretName: tls-localhost-dev
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: letsencrypt-dev-certificate
  namespace: cert-manager
spec:
  secretName: tls-localhost-dev
  dnsNames:
    - localhost
  issuerRef:
    name: letsencrypt-dev-issuer
    kind: Issuer
# k8s/dev/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-dev"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  name: ingress-dev
  namespace: dev
spec:
  tls:
    - hosts:
        - localhost
      secretName: tls-localhost-dev
  rules:
    - host: localhost
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: client-cluster-ip-service-dev
                port:
                  number: 3000

After all of that, you can navigate to localhost and see it has a certificate... on Linux and macOS.

In WSL2, I can't get the certificates working even though there are no errors except for when I describe some of the resources:

$ kubectl describe issuer letsencrypt-dev-issuer -n cert-manager
Name:         letsencrypt-dev-issuer
Namespace:    cert-manager
Labels:       <none>
Annotations:  <none>
API Version:  cert-manager.io/v1
Kind:         Issuer
Metadata:
  Creation Timestamp:  2021-03-04T01:33:06Z
  Generation:          1
  Managed Fields:
    API Version:  cert-manager.io/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:status:
        .:
        f:conditions:
    Manager:      controller
    Operation:    Update
    Time:         2021-03-04T01:33:06Z
    API Version:  cert-manager.io/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .:
          f:kubectl.kubernetes.io/last-applied-configuration:
      f:spec:
        .:
        f:ca:
          .:
          f:secretName:
    Manager:         kubectl-client-side-apply
    Operation:       Update
    Time:            2021-03-04T01:33:06Z
  Resource Version:  800
  Self Link:         /apis/cert-manager.io/v1/namespaces/cert-manager/issuers/letsencrypt-dev-issuer
  UID:               ebad4607-afe7-480a-8107-1c27fa8c2e8d
Spec:
  Ca:
    Secret Name:  tls-localhost-dev
Status:
  Conditions:
    Last Transition Time:  2021-03-04T01:33:06Z
    Message:               Error getting keypair for CA issuer: secret "tls-localhost-dev" not found
    Reason:                ErrGetKeyPair
    Status:                False
    Type:                  Ready
Events:
  Type     Reason         Age                  From          Message
  ----     ------         ----                 ----          -------
  Warning  ErrGetKeyPair  4m30s (x9 over 19m)  cert-manager  Error getting keypair for CA issuer: secret "tls-localhost-dev" not found
  Warning  ErrInitIssuer  4m30s (x9 over 19m)  cert-manager  Error initializing issuer: secret "tls-localhost-dev" not found
$ kubectl describe certificate tls-localhost-dev -n dev
Name:         tls-localhost-dev
Namespace:    dev
Labels:       app.kubernetes.io/managed-by=skaffold
              skaffold.dev/run-id=a853f8d6-f192-465c-a43f-4369d5c5a636
Annotations:  <none>
API Version:  cert-manager.io/v1
Kind:         Certificate
Metadata:
  Creation Timestamp:  2021-03-04T01:38:18Z
  Generation:          1
  Managed Fields:
    API Version:  cert-manager.io/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:labels:
          .:
          f:app.kubernetes.io/managed-by:
          f:skaffold.dev/run-id:
        f:ownerReferences:
          .:
          k:{"uid":"d596b83b-95eb-46f6-941f-0f6cef0a76d8"}:
            .:
            f:apiVersion:
            f:blockOwnerDeletion:
            f:controller:
            f:kind:
            f:name:
            f:uid:
      f:spec:
        .:
        f:dnsNames:
        f:issuerRef:
          .:
          f:group:
          f:kind:
          f:name:
        f:secretName:
        f:usages:
      f:status:
        .:
        f:conditions:
        f:nextPrivateKeySecretName:
        f:notAfter:
        f:notBefore:
        f:renewalTime:
    Manager:    controller
    Operation:  Update
    Time:       2021-03-04T01:38:18Z
  Owner References:
    API Version:           networking.k8s.io/v1beta1
    Block Owner Deletion:  true
    Controller:            true
    Kind:                  Ingress
    Name:                  ingress-dev
    UID:                   d596b83b-95eb-46f6-941f-0f6cef0a76d8
  Resource Version:        1312
  Self Link:               /apis/cert-manager.io/v1/namespaces/dev/certificates/tls-localhost-dev
  UID:                     12d0f503-928b-4aaf-b691-3e6ed6e76e39
Spec:
  Dns Names:
    localhost
  Issuer Ref:
    Group:      cert-manager.io
    Kind:       ClusterIssuer
    Name:       letsencrypt-dev
  Secret Name:  tls-localhost-dev
  Usages:
    digital signature
    key encipherment
Status:
  Conditions:
    Last Transition Time:        2021-03-04T01:38:18Z
    Message:                     Issuing certificate as Secret was previously issued by Issuer.cert-manager.io/
    Reason:                      IncorrectIssuer
    Status:                      True
    Type:                        Issuing
    Last Transition Time:        2021-03-04T01:38:18Z
    Message:                     Existing issued Secret is not up to date for spec: [spec.ipAddresses]
    Reason:                      SecretMismatch
    Status:                      False
    Type:                        Ready
  Next Private Key Secret Name:  tls-localhost-dev-zqwpw
  Not After:                     2023-06-04T00:32:33Z
  Not Before:                    2021-03-04T01:32:33Z
  Renewal Time:                  2023-05-05T00:32:33Z
Events:
  Type    Reason     Age   From          Message
  ----    ------     ----  ----          -------
  Normal  Issuing    15m   cert-manager  Issuing certificate as Secret was previously issued by Issuer.cert-manager.io/
  Normal  Reused     15m   cert-manager  Reusing private key stored in existing Secret resource "tls-localhost-dev"
  Normal  Requested  15m   cert-manager  Created new CertificateRequest resource "tls-localhost-dev-4xrv9"
$ kubectl describe secret tls-localhost-dev -n dev
Name:         tls-localhost-dev
Namespace:    dev
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1521 bytes
tls.key:  1708 bytes

Basically says something isn't there that is quite clearly there.

Any suggestions for how to resolve this?

like image 996
cjones Avatar asked Oct 29 '25 04:10

cjones


1 Answers

Ok, got this figured out with some help:

  • https://github.com/Microsoft/WSL/issues/3161#issuecomment-451863149
  • https://ddev.readthedocs.io/en/latest/#installation-or-upgrade-windows-wsl2
  • https://www.haveiplayedbowie.today/blog/posts/secure-localhost-with-mkcert/

This is what worked for my use case. Granted, I didn't test it without installing mkcert into WSL, so that step may not be necessary:

  1. Use choco to install mkcert: choco install -y mkcert
  2. In Windows, mkcert -install
  3. WSL install mkcert (again, not 100% sure this is necessary):
    curl -Lo mkcert https://github.com/FiloSottile/mkcert/releases/download/v1.4.3/mkcert-v1.4.3-linux-amd64 &&
       sudo install mkcert /usr/local/bin/
    
  4. In WSL, mkcert -install (again, not 100% sure this is necessary)
  5. In Windows:
    mkcert localhost 127.0.0.1 ::1
    
  6. This will generate them in your C:\Users\<user>\ directory by default
  7. Copy them into WSL, which for my use case is the root of my project
  8. Then for my use case I run:
    kubectl create secret tls tls-localhost-dev --key=localhost+2-key.pem --cert=localhost+2.pem -n dev 
    
  9. For my use case, I then run kubectl apply -f k8s/dev/tls.yaml which contains:
     apiVersion: cert-manager.io/v1
     kind: Issuer
     metadata:
       name: letsencrypt-dev-issuer
       namespace: cert-manager
     spec:
       ca:
         secretName: tls-localhost-dev
     ---
     apiVersion: cert-manager.io/v1
     kind: Certificate
     metadata:
       name: letsencrypt-dev-certificate
       namespace: cert-manager
     spec:
       secretName: tls-localhost-dev
       dnsNames:
         - localhost
       issuerRef:
         name: letsencrypt-dev-issuer
         kind: Issuer
    

This time after running skaffold dev, and minikube tunnel, my app is running with the TLS certificates like it should be.

like image 176
cjones Avatar answered Nov 01 '25 11:11

cjones



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!