Replacing Kasm’s default self-signed certificates with **Let’s Encrypt** is a common task to remove browser “Insecure” warnings.
The process involves generating the certificates using `certbot` and then linking them to the Kasm proxy.
### Prerequisites
* A domain name pointed to your Kasm server’s IP.
* Ports **80** and **443** open on your firewall.
* `certbot` installed on your host system.
—
### Step 1: Generate the Let’s Encrypt Certificate
Since Kasm uses port 443, you should use Certbot’s **standalone** mode.
You must briefly stop the Kasm proxy so Certbot can use the port to verify your domain.
1. **Stop the Kasm Proxy:**
“`bash
sudo docker stop kasm_proxy
“`
2. **Run Certbot:**
Replace `yourdomain.com` with your actual domain.
“`bash
sudo certbot certonly –standalone -d yourdomain.com
“`
*This will save your certificates to `/etc/letsencrypt/live/yourdomain.com/`.*
3. **Verify:**
If the process was successful, you should see output like this:
“`bash
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/your.domain.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/your.domain.net/privkey.pem
This certificate expires on 2026-07-19.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let’s Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
“`
—
### Step 2: Replace Kasm Certificates
Kasm looks for its certificates in `/opt/kasm/current/certs/`. Instead of copying the files, it is best practice to use **symbolic links** so that when Let’s Encrypt auto-renews, Kasm automatically sees the new files.
1. **Navigate to the Kasm cert directory:**
“`bash
cd /opt/kasm/current/certs/
“`
2. **Backup the original self-signed certs:**
“`bash
sudo mv kasm_nginx.crt{,.bak} && mv kasm_nginx.key{,.bak}
“`
3. **Create the symbolic links:**
Point Kasm’s expected filenames to your new Let’s Encrypt files:
“`bash
sudo ln -s /etc/letsencrypt/live/yourdomain.com/fullchain.pem kasm_nginx.crt
sudo ln -s /etc/letsencrypt/live/yourdomain.com/privkey.pem kasm_nginx.key
“`
—
### Step 3: Restart and Verify
Now, bring the proxy back up to apply the changes.
1. **Start the Kasm Proxy:**
“`bash
sudo docker start kasm_proxy
“`
2. **Verify:**
Open your browser and navigate to `https://yourdomain.com`. You should now see a valid lock icon without any security warnings.
—
### Step 4: Automating Renewal
Let’s Encrypt certificates expire every 90 days and need to be renewed.
Since we had to stop the kasm_proxy to issue the cert, the normal automatic renewal will fail as kasm_proxy is occupying those ports.
Luckily for us, Certbot has built in support for this as part of it’s renewal process, we just need to tell it what to do:
1. Open the renewal file for your domain:
“`bash
sudo nano /etc/letsencrypt/renewal/your.domain.net.conf
“`
2. Under **[renewalparams]** add two new lines to the bottom of the block:
“`bash
pre_hook = docker stop kasm_proxy
post_hook = docker start kasm_prox
“`
3. Now do a renewal `dry-run` to test everything is working:
“`bash
sudo certbot renew –dry-run –cert-name your.domain.net
“`
4. You should see the pre-hook & post-hook fire for kasm_proxy, confirming everything was successful:
“`bash
# sudo certbot renew –dry-run –cert-name your.domain.net
Saving debug log to /var/log/letsencrypt/letsencrypt.log
– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
Processing /etc/letsencrypt/renewal/your.domain.net.conf
– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
Account registered.
Hook ‘pre-hook’ ran with output:
kasm_proxy
Simulating renewal of an existing certificate for your.domain.net and kasm-direct.uo5.net
– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/your.domain.net/fullchain.pem (success)
– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
Hook ‘post-hook’ ran with output:
kasm_proxy
“`
5. **Note:** If you prefer not to open port 80 or stop Kasm for renewals, consider using the **DNS-01 challenge** with Certbot (e.g., `certbot-dns-cloudflare`), which verifies ownership via DNS records rather than a web server.
Leave a Reply