Enforcing HTTPS on Portainer using cert-manager and Let’s Encrypt after Initial Setup
After setting up a working k3s cluster with both Portainer (without TLS) and helm
for configuration management, you can now enforce secure communication by integrating the previously generated certificate through Cert-Manager. Here’s how to do it:
Steps To Enforce HTTPS on Portainer
- Create a Secret in your namespace with certificates (this step should be done before helm installation):
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: portainer-tls-secret namespace: portainer spec: secretName: portainer-tls-secret duration: 2160h # 90 days for renewal period renewBefore: 360h # After how many hours a new certificate should be issued before the previous one expires, around two weeks ahead. Adjust as necessary depending on your desired cert validity window and issuance frequency rate of Let's Encrypt subject: organizations: - <redacted> # Replace with actual info here commonName: portainer.k8s.mydomain.tld isCA: false privateKey: algorithm: RSA encoding: PKCS1 size: 4096 usages: - server auth # Essential usage for TLS termination in Portainer
- Remove the existing portainer deployment and namespace if they are not needed anymore, as we will be using Helm to reinstall it with our custom certificates now:
kubectl delete namespace --purge portainer # Cleanup previous resources created by Portainer before installation of a new one via helm. Note that this step isn't strictly necessary if you are only changing the existing secret and not creating any additional deployments or configurations, but it’s safe to do so: kubectl delete clusterrolebinding portainer # Assuming there was an associated ClusterRoleBinding in your previous setup
- Reinstall Portainer using helm with environment variables pointing towards the custom certificate secret you created earlier (ensure that these values are correct):
helm install --create-namespace -n portainer portainer/portainer \ --set tls=true \ # Forces TLS and sets up HTTPS endpoint by default. Adjust if additional settings are required beyond what cert-manager provides: "tlsSecret"="portainer-tls-secret"
- Check that the certificate has been applied to your Portainer instance successfully (optional but recommended):
Now, Portainer should be accessible via HTTPS: https://portainer-service/ (replace with actual service name if different).kubectl get certificates --all-namespaces | grep portainer # You should see a successful deployment with "True". If not, review above steps for errors: kubectl -n=portainer describe certificate <certificate name> ## Replace `<certificate name>` accordingly. Here is an example output that you may find helpful to verify the status and conditions of your created certificates in specific namespace within Kubernetes cluster using this command line utility `kubectl`.
- Note that you can easily automate renewing certificates by updating the issuer settings in your cert-manager
ClusterIssuer
resources as necessary according to Let’s Encrypt’s documentation and policies for certificate management within Kubernetes environments using Cert Manager: Certificate Management with LetsEncrypt. It should not require manual intervention or reinstallation via helm unless your requirements change significantly (such as changing the domain names, adjusting renewal periods, etc.). - Make sure to always monitor for certificate expiration and update corresponding resources in cert-manager accordingly using commands like:
kubectl get certificates --all-namespaces
. This way you can ensure uninterrupted SSL endpoints within your Kubernetes cluster environment at all times.
Enforcing HTTPS with a selfsigned or third party certificate generated by Cert Manager gives security assurance to sensitive data transmitted between client applications and backend services in the containerized environments, making it an excellent practice for production-grade deployments of containers like Portainer within Kubernetes clusters using Helm. Happy Securing!