[{"data":1,"prerenderedAt":183},["ShallowReactive",2],{"seo-verification":3,"blog-free-ssl-certificates-with-lets-encrypt-on-a-vps-ma-en":6,"promo-bar-likely":182},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-free-ssl-certificates-with-lets-encrypt-on-a-vps-ma-en",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":29,"intro":32,"sections":33,"ctaTitle":122,"ctaBody":123,"ctaButton":124,"ctaUrl":125,"relatedPosts":126},116,"free-ssl-certificates-with-lets-encrypt-on-a-vps",{"fr":12,"en":10,"ar":13,"es":14},"certificats-ssl-lets-encrypt-vps","شهادات-ssl-مجانية-باستخدام-lets-encrypt-على-خادم-vps","certificados-ssl-gratis-con-lets-encrypt-en-un-vps","Free SSL Certificates with Let's Encrypt on a VPS","Complete Let's Encrypt guide for VPS: certbot nginx, DNS-01 wildcard, systemd renewal, TLS hardening, rate-limit troubleshooting and certbot vs acme.sh vs Caddy.",8,0,false,"2026-02-24T00:00:00+00:00","2026-09-30T11:20:34+00:00",{"id":17,"name":23,"slug":24,"color":25,"icon":26},"Security & Monitoring","securite-monitoring","bg-rose-500\u002F10 text-rose-400","security",[28],{"id":17,"name":23,"slug":24,"color":25,"icon":26},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fcertificats-ssl-lets-encrypt-vps-poster.svg","HTTPS is no longer optional: browsers, SEO and customers all demand it. On a VPS you control end to end, Let's Encrypt issues recognized certificates that are free and renew themselves. This guide covers step-by-step certbot installation with Nginx, wildcard certificates via Cloudflare DNS challenge, systemd timer renewal verification, expiry monitoring and the most common errors — ACME rate limits, blocked port 80, DNS propagation.",[34,38,48,51,67,70,73,76,79,118],{"type":35,"title":36,"body":37},"h2","Why manage Let's Encrypt yourself on a VPS","Let's Encrypt is a free certificate authority that issues TLS certificates validated by an automated challenge (HTTP-01 or DNS-01). On shared hosting, you are stuck with the provider's TLS config: imposed protocol versions, no OCSP stapling, opaque renewal. On a VPS, you own the `certbot` (or `acme.sh`), the reverse proxy and the TLS termination. You decide on the protocols (TLS 1.2\u002F1.3 only), the cipher suites, HSTS and OCSP stapling. You can also issue a **wildcard** certificate (`*.your-domain.com`) via the DNS-01 challenge, cover several domains in a single certificate (SAN), and wire renewal to your own alerts. In short: total control over transport security, a prerequisite for an A+ score on SSL Labs and maximum browser-side trust.",{"type":39,"title":40,"items":41},"ul","What you gain by self-hosting the TLS chain",[42,43,44,45,46,47],"100% free certificates, valid for 90 days and renewed automatically without intervention.","Wildcard `*.your-domain.com` possible via the DNS-01 challenge: a single certificate for all your subdomains.","Full control of the config: TLS 1.3, modern cipher suites, HSTS and OCSP stapling.","Multi-domain SAN certificates (`your-domain.com`, `www.your-domain.com`, `api.your-domain.com`) on a single IP.","Scriptable and observable renewal: reload hooks, Slack\u002Femail alerts before expiry.","No dependency on a third-party panel: the same recipe works across all your VPSes and environments.",{"type":35,"title":49,"body":50},"Prerequisites before you start","TLS termination consumes very few resources: a VPS with **1 vCPU \u002F 512 MB to 1 GB of RAM** is more than enough to serve HTTPS for one or more sites.\n\nOn the network side: your **domain name must point to the VPS's public IP** (a propagated A\u002FAAAA record). Check propagation before running certbot: `dig +short your-domain.com` must return your VPS's IP. A challenge that fails due to incomplete DNS propagation counts as an attempt and brings you closer to the ACME rate limits.\n\n**Ports 80 and 443 must be open** in the firewall — port 80 is essential for the HTTP-01 challenge (certbot places a temporary challenge file there):\n```bash\nufw allow 80\u002Ftcp\nufw allow 443\u002Ftcp\nufw reload\n```\n\nFor a **wildcard** certificate (`*.your-domain.com`), the HTTP-01 challenge is not sufficient: you will need an API token from your DNS provider (Cloudflare, OVH…) to automate the DNS-01 challenge.",{"type":52,"title":53,"steps":54},"steps","Install certbot and obtain a Nginx certificate",[55,58,61,64],{"title":56,"body":57},"Install certbot and the Nginx plugin","On Debian\u002FUbuntu:\n```bash\napt update\napt install -y certbot python3-certbot-nginx\n```\nThe `python3-certbot-nginx` plugin reads your Nginx config, injects the TLS configuration and replaces the `listen 80` directive with an `443 ssl` block. If you prefer to manage Nginx manually, use `--standalone` or `--webroot` instead of `--nginx`.",{"title":59,"body":60},"Point the domain and open the ports","Create an A record `your-domain.com` (and AAAA if IPv6) pointing to the VPS's IP, then allow web traffic:\n```bash\nufw allow 80,443\u002Ftcp\n```\nConfirm resolution with `dig +short your-domain.com` before going further — a challenge always fails if DNS is not yet pointing.",{"title":62,"body":63},"Issue the certificate with the Nginx plugin","The most direct method — certbot modifies your Nginx vhost and manages renewal:\n```bash\ncertbot --nginx -d your-domain.com -d www.your-domain.com\n```\nCertbot asks for an email address (expiry alerts) and prompts you to accept the ToS. It issues the certificate, modifies `\u002Fetc\u002Fnginx\u002Fsites-available\u002F\u003Cvhost>`, adds an HTTP→HTTPS redirect and reloads Nginx without downtime.\n\nFiles are placed in `\u002Fetc\u002Fletsencrypt\u002Flive\u002Fyour-domain.com\u002F`: `fullchain.pem` (certificate + chain) and `privkey.pem` (private key).",{"title":65,"body":66},"Verify automatic renewal","Certbot installs a **systemd timer** that attempts renewal twice a day:\n```bash\nsystemctl status certbot.timer\n```\nTo simulate a renewal without issuing a new certificate:\n```bash\ncertbot renew --dry-run\n```\nIf the simulation succeeds, your renewal chain is operational. Make sure Nginx reloads after an actual renewal — certbot automatically adds a `--deploy-hook \"systemctl reload nginx\"` hook in `\u002Fetc\u002Fletsencrypt\u002Frenewal\u002F\u003Cdomain>.conf` when using the Nginx plugin.",{"type":35,"title":68,"body":69},"Wildcard certificate with Cloudflare DNS challenge","A `*.your-domain.com` certificate covers all your subdomains with a single file. It is mandatory if you create subdomains dynamically or if you don't want to issue one certificate per subdomain.\n\nThe HTTP-01 challenge cannot validate a wildcard — you need the **DNS-01 challenge**, which requires certbot to temporarily create a TXT record `_acme-challenge.your-domain.com`.\n\n**With Cloudflare (API token):**\n```bash\napt install -y python3-certbot-dns-cloudflare\n```\nCreate a Cloudflare credentials file (permissions: `600`):\n```bash\nmkdir -p \u002Fetc\u002Fletsencrypt\u002Fcloudflare\nchmod 700 \u002Fetc\u002Fletsencrypt\u002Fcloudflare\ncat > \u002Fetc\u002Fletsencrypt\u002Fcloudflare\u002Fcredentials.ini \u003C\u003C 'EOF'\ndns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN\nEOF\nchmod 600 \u002Fetc\u002Fletsencrypt\u002Fcloudflare\u002Fcredentials.ini\n```\nIssue the wildcard certificate:\n```bash\ncertbot certonly \\\n  --dns-cloudflare \\\n  --dns-cloudflare-credentials \u002Fetc\u002Fletsencrypt\u002Fcloudflare\u002Fcredentials.ini \\\n  -d your-domain.com \\\n  -d '*.your-domain.com'\n```\nCertbot creates the TXT record, waits for propagation (10 seconds by default — increase with `--dns-cloudflare-propagation-seconds 30`), obtains the certificate, then deletes the TXT record.\n\n**Alternative with acme.sh:**\n```bash\nacme.sh --issue --dns dns_cf -d your-domain.com -d '*.your-domain.com'\n```\n`acme.sh` uses the `CF_Token` environment variable or `CF_Key` + `CF_Email` depending on your Cloudflare authentication method.",{"type":35,"title":71,"body":72},"Nginx TLS hardening: TLS 1.2\u002F1.3, HSTS and cipher suites","The certbot plugin configures a functional HTTPS, but the default configuration is not optimal for an A+ score on SSL Labs. Here are the directives to add to your `server` block (or in an included file like `\u002Fetc\u002Fnginx\u002Fsnippets\u002Fssl-params.conf`):\n```bash\n# Protocols: TLS 1.2 minimum, TLS 1.3 recommended\nssl_protocols TLSv1.2 TLSv1.3;\n\n# Modern cipher suites (Mozilla Intermediate)\nssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256;\nssl_prefer_server_ciphers off;\n\n# TLS session\nssl_session_timeout 1d;\nssl_session_cache shared:SSL:10m;\nssl_session_tickets off;\n\n# OCSP Stapling\nssl_stapling on;\nssl_stapling_verify on;\nresolver 1.1.1.1 8.8.8.8 valid=300s;\nresolver_timeout 5s;\n\n# HSTS (6 months, subdomains included, preload)\nadd_header Strict-Transport-Security \"max-age=15768000; includeSubDomains; preload\" always;\n\n# Additional security headers\nadd_header X-Frame-Options DENY;\nadd_header X-Content-Type-Options nosniff;\n```\nRedirect all of port 80 to 443 in a separate `server` block:\n```bash\nserver {\n    listen 80;\n    server_name your-domain.com www.your-domain.com;\n    return 301 https:\u002F\u002F$host$request_uri;\n}\n```\nReload without downtime: `nginx -s reload`. Then test on \u003Ca href=\"https:\u002F\u002Fwww.ssllabs.com\u002Fssltest\u002F\">SSL Labs\u003C\u002Fa> — you should get A+.",{"type":35,"title":74,"body":75},"Monitoring certificate expiry","Automatic renewal can fail silently: systemd timer disabled, port 80 blocked after a firewall change, Cloudflare API token revoked… An expired certificate in production breaks the service for all your visitors.\n\n**Manual check:**\n```bash\necho | openssl s_client -connect your-domain.com:443 -servername your-domain.com 2>\u002Fdev\u002Fnull \\\n  | openssl x509 -noout -dates\n```\n\n**Email alert script (to place in cron or systemd):**\n```bash\n#!\u002Fbin\u002Fbash\n# Alert if the certificate expires in less than 14 days\ncert_file=\"\u002Fetc\u002Fletsencrypt\u002Flive\u002Fyour-domain.com\u002Ffullchain.pem\"\nif ! openssl x509 -checkend 1209600 -noout -in \"$cert_file\" 2>\u002Fdev\u002Fnull; then\n  echo \"ALERT: certificate your-domain.com expires in less than 14 days\" \\\n    | mail -s \"[SSL] Imminent expiry\" admin@your-domain.com\nfi\n```\n`-checkend 1209600` corresponds to 14 days in seconds (14 × 86,400).\n\n**With Uptime Kuma:** add a \"Certificate Expiry\" monitor that alerts at D-14 — no script to maintain.",{"type":35,"title":77,"body":78},"Troubleshooting: rate limits, blocked port 80, DNS propagation","**ACME rate limits: \"too many certificates already issued\"**\nLet's Encrypt limits to 5 certificates per registrable domain per week. If you hit this limit during testing, switch to the **staging** environment:\n```bash\ncertbot --nginx --staging -d your-domain.com\n```\nStaging issues certificates not trusted by browsers, but with no rate limit. Once your configuration is validated, delete the staging certificate and reissue in production.\n\n**Port 80 blocked**\nThe HTTP-01 challenge requires Let's Encrypt to reach `http:\u002F\u002Fyour-domain.com\u002F.well-known\u002Facme-challenge\u002F`. Check:\n```bash\ncurl -I http:\u002F\u002Fyour-domain.com\u002F.well-known\u002Facme-challenge\u002Ftest\n# expected: 404 (the route exists, the file doesn't yet)\nufw status | grep 80\n```\nIf port 80 is blocked by an upstream firewall (cloud provider, Cloudflare in proxy mode), temporarily open it or switch to the DNS-01 challenge.\n\n**Cloudflare proxy active**\nIf your domain is behind Cloudflare (orange cloud icon), make sure Cloudflare's SSL mode is **Full (Strict)** — in Flexible mode, Cloudflare communicates with your server over HTTP and nginx redirecting HTTP→HTTPS produces an infinite loop (HTTP 525\u002F526).\n\n**Insufficient DNS propagation**\nFor the DNS-01 challenge, wait at least 60 seconds after creating the TXT record before retrying certbot. Check:\n```bash\ndig TXT _acme-challenge.your-domain.com +short\n```\nIf the value does not appear yet, wait before retrying.",{"type":80,"title":81,"headers":82,"rows":87},"comparison","Comparison: certbot vs acme.sh vs Caddy automatic HTTPS",[83,84,85,86],"Criterion","certbot","acme.sh","Caddy (auto HTTPS)",[88,93,98,103,108,113],[89,90,91,92],"Installation","`apt install certbot`","Bash script, no system dependencies","Single binary, included",[94,95,96,97],"Nginx\u002FApache integration","Native plugin (`--nginx`, `--apache`)","Manual `--install-cert` hooks","Manages its own reverse proxy",[99,100,101,102],"Wildcard DNS-01","Via DNS plugin (`python3-certbot-dns-*`)","Native, many integrated DNS providers","Via `tls.dns.*` module (Caddy v2)",[104,105,106,107],"Renewal","Systemd timer (automatic)","Cron job generated at install","Native, no configuration",[109,110,111,112],"Learning curve","Low — intuitive commands","Medium — many options","Very low — minimalist Caddyfile",[114,115,116,117],"Ideal use case","Existing dedicated Nginx\u002FApache server","Complex environments, multi-DNS providers","New projects, integrated reverse proxy",{"type":119,"title":120,"body":121},"tip","Test before production","Before going to production, test against Let's Encrypt's **staging** environment (`--staging` with Certbot, `--server letsencrypt_test` with acme.sh): the production limit is 5 issuances per domain per week, and a poorly tuned script can quickly make you hit it.\n\nAlso add **expiry monitoring**: a probe that runs `openssl x509 -checkend 604800` (7 days) and triggers an alert if automatic renewal has silently failed — a broken cron is the top cause of an HTTPS certificate expiring in the middle of the night.\n\nCheck the \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcertbot\u002Fcertbot\">certbot releases page on GitHub\u003C\u002Fa> to verify the available version before writing a tutorial or installation script.","Deploy your Cloud VPS with HTTPS ready to go","The ServOrbit Cloud VPS template comes with Docker, a reverse proxy and the Let's Encrypt chain preconfigured: certificates issued and renewed automatically, an A+ SSL Labs score from the very first deployment. Focus on your application, not on TLS plumbing.","Deploy my Cloud VPS","\u002Fvps-cloud",[127,145,164],{"id":128,"slug":129,"slugs":130,"title":134,"excerpt":135,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":136,"updatedAt":137,"category":138,"categories":139,"featuredImage":29,"bgImage":30,"posterImage":141,"relatedSolution":142},105,"monitoring-your-vps-with-uptime-kuma",{"fr":131,"en":129,"ar":132,"es":133},"superviser-vps-uptime-kuma","مراقبة-خادمك-الافتراضي-vps-باستخدام-uptime-kuma","supervisar-vps-con-uptime-kuma","Monitoring your VPS with Uptime Kuma","Deploy Uptime Kuma on your VPS to monitor your sites and services self-hosted, with alerts and a public status page.","2026-03-07T00:00:00+00:00","2026-11-09T20:55:19+00:00",{"id":17,"name":23,"slug":24,"color":25,"icon":26},[140],{"id":17,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fsuperviser-vps-uptime-kuma-poster.svg",{"categorySlug":143,"appSlug":144},"monitoring-observability","uptime-kuma",{"id":146,"slug":147,"slugs":148,"title":152,"excerpt":153,"readTime":154,"views":155,"isPinned":19,"noindex":19,"publishedAt":156,"updatedAt":157,"category":158,"categories":159,"featuredImage":29,"bgImage":30,"posterImage":161,"relatedSolution":162},106,"vps-monitoring-with-grafana-and-prometheus",{"fr":149,"en":147,"ar":150,"es":151},"monitoring-vps-grafana-prometheus","مراقبة-الخادم-الافتراضي-vps-باستخدام-grafana-و-prometheus","monitorizacion-vps-grafana-prometheus","VPS Monitoring with Grafana and Prometheus","Deploy Prometheus 3.x, Grafana 13.x, Node Exporter and Alertmanager on your VPS with Docker Compose. Dashboards, alerts and hardening.",11,1,"2026-03-06T00:00:00+00:00","2026-10-05T14:05:27+00:00",{"id":17,"name":23,"slug":24,"color":25,"icon":26},[160],{"id":17,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fmonitoring-vps-grafana-prometheus-poster.svg",{"categorySlug":143,"appSlug":163},"grafana",{"id":165,"slug":166,"slugs":167,"title":171,"excerpt":172,"readTime":173,"views":155,"isPinned":19,"noindex":19,"publishedAt":174,"updatedAt":175,"category":176,"categories":177,"featuredImage":29,"bgImage":30,"posterImage":179,"relatedSolution":180},107,"monitor-your-vps-in-real-time-with-netdata",{"fr":168,"en":166,"ar":169,"es":170},"monitorer-vps-netdata","راقب-خادمك-الافتراضي-vps-في-الوقت-الفعلي-باستخدام-netdata","monitorizar-vps-en-tiempo-real-con-netdata","Monitor your VPS in real time with Netdata","Install Netdata on your VPS for per-second real-time monitoring: thousands of metrics, zero configuration, alerts included.",3,"2026-03-05T00:00:00+00:00","2026-09-07T11:26:10+00:00",{"id":17,"name":23,"slug":24,"color":25,"icon":26},[178],{"id":17,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fmonitorer-vps-netdata-poster.svg",{"categorySlug":143,"appSlug":181},"netdata",true,1794270403860]