Deployment guide

Free SSL Certificates with Let's Encrypt on a VPS

Deploy on a VPS Cloud →

Security & Monitoring8 min read

Free SSL Certificates with Let's Encrypt on a VPS

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. Here's how to build a clean, automated TLS chain rated A+, without depending on a shared hosting panel.

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/1.3 only), the cipher suites, HSTS and OCSP stapling. You can also issue a wildcard certificate (*.example.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.

What you gain by self-hosting the TLS chain

  • 100% free certificates, valid for 90 days and renewed automatically without intervention.
  • Wildcard *.example.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 (example.com, www.example.com, api.example.com) on a single IP.
  • Scriptable and observable renewal: reload hooks, Slack/email alerts before expiry.
  • No dependency on a third-party panel: the same recipe works across all your VPSes and environments.

Realistic prerequisites

TLS termination consumes very few resources: a VPS with 1 vCPU / 512 MB to 1 GB of RAM is more than enough to serve HTTPS for one or more sites. On the software side: Docker and docker compose (or a native Nginx/Caddy), a domain name pointing to the VPS's public IP (a propagated A/AAAA record), and ports 80 and 443 open in the firewall — port 80 is essential for the HTTP-01 challenge. For a wildcard certificate, plan for API access to your DNS provider (a token) to automate the DNS-01 challenge. Check propagation before starting: dig +short example.com must return the VPS's IP.

Deploy automated HTTPS in a few steps

01

Point the domain and open the ports

Create an A record example.com (and AAAA if IPv6) to the VPS's IP, then allow web traffic: ufw allow 80,443/tcp. Confirm resolution with dig +short example.com before going further — a challenge always fails if the DNS is not yet pointing.

02

Choose the reverse proxy that handles TLS

The simplest: Caddy, which obtains and renews Let's Encrypt automatically. A minimal Caddyfileexample.com { reverse_proxy app:3000 } — is enough to serve HTTPS as soon as docker compose up -d. For fine-grained control, go instead with Nginx + certbot, or Traefik with its built-in ACME resolver.

03

Issue the first certificate (HTTP-01)

With Nginx + Certbot in a container: docker run --rm -v ./certs:/etc/letsencrypt -v ./webroot:/var/www certbot/certbot certonly --webroot -w /var/www -d example.com -d www.example.com. Certbot places a challenge file in the webroot served by Nginx, Let's Encrypt validates it, and deposits fullchain.pem + privkey.pem.

04

Issue a wildcard via DNS-01 (optional)

For *.example.com, the HTTP-01 challenge is unsuitable: use DNS-01. With acme.sh and an API token: acme.sh --issue --dns dns_cf -d example.com -d '*.example.com'. The script creates a _acme-challenge TXT record, waits for propagation, then cleans up automatically.

05

Harden the TLS config

In Nginx, force ssl_protocols TLSv1.2 TLSv1.3;, enable ssl_stapling on;, and add add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;. Redirect all of port 80 to 443. Reload without downtime: nginx -s reload.

06

Automate renewal

Schedule renewal twice a day with a proxy reload: 0 0,12 * * * docker run --rm -v ./certs:/etc/letsencrypt certbot/certbot renew --quiet --deploy-hook "nginx -s reload". Caddy and Traefik do it natively; check expiry with echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates.

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. Also 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 number one cause of an HTTPS certificate expiring in the middle of the night.

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.

Need help?

Browse our help center and FAQ, or write to our team — support in French, English and Arabic.