Skip to content

Instantly share code, notes, and snippets.

@jajansen
Created January 7, 2026 19:01
Show Gist options
  • Select an option

  • Save jajansen/3369e447b30345f459d98af690be113e to your computer and use it in GitHub Desktop.

Select an option

Save jajansen/3369e447b30345f459d98af690be113e to your computer and use it in GitHub Desktop.
Proper certificates for for GLKVM Comet (Pro) using Certbot
#!/bin/bash
# Automated certbot setup script for KVMD (PiKVM) with Cloudflare DNS
# Usage: ./setup-certbot-glkvm.sh <domain> <cloudflare-api-token>
set -e # Exit on any error
# Validate arguments
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <domain> <cloudflare-api-token>"
echo "Example: $0 glkvm.example.com YOUR_CLOUDFLARE_API_TOKEN"
exit 1
fi
DOMAIN="$1"
CF_TOKEN="$2"
VENV_PATH="/opt/certbot"
CF_CREDS_FILE="${HOME}/cf-credentials.txt"
echo "=== Certbot Setup for KVMD ==="
echo "Domain: ${DOMAIN}"
echo "Virtual Environment: ${VENV_PATH}"
# Create Python virtual environment for certbot isolation
echo "Step 1: Creating Python virtual environment..."
python3 -m venv "${VENV_PATH}"
# Upgrade pip to latest version in virtual environment
echo "Step 2: Upgrading pip..."
"${VENV_PATH}/bin/pip" install --upgrade pip
# Install certbot and nginx plugin into virtual environment
echo "Step 3: Installing certbot and certbot-nginx..."
"${VENV_PATH}/bin/pip" install certbot certbot-nginx
# Install Cloudflare DNS plugin for DNS-01 challenge
echo "Step 4: Installing certbot-dns-cloudflare plugin..."
"${VENV_PATH}/bin/pip" install certbot-dns-cloudflare
# Create symlink to make certbot available system-wide
echo "Step 5: Creating certbot symlink..."
if [ ! -L /usr/bin/certbot ]; then
ln -s "${VENV_PATH}/bin/certbot" /usr/bin/certbot
fi
# Create Cloudflare credentials file with API token
echo "Step 6: Creating Cloudflare credentials file..."
cat > "${CF_CREDS_FILE}" <<EOF
# Cloudflare API token used by Certbot
dns_cloudflare_api_token = ${CF_TOKEN}
EOF
# Set restrictive permissions on credentials file (read-only for owner)
echo "Step 7: Setting secure permissions on credentials file..."
chmod 400 "${CF_CREDS_FILE}"
# Request certificate using Cloudflare DNS-01 challenge
echo "Step 8: Requesting certificate from Let's Encrypt..."
certbot certonly \
--non-interactive \
--agree-tos \
--email "" \
--dns-cloudflare \
--dns-cloudflare-credentials "${CF_CREDS_FILE}" \
-d "${DOMAIN}"
# Backup existing KVMD nginx SSL configuration
echo "Step 9: Backing up existing nginx SSL configuration..."
if [ -f /etc/kvmd/nginx/ssl.conf ]; then
cp /etc/kvmd/nginx/ssl.conf /etc/kvmd/nginx/ssl.conf.backup
fi
# Update KVMD nginx SSL configuration to use Let's Encrypt certificates
echo "Step 10: Updating nginx SSL configuration..."
cat > /etc/kvmd/nginx/ssl.conf <<EOF
ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
#ssl_certificate /etc/kvmd/user/ssl/server.crt;
#ssl_certificate_key /etc/kvmd/user/ssl/server.key;
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
EOF
# Restart KVMD nginx service to apply new SSL certificates
echo "Step 11: Restarting kvmd-nginx service..."
/etc/init.d/S99kvmd-nginx restart
# Set up automatic certificate renewal via crontab with random sleep delay
echo "Step 12: Setting up automatic certificate renewal..."
SLEEPTIME=$(awk 'BEGIN{srand(); print int(rand()*(3600+1))}')
CRON_ENTRY="0 0,12 * * * root sleep $SLEEPTIME && certbot renew -q --dns-cloudflare --dns-cloudflare-credentials ${CF_CREDS_FILE} --post-hook '/etc/init.d/S99kvmd-nginx restart'"
# Check if crontab entry already exists to avoid duplicates
if ! grep -q "certbot renew" /etc/crontab 2>/dev/null; then
echo "${CRON_ENTRY}" >> /etc/crontab
echo "Added certbot renewal to crontab (runs at midnight and noon with ${SLEEPTIME}s random delay)"
else
echo "Certbot renewal already exists in crontab, skipping..."
fi
echo ""
echo "=== Setup Complete ==="
echo "Certificate location: /etc/letsencrypt/live/${DOMAIN}/"
echo "Certificate expires: $(date -d "+90 days" +%Y-%m-%d)"
echo "Credentials file: ${CF_CREDS_FILE}"
echo ""
echo "Next steps:"
echo "1. Test HTTPS access: https://${DOMAIN}"
echo "2. Verify automatic renewal: certbot renew --dry-run"
echo "3. Check crontab entry: cat /etc/crontab | grep certbot"
echo ""
echo "To run this script over SSH without uploading:"
echo " ssh root@glkvm.local 'bash -s' < setup-certbot-glkvm.sh glkvm.example.com YOUR_CLOUDFLARE_API_TOKEN"
@jajansen
Copy link
Author

jajansen commented Feb 26, 2026

A remote way to update glkvm
ssh root@glkvm.local 'bash -s' < setup-certbot-glkvm.sh glkvm.example.com YOUR_CLOUDFLARE_API_TOKEN

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment