BinaryLane does not sell SSL/TLS certificates, but you can secure any site on your VPS at no cost using Let's Encrypt. This guide installs Certbot on Ubuntu 24.04, issues a certificate for your domain, configures Nginx or Apache to use it, and sets up automatic renewal. It also covers the two things that most often break a Let's Encrypt setup on a BinaryLane server: a firewall that blocks the validation request, and a hardened web server config that hides it.
Prerequisites:
- A BinaryLane VPS running Ubuntu 24.04 LTS (the steps also work on 22.04)
- Root or sudo access
- Nginx or Apache already installed and serving your site
- A registered domain name you control
- Port 80 open to the internet, and kept open afterwards
Before you start: Let's Encrypt validates your domain by fetching a file from your server over plain HTTP on port 80. That means port 80 must be reachable from the internet both when you first issue the certificate and every time it renews. Closing port 80 once HTTPS is working is the single most common cause of a certificate quietly expiring 60 days later.
TABLE OF CONTENTS
- Point your domain at the server
- Open port 80
- Install Certbot
- Check the validation path is reachable
- Issue the certificate
- Verify it worked
- Automatic renewal
- Optional: enable HSTS
- Troubleshooting
Point your domain at the server
Let's Encrypt will not issue a certificate for a bare IP address, so you need a domain or subdomain pointing at your VPS. If your DNS is hosted with BinaryLane, add an A record in the mPanel DNS section, or through the API:
curl -X POST "https://api.binarylane.com.au/v2/domains/example.com/records" \
-H "Authorization: Bearer $BINARYLANE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"A","name":"www","data":"203.0.113.10"}'Note: BinaryLane DNS uses a fixed TTL of 3600 seconds. If you include a ttl field in the API request it will be rejected with TTL of 3600 may not be changed. Leave the field out.
Confirm the record has propagated before continuing. Your own machine may have cached a previous failed lookup, so check against a public resolver rather than trusting a local ping:
curl -s "https://dns.google/resolve?name=www.example.com&type=A"
A "Status": 0 along with your server's IP means DNS is ready.
Open port 80
Validation happens over HTTP, so port 80 must be open in every firewall in front of the server. On a BinaryLane VPS that can mean two places.
If you use the BinaryLane External Firewall, make sure it has an accept rule for TCP 80 and TCP 443. If you run a host firewall such as nftables, allow both there too:
sudo nft list ruleset | grep -E "dport (80|443)"
If nothing is returned, add accept rules for both ports before continuing.
Install Certbot
Install Certbot and the plugin for your web server. For Nginx:
sudo apt-get update sudo apt-get install -y certbot python3-certbot-nginx certbot --version
For Apache, install the Apache plugin instead:
sudo apt-get install -y certbot python3-certbot-apache
Check the validation path is reachable
Certbot proves you control the domain by placing a file at /.well-known/acme-challenge/ and asking Let's Encrypt to fetch it over HTTP. Testing that path yourself first turns a confusing certbot failure into an obvious one.
sudo mkdir -p /var/www/html/.well-known/acme-challenge echo ok | sudo tee /var/www/html/.well-known/acme-challenge/precheck curl -s http://www.example.com/.well-known/acme-challenge/precheck
You should see ok. Once it works, remove the test file:
sudo rm /var/www/html/.well-known/acme-challenge/precheck
If you get 403 Forbidden: a hardened web server config is the usual cause. Many security guides suggest blocking dotfiles with a rule like location ~ /\. { deny all; } in Nginx. Because .well-known begins with a dot, that rule blocks the validation request as well, and Certbot fails with an unhelpful authorization error. Add an explicit exception above the deny rule, since a ^~ prefix location takes precedence over a regular expression location:
location ^~ /.well-known/acme-challenge/ {
root /var/www/html;
default_type "text/plain";
allow all;
}
location ~ /\. { deny all; }The Apache equivalent is to make sure any <FilesMatch "^\."> or similar deny directive does not cover the .well-known directory.
If the precheck fails once and then works: that is normal. Reloading Nginx returns immediately, but worker processes pick up the new configuration a moment later. Retry once before assuming the config is wrong.
Issue the certificate
Make sure your server_name (Nginx) or ServerName (Apache) matches the domain you are requesting, then run Certbot. For Nginx:
sudo certbot --nginx \ -d www.example.com \ --agree-tos \ --email you@example.com \ --redirect
For Apache, substitute --apache. The --redirect flag tells Certbot to add an automatic HTTP to HTTPS redirect, which is almost always what you want.
On success you will see something like:
Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/www.example.com/fullchain.pem Key is saved at: /etc/letsencrypt/live/www.example.com/privkey.pem This certificate expires on 2026-11-04.
To cover several names on one certificate, repeat -d:
sudo certbot --nginx -d example.com -d www.example.com --agree-tos --email you@example.com --redirect
Verify it worked
# site loads over HTTPS
curl -sI https://www.example.com/ | head -1
# plain HTTP now redirects
curl -sI http://www.example.com/ | grep -i location
# check the certificate dates
echo | openssl s_client -servername www.example.com \
-connect www.example.com:443 2>/dev/null | openssl x509 -noout -datesAutomatic renewal
Let's Encrypt certificates last 90 days. Certbot installs a systemd timer that renews them automatically from day 60, so there is nothing to schedule yourself. Confirm it is active:
systemctl is-enabled certbot.timer systemctl is-active certbot.timer
Then test the renewal path without actually replacing anything:
sudo certbot renew --dry-run
A successful run ends with Congratulations, all simulated renewals succeeded.
Note: The dry run can take a minute or two. If you start a second Certbot command while it is still going you will see Another instance of Certbot is already running. Wait for the first to finish rather than re-running it.Important: renewal uses the same HTTP validation as the initial request, so port 80 must remain open permanently. A server that works perfectly today will fail to renew in two months if port 80 has been closed in the meantime, and the first sign is usually a browser certificate warning.
Optional: enable HSTS
Once you are confident HTTPS is working, HTTP Strict Transport Security tells browsers to refuse plain HTTP for your domain. In Nginx:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Note: Nginx add_header directives are not inherited by a location block that defines its own. If any location sets its own headers, repeat the full set there or it will silently lose the others.
Only enable HSTS after HTTPS is confirmed working. Browsers cache the policy for the duration you set, so a broken certificate becomes much harder to recover from.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Timeout during authorization | Port 80 blocked by the External Firewall or a host firewall |
| 403 Forbidden on the challenge file | A dotfile deny rule is blocking .well-known |
| 404 on the challenge file | root does not point at the directory Certbot is writing to |
| DNS problem: NXDOMAIN looking up A | The record has not propagated, or the name is misspelled |
| Too many certificates already issued | Let's Encrypt rate limit; wait, or use --dry-run while testing |
| Certificate works but expires anyway | Port 80 was closed after setup, so renewal could not validate |
Certbot writes detailed logs to /var/log/letsencrypt/letsencrypt.log, which is usually more informative than the console output.
Locked out? If a web server or firewall change leaves you unable to reach the server over SSH, you can still get in through the Rescue Console in the mPanel. It connects at the console level and does not depend on the network configuration or firewall rules.
Let's Encrypt certificates are free and trusted by all major browsers. BinaryLane provides the VPS; certificate installation and renewal are self-managed, and the automatic renewal timer means there is normally nothing left to do once it is set up.
Using Windows Server and IIS? See Free SSL/TLS Certificates with Let’s Encrypt and win-acme on Windows Server.
