How to Install an SSL Certificate on a VPS: Let’s Encrypt, Certbot, and Automatic Renewal

Martin Klein

Reading time 1 minute

An SSL certificate on a VPS is not installed “on the server as a whole,” but for a specific domain or subdomain. Before a certificate can be issued, the domain must point to the VPS IP address, the web server must respond over HTTP, and ports 80 and 443 must be open.

The general workflow is as follows: domain → DNS → web server → ACME challenge → certificate issuance → automatic renewal

Let’s Encrypt uses an ACME challenge to verify that you actually control the domain. After successful verification, the certificate is issued, and the web server starts serving the site over HTTPS.

Certbot is most commonly used for Nginx and Apache. It can automatically detect the site configuration, issue a certificate, add the SSL settings, and enable redirects from HTTP to HTTPS.

For Nginx, the basic workflow usually looks like this: sudo certbot –nginx -d example.com -d www.example.com

For Apache: sudo certbot –apache -d example.com -d www.example.com

After installing the certificate, you need to check not only the green padlock in the browser, but also several technical details:

  • The site opens over HTTPS;
  • HTTP is correctly redirected to HTTPS;
  • The certificate was issued for the correct domain;
  • The www and non-www versions work correctly;
  • Certbot automatic renewal runs without errors;
  • There is no mixed content left on the pages;
  • The backend, API, images, stylesheets, and scripts are also loaded over HTTPS.

If SSL is configured through a VPS control panel, the process is similar: the panel starts certificate issuance through Let’s Encrypt and then adds it to the site configuration. However, the panel does not replace the basic checks. DNS, ports, redirects, and mixed content still need to be checked manually.

A wildcard certificate is needed if you need to secure all subdomains of the form *.example.com at once, such as app.example.com, api.example.com, and dev.example.com. It usually uses a DNS challenge because Let’s Encrypt must verify control over the domain’s entire DNS zone.

The main mistakes when installing SSL on a VPS are closed ports 80 or 443, a domain pointing to the wrong IP address, the web server not responding over HTTP, an incorrectly configured HTTP → HTTPS redirect, a certificate issued for the wrong domain, unverified automatic renewal, and mixed content remaining on the site after installation.

The correct sequence is as follows: first check DNS and the web server, then issue the certificate, enable HTTPS, check redirects, test automatic renewal, and only then consider SSL configured.

How SSL Issuance Works on a VPS

An SSL certificate is required so that a website can be accessed over HTTPS and the browser can verify that the user is connecting to the correct domain and that the connection is encrypted.

On a VPS, certificates are often issued through Let’s Encrypt. It is a free certificate authority that uses the ACME protocol. The server owner runs Certbot or uses a control panel, and Let’s Encrypt verifies that the domain is actually associated with this server or is controlled by its owner. Alternatives such as paid certificates and ZeroSSL also exist and are widely used, but LE remains the most popular option.

The key is to understand the validation chain. If even one step in that chain is broken, certificate issuance will fail.

Domain → DNS → web server → ACME challenge → certificate

The SSL certificate issuance process can be represented as the following sequence: domain → DNS → web server → ACME challenge → certificate issuance → automatic renewal

First, the domain must point to the VPS IP address. This is configured in the domain’s DNS zone using an A record for IPv4 or an AAAA record for IPv6.

Next, the web server on the VPS must handle requests for this domain. This is usually Nginx or Apache with a configured virtual host.

After that, Certbot sends a request to Let’s Encrypt. Let’s Encrypt verifies the domain through an ACME challenge. In the standard scenario, the server must serve a special validation file over HTTP, so it is important that the server respond over HTTP on port 80. If the validation succeeds, Let’s Encrypt issues the certificate.

Certbot then adds the certificate to the web server configuration or shows where the certificate files are located if the setup is performed manually.

After installation, the site becomes available over HTTPS. But the work does not end there: you need to check the redirect, the domains included in the certificate, mixed content, and automatic renewal.

What Let’s Encrypt Checks

Let’s Encrypt does not verify who owns the business, where the server is located, or who legally owns the website. In the standard scenario, it verifies control over the domain.

For a standard certificate, the HTTP-01 challenge is most commonly used. Let’s Encrypt connects to the domain over HTTP and checks whether the server can serve a special file with the required content.

If the file is accessible, it means the person initiating certificate issuance controls the server that the domain points to. The certificate can then be issued.

Wildcard certificates use a different approach: the DNS challenge. In this case, a special TXT record must be added to the domain’s DNS zone. This allows Let’s Encrypt to verify control not over a specific web server, but over the domain’s DNS.

That is why, before installing SSL, it is important to make sure the domain already points to the correct IP address, DNS changes have had time to propagate, and the web server is serving the correct site.

Why Ports 80 and 443 Matter

Two ports are important for issuing and using SSL: 80 and 443.

Port 80 is used for HTTP. It is needed not only to open a website normally without HTTPS, but also for Let’s Encrypt validation in the HTTP-01 challenge scenario. If port 80 is blocked by a firewall, the hosting provider, or server settings, Certbot may fail domain validation.

Port 443 is used for HTTPS. After the certificate is issued, browsers use this port to connect to the secure version of the website.

A common mistake is to block port 80 too early because “the site should only work over HTTPS.” In practice, the HTTP port is usually left open, but a redirect is configured: the user visits http://example.com, and the server redirects them to https://example.com.

If port 443 is closed, the certificate may still be issued, but the site will not be accessible over HTTPS. If port 80 is closed, issuing or renewing the certificate via an HTTP challenge may fail.

Therefore, before installing SSL, you need to check three things: the domain points to the VPS, the web server responds over HTTP, and the firewall allows traffic on ports 80 and 443. After that, you can proceed with preparing the server and installing the certificate.

What to Prepare Before Installing SSL

The domain must point to the VPS IP address

Before installing an SSL certificate, make sure the domain already points to the VPS. To do this, the domain’s DNS zone must contain an A record with the server’s IPv4 address. If IPv6 is used, an AAAA record must also be configured.

For example, for the domain example.com, the A record must point to your VPS IP address: example.com → 203.0.113.10

If a certificate is also required for the www version, a separate record must also exist for www.example.com: www.example.com → 203.0.113.10

You can check where the domain currently points using dig:

dig +short example.com

dig +short www.example.com

Or using nslookup: nslookup example.com

If the response shows an IP address other than your VPS IP address, certificate issuance may fail. Let’s Encrypt will try to access the domain, reach a different server, and be unable to complete validation.

You should also take DNS propagation time into account. After records are changed, the domain does not start pointing to the new IP address immediately. Wait until the changes have propagated.

The web server must respond over HTTP

After DNS is configured, verify that the web server on the VPS responds over HTTP. For Let’s Encrypt, the domain must be reachable from the internet, and requests must reach Nginx or Apache. Naturally, HTTPS will not work until a certificate is installed.

You can check this in a browser: http://example.com

Or with curl: curl -I http://example.com

If the server returns a 200, 301, or 302 status code, that is already a good sign. It means the domain is reachable, the web server is accepting requests, and it is returning a response.

If you get a connection error, a timeout, or a page from another site instead of a response, fix the basic configuration first. Certbot should not be the first diagnostic tool you use. Plain HTTP must work first.

It is important to check both the apex domain and www if the certificate is being issued for both versions:

curl -I http://example.com

curl -I http://www.example.com

If one version works and the other does not, Certbot may issue a certificate for only some of the domains or fail during validation.

The firewall must allow traffic on ports 80 and 443

Even if DNS is configured correctly and the web server is installed, SSL will not work if the ports are closed.

HTTP requires port 80, and HTTPS requires port 443. These ports must be open both on the server itself and in the provider’s firewall if the VPS has separate network rules in the cloud control panel.

On Ubuntu with UFW, you can check the status as follows: sudo ufw status

If Nginx is used, the following profile is often allowed: sudo ufw allow ‘Nginx Full’

For Apache: sudo ufw allow ‘Apache Full’

You can also open the ports explicitly:

sudo ufw allow 80/tcp

sudo ufw allow 443/tcp

Port 80 should not be closed after switching to HTTPS. It is often needed to redirect HTTP to HTTPS and to renew the certificate automatically using the HTTP challenge.

It is worth noting that, in addition to HTTP-01 (a request over port 80) and DNS-01 (DNS record validation), there is also the TLS-ALPN-01 validation method, which uses only port 443. However, this option is not suitable for everyone because it is more complex and requires the use of the special ALPN protocol. Therefore, the simplest option is to use HTTP-based validation.

If port 443 is closed, the site will not open over HTTPS even with a correctly issued certificate. If port 80 is closed, Certbot may fail domain validation or may be unable to renew the certificate in the future.

The site configuration must be working before SSL is installed

Certbot does not fix a broken site configuration. Before issuing a certificate, make sure that Nginx or Apache already knows which domain to serve and which directory to serve the site from.

For Nginx, the configuration is usually checked with this command: sudo nginx -t

If there are no errors, you can reload the web server: sudo systemctl reload nginx

For Apache, use: sudo apachectl configtest

Then reload the service: sudo systemctl reload apache2

If the site configuration is broken, Certbot may not find the required virtual host, may fail to apply the SSL settings correctly, or may issue a certificate, but the site still will not load.

Before installing SSL, check the following:

  • The domain is specified in the web server configuration;
  • The site opens over HTTP;
  • There are no errors in the Nginx or Apache configuration;
  • The document root points to the correct directory;
  • The www and non-www versions are configured deliberately;
  • Old redirects do not interfere with Let’s Encrypt validation.

Once DNS, HTTP, the firewall, and the site configuration are in order, you can proceed with installing SSL through Certbot. The process differs slightly for Nginx and Apache, but the logic remains the same: Certbot validates the domain, issues the certificate, and configures the web server to use it.

Installing SSL on a VPS with Nginx

Installing Certbot

For Nginx, Certbot is most commonly used with the Nginx plugin. It can automatically detect the site configuration, issue a Let’s Encrypt certificate, apply the SSL settings, and, if needed, add a redirect from HTTP to HTTPS.

On Ubuntu/Debian, Certbot is often installed via apt:

sudo apt update

sudo apt install certbot python3-certbot-nginx

After installation, it is a good idea to make sure that Nginx is running and that the site configuration contains no errors:

sudo nginx -t

sudo systemctl status nginx

If nginx -t reports an error, you need to fix the configuration first. Otherwise, Certbot may not find the required server block or may be unable to update the settings safely.

Before issuing the certificate, also check that the correct domain is specified in the Nginx configuration: server_name example.com www.example.com;

These are the exact names you will then need to pass to Certbot using the -d option.

Issuing a Certificate for a Domain

Once DNS, the firewall, and the Nginx configuration are ready, you can start issuing the certificate.

For a domain without www, use the following command: sudo certbot –nginx -d example.com

If you need a certificate for both the root domain and the www version, specify both names: sudo certbot –nginx -d example.com -d www.example.com

Certbot will validate the domain with Let’s Encrypt, issue the certificate, and offer to configure an HTTP-to-HTTPS redirect if this is applicable to your version and configuration.

After successful issuance, the certificates are usually stored in the Let’s Encrypt directory: /etc/letsencrypt/live/example.com/

It contains the main files:

fullchain.pem

privkey.pem

You usually do not need to specify these paths manually when using the certbot –nginx command. Certbot adds them to the Nginx configuration automatically. However, knowing their location is useful for troubleshooting and manual configuration.

After issuing the certificate, check the configuration and reload Nginx:

sudo nginx -t

sudo systemctl reload nginx

If Certbot exits with an error, do not repeat the command many times in a row. Let’s Encrypt limits the number of failed requests, and the address may be temporarily blocked. It is better to check DNS, open ports, server_name, HTTP access to the site, and the error logs first.

Checking HTTPS and redirects

After the certificate has been issued, verify that the site actually opens over HTTPS: curl -I https://example.com

The response should not contain a certificate error. If the server returns 200, 301, or 302, HTTPS is working.

Next, check the HTTP version: curl -I http://example.com

If redirection is enabled, the server should redirect the request to HTTPS. This is usually a 301 or 302 response with a Location: https://example.com/… header.

You should also check all domains listed in the certificate:

curl -I https://example.com

curl -I https://www.example.com

A common mistake is issuing a certificate only for example.com and then opening www.example.com. In this case, the browser may show a warning because www is not included in the certificate.

It is also worth opening the site in a browser and checking for mixed content warnings. These appear when the page itself is loaded over HTTPS, but images, scripts, stylesheets, or API requests are still loaded over HTTP.

Checking Automatic Renewal

Let’s Encrypt certificates are issued for a limited period, so they must be renewed regularly. Certbot usually configures automatic renewal through a systemd timer or cron, but you should still verify that it works.

To test automatic renewal, use a dry run: sudo certbot renew –dry-run

This command does not replace the live certificate; it checks whether Certbot can complete the renewal process. The official Certbot instructions also use sudo certbot renew –dry-run to verify automatic renewal.

If the dry run completes successfully, the basic renewal setup is working. If an error occurs, check DNS, the domain’s availability over HTTP, port 80, the Nginx configuration, and the method used to issue the certificate.

On a server with systemd, you can view the Certbot timers: systemctl list-timers | grep certbot

Or check the service status: systemctl status certbot.timer

After verifying automatic renewal, it is useful to record this in the project documentation: which domain is protected, where the Nginx configuration is located, how to check renewal, and who is responsible for SSL.

If HTTPS is working, the redirect is configured, the www and non-www versions have been checked, and certbot renew –dry-run completes without errors, the SSL setup for Nginx can be considered complete.

Installing SSL on a VPS with Apache

Installing Certbot

For Apache, Certbot is used with the Apache plugin. It helps issue a Let’s Encrypt certificate and automatically configure it for the appropriate virtual host.

On Ubuntu/Debian, Certbot and the Apache plugin are usually installed as follows:

sudo apt update

sudo apt install certbot python3-certbot-apache

Before issuing the certificate, check that Apache is installed, running, and has no configuration errors:

sudo apachectl configtest

sudo systemctl status apache2

If apachectl configtest returns an error, fix the configuration first. Certbot should not be run against a broken Apache configuration.

You should also make sure that a virtual host has been created for the site and that it specifies the required domain:

ServerName example.com

ServerAlias www.example.com

These are the domains that are then passed to Certbot using the -d parameter.

Issuing a Certificate for a Domain

Once DNS, the firewall, and the virtual host are ready, you can start issuing the certificate.

For a single domain, the command is: sudo certbot –apache -d example.com

If you need a certificate for both the main domain and the www version, specify both domains: sudo certbot –apache -d example.com -d www.example.com

Certbot will validate the domain through Let’s Encrypt, issue the certificate, and offer to configure an HTTP-to-HTTPS redirect if this is available for the current configuration.

After the certificate is issued successfully, Certbot usually adds the SSL settings to the Apache configuration automatically. Certificates are stored in the Let’s Encrypt directory:

/etc/letsencrypt/live/example.com/

Main certificate files:

fullchain.pem

privkey.pem

If the setup was performed using certbot –apache, you usually do not need to specify these paths manually. However, they may be useful for troubleshooting, manual configuration, or migrating the configuration.

After issuing the certificate, check Apache and reload the service:

sudo apachectl configtest

sudo systemctl reload apache2

If Certbot could not issue the certificate, first check DNS, that the site is accessible over HTTP, that port 80 is open, ServerName, ServerAlias, and that the virtual host is correct.

Checking HTTPS and redirects

After installing the certificate, verify that the site is accessible over HTTPS: curl -I https://example.com

If everything is configured correctly, the server will return a response without a certificate error. Typically, this will be 200, 301, or 302.

Next, check the HTTP version: curl -I http://example.com

If the redirect to HTTPS is enabled, the response should contain a 301 or 302 status code, and the Location header should contain a URL with https://.

Separately, check all domain variants that are expected to work:

curl -I https://example.com

curl -I https://www.example.com

If the certificate was issued only for example.com, but the site is also accessible at www.example.com, the browser may display an error. For this reason, it is best to plan the www and non-www versions in advance.

After installing SSL, you should also open the site in a browser and check for mixed content. If the page loads over HTTPS but images, stylesheets, scripts, or API requests are loaded over HTTP, the browser may show a warning or block some of the content.

Checking automatic renewal

Let’s Encrypt certificates must be renewed regularly. Certbot usually sets up automatic renewal via a systemd timer or cron, but you should always verify this after installing SSL.

Use the following command to test it: sudo certbot renew –dry-run

This simulates certificate renewal and shows whether Certbot can complete domain validation without actually replacing the certificate.

If the dry run completes successfully, automatic renewal is most likely configured correctly. If an error occurs, check that the domain is accessible, port 80 is open, DNS is configured correctly, the Apache virtual host is set up properly, and redirects are working.

On a server with systemd, you can check the Certbot timer as follows: systemctl list-timers | grep certbot

Or with: systemctl status certbot.timer

After the check, it is useful to record in the project documentation which domains are covered by the certificate, where the Apache virtual host is located, and how to verify automatic renewal.

If HTTPS works, HTTP correctly redirects to HTTPS, all domain variants are included in the certificate, and certbot renew –dry-run completes without errors, the SSL installation for Apache can be considered complete.

Installing an SSL Certificate via the VPS Control Panel

How this typically works in a control panel

In a VPS control panel, installing SSL is usually simpler than doing it from the console. The user opens the site settings, selects the option to issue a Let’s Encrypt SSL certificate, specifies the domain, and starts the installation.

Internally, the logic remains the same: the panel contacts Let’s Encrypt, completes domain validation, obtains the certificate, and adds it to the web server configuration.

A control panel usually allows you to:

  • Select a site or domain;
  • Enable SSL;
  • Issue a Let’s Encrypt certificate;
  • Add the www version of the domain;
  • Enable an HTTP-to-HTTPS redirect;
  • Configure automatic renewal;
  • View the certificate expiration date.

In HestiaCP, CyberPanel, aaPanel, and other control panels, the item names may differ, but the overall workflow is similar: the site must first exist in the panel, then the domain is linked to it, and after that the certificate is issued.

A control panel is convenient because you do not need to edit Nginx or Apache configuration files manually. However, it does not remove the basic requirements: the domain must point to the VPS, the web server must respond, and ports 80 and 443 must be open.

What to check after the certificate is issued

After a success message appears in the control panel, do not assume the task is complete right away. The certificate may have been issued, but redirects, domains, or page content may still not be working correctly.

First, open the site over HTTPS: https://example.com

Then check the HTTP version: http://example.com

If redirects are enabled, HTTP should automatically redirect to HTTPS.

Also check both versions of the domain, if they are used:

https://example.com
https://www.example.com

If the certificate was issued only for example.com, but the site is accessed as www.example.com, the browser may display a certificate error.

After that, check the following:

  • The certificate expiration date is displayed correctly;
  • Auto-renewal is enabled in the control panel;
  • HTTP redirects to HTTPS;
  • The www and non-www versions work as intended;
  • There is no redirect loop;
  • The browser does not show a mixed content warning;
  • Forms, images, stylesheets, scripts, and API requests work over HTTPS.

If the control panel shows that the certificate is installed but the browser still says “Not secure,” the cause is often not Let’s Encrypt. The issue may be mixed content, an incorrect domain, caching, redirects, or an old certificate that the web server is still serving.

Why the control panel does not remove the need to check DNS and ports

The control panel simplifies SSL certificate issuance, but it cannot bypass Let’s Encrypt rules. For a certificate to be issued, the domain must still pass validation.

If the domain points to a different IP address, the control panel will not be able to prove control over the required server. Let’s Encrypt will connect to the domain, reach something other than your VPS, and the validation will fail.

If port 80 is closed, the HTTP challenge may fail. If port 443 is closed, the certificate may be installed, but the website will not open over HTTPS.

Therefore, before installing SSL through the control panel, you still need to check:

dig +short example.com

curl -I http://example.com

And make sure the firewall allows the required ports: sudo ufw status

If the provider has a separate cloud firewall or security group, you need to check the rules not only inside the VPS, but also in the provider’s control panel.

Another common issue is that the website has been created in the control panel, but the domain is not mapped to the correct virtual host. In this case, requests reach the server, but are routed to the wrong site or to the default page.

For this reason, it is better to treat the control panel as a convenient interface, not as a replacement for troubleshooting. If DNS, HTTP, ports, and the site configuration are correct, issuing SSL through the control panel usually completes quickly. If even one of these elements is broken, the “Install SSL” button will not solve the problem on its own.

Let’s Encrypt wildcard certificate

A standard SSL certificate is issued for specific domains, such as example.com and www.example.com. If you have many subdomains, this approach becomes inconvenient: each new app.example.com, api.example.com, or client.example.com must be added separately.

In such cases, a wildcard certificate is used. It secures a set of subdomains at the same level all at once.

When you need a wildcard certificate

A wildcard certificate is needed when a project has many subdomains or when subdomains are created regularly.

For example: *.example.com

This certificate will work for:

app.example.com

api.example.com

dev.example.com

client1.example.com

client2.example.com

This is convenient for SaaS projects, customer portals, test environments, APIs, staging servers, and services where subdomains are created dynamically.

However, a wildcard certificate covers only one level of subdomains. A certificate for *.example.com will cover api.example.com, but not v1.api.example.com. For that nested subdomain, you need a separate certificate or another wildcard certificate for the required level.

Also, a wildcard does not replace a certificate for the root domain. If you need to protect both example.com and all subdomains, you typically specify both names: -d example.com -d "*.example.com"

Why wildcard certificates require a DNS challenge

For a standard certificate, the HTTP-01 challenge is often used: Let’s Encrypt connects to the site over HTTP and checks a special file on the server.

This approach does not work for wildcard certificates. Let’s Encrypt cannot verify every possible subdomain over HTTP, because there may be an unlimited number of subdomains. For this reason, wildcard certificates use the DNS challenge.

In this scenario, you need to add a special TXT record to the domain’s DNS zone. This allows Let’s Encrypt to verify that you control the domain’s DNS, not a specific web server.

A Certbot command for a manual DNS challenge might look like this: sudo certbot certonly –manual –preferred-challenges dns -d example.com -d “*.example.com”

After you run it, Certbot will display the TXT record that you need to add to DNS. It is usually created for a name in this format: _acme-challenge.example.com

After adding the record, you need to wait for DNS to update before continuing with certificate issuance.

The main drawback of a manual DNS challenge is that it is difficult to automate for renewals. Manually adding a TXT record every time a certificate is renewed cannot be considered a normal production scenario, but if your DNS server, whether provided by your registrar or self-hosted, supports automation, DNS-01 validation can significantly simplify site operations, especially for internal sites.

What to consider when auto-renewing a wildcard certificate

A wildcard certificate must be renewed in the same way as a regular certificate. However, because of the DNS challenge, automatic renewal is more complex.

For renewal to work without manual intervention, Certbot must be able to automatically create and delete TXT records in the domain’s DNS zone. To do this, use a DNS plugin for the specific DNS provider or a separate ACME client with API support.

The logic is as follows:

  1. Certbot starts the certificate renewal.
  2. The DNS plugin creates the _acme-challenge TXT record.
  3. Let’s Encrypt verifies the DNS record.
  4. The certificate is renewed.
  5. The TXT record is deleted or updated.

Before using a wildcard certificate, check whether your DNS provider supports an API and whether a suitable plugin is available for it. If there is no API, auto-renewing a wildcard certificate may become a manual procedure every few months.

It is also important to store the DNS API token securely. Such a token may provide access to manage the DNS zone, so it must not be left in plaintext, committed to Git, or shared with contractors without restrictions.

After configuring the wildcard certificate, be sure to test automatic renewal: sudo certbot renew –dry-run

If the dry run fails, the wildcard certificate has technically been issued, but after some time it may expire and break HTTPS for all subdomains.

A wildcard certificate is useful when there are many subdomains. However, if a project has only one or two subdomains, it is simpler to issue a regular certificate for the specific names and avoid complicating the setup with a DNS challenge.

Automatic SSL Certificate Renewal

Let’s Encrypt certificates are issued for a limited period, so they must be renewed regularly. Manually tracking the expiration date is inconvenient and unsafe: if you forget to renew the certificate, the site will start showing an HTTPS error.

For this reason, after installing SSL, it is important to check automatic renewal right away. The certificate should not only be issued once, but also be renewed without manual intervention.

How Certbot renew works

Certbot stores information about issued certificates and can renew them with the following command:

sudo certbot renew

This command checks the installed certificates and updates those that will need renewal soon. Certbot typically does not reissue a certificate every time; it renews only certificates that meet the renewal criteria.

On most modern systems, automatic renewal is run via a systemd timer or cron. This means the administrator does not need to run certbot renew manually every day.

You can check the timer as follows: systemctl list-timers | grep certbot

Or like this: systemctl status certbot.timer

If cron is used, you can look for the job in the system cron directories or in the Certbot package configuration. The exact setup depends on the distribution and how Certbot was installed.

Important: automatic renewal updates the certificate, but the site must start using the new certificate. Certbot usually performs the required reload operations for Nginx or Apache itself, but this is also worth verifying.

How to test automatic renewal

You should test automatic renewal immediately after setting up SSL, not the day before the certificate expires.

Use a dry run for this: sudo certbot renew –dry-run

This command simulates certificate renewal. It follows almost the same path as a normal renewal, but does not replace the live certificate.

If the dry run completes successfully, it means Certbot can validate the domain, obtain a test certificate, and perform the renewal procedure.

After a successful check, make sure the web server continues to run:

sudo nginx -t

sudo systemctl reload nginx

For Apache:

sudo apachectl configtest

sudo systemctl reload apache2

Then you can check HTTPS: curl -I https://example.com

It is also useful to view the list of certificates: sudo certbot certificates

This lets you see which domains are included in the certificate, where the files are stored, and when the certificate expires.

What to do if renewal fails

If certbot renew –dry-run ends with an error, do not ignore the issue. It means the certificate may also fail to renew when the actual renewal runs.

Start by reading the error message. The cause is often not Certbot itself, but the surrounding environment:

  • The domain no longer points to the VPS IP address;
  • Port 80 is closed;
  • The HTTP redirect is broken;
  • The web server is not serving the ACME challenge;
  • The Nginx or Apache configuration has changed;
  • The certificate was issued for an old domain;
  • The wildcard certificate cannot be renewed without a DNS API;
  • A firewall or security group is blocking Let’s Encrypt requests.

For standard certificates using the HTTP challenge, it is especially important that the domain be reachable over HTTP. If all HTTP traffic is blocked or redirected incorrectly, validation may fail.

For wildcard certificates, the DNS challenge must be checked separately. If Certbot cannot automatically create the TXT record through the DNS API, renewal will not work without manual intervention.

After fixing the issue, run the dry run again: sudo certbot renew –dry-run

Only after it succeeds should you consider automatic renewal configured.

Automatic SSL renewal is not just a convenience feature. It is part of standard VPS operations. If the certificate expires, the site may remain technically accessible, but browsers will start showing warnings, and users will consider the resource unsafe.

A good practice is to configure monitoring to send notifications when the certificate is approaching expiration and when the certificate changes, so you can take action in advance if the certificate is not renewed on time.

Common Errors When Installing SSL on a VPS

Port 80 or 443 is not open

One of the most common causes of errors when issuing an SSL certificate is port 80 being closed. It is required for the HTTP-01 challenge, where Let’s Encrypt verifies the domain using a standard HTTP request.

If port 80 is blocked by a firewall, the provider’s security group, or server settings, Certbot will not be able to verify control of the domain. As a result, the certificate will not be issued or renewed.

Port 443 is required for HTTPS itself. If it is closed, the certificate may be installed correctly, but the website still will not open over a secure connection.

You need to check two levels:

  • The firewall inside the VPS;
  • Network rules in the cloud provider’s control panel.

On Ubuntu with UFW, you can view the rules as follows: sudo ufw status

Then, if necessary, open the ports:

sudo ufw allow 80/tcp

sudo ufw allow 443/tcp

After that, check the site again over HTTP and HTTPS. If requests are not reaching the web server, it is too early to start issuing the SSL certificate.

The domain resolves to the wrong IP address

The second common error is that the domain’s DNS record points to the wrong server. The user runs Certbot on their VPS, but when Let’s Encrypt validates the domain, it reaches a different IP address.

This can happen after a site migration, a VPS change, an error in the DNS zone, or an attempt to issue a certificate immediately after changing DNS records.

You can check the current IP address as follows:

dig +short example.com

dig +short www.example.com

If the domain is supposed to work both with and without www, you need to check both versions. They may point to different IP addresses, or one of the records may be missing.

You should also keep DNS propagation in mind. After an A record or AAAA record is changed, the update is not always immediate. Sometimes you need to wait until different DNS resolvers start returning the new records.

If the domain does not point to the VPS, Certbot will not be able to pass validation. First, fix the DNS, wait for the records to update, and only then run the certificate issuance again.

Broken HTTP → HTTPS Redirect

A redirect from HTTP to HTTPS is almost always needed, but it is easy to misconfigure.

The problem can appear in different ways: an infinite redirect loop, a redirect to the wrong domain, a redirect from www to non-www without taking the certificate into account, or a redirect occurring before Let’s Encrypt has been able to complete the HTTP challenge.

You can check the redirect with curl: curl -I http://example.com

If everything is working correctly, the server will usually return 301 or 302 and a Location header with an HTTPS URL:

Location: https://example.com/

However, the redirect must be logically consistent. If http://example.com redirects to https://www.example.com, then www.example.com must also be included in the certificate. If the redirect points to another domain, the certificate must be issued for that domain.

Pay particular attention when checking sites behind a reverse proxy, CDN, or load balancer. In these setups, a redirect loop can occur because one layer treats the connection as HTTP while another is already using HTTPS.

The certificate was issued for the wrong domain

An SSL certificate is valid only for the domain names specified when it was issued. If a certificate is issued for example.com, it will not automatically cover www.example.com, api.example.com, or any other domain.

You can check the list of Certbot certificates as follows: sudo certbot certificates

This will show which domains are included in the certificate and when it expires.

A common scenario is that a site is available as both example.com and www.example.com, but the certificate was issued for only one version. In the browser, this may appear as a security error for one of the domain variants.

To avoid this issue, plan the domains in advance. For example: sudo certbot –nginx -d example.com -d www.example.com

Or for Apache: sudo certbot –apache -d example.com -d www.example.com

If subdomains are used, they must also be specified separately, or you can use a wildcard certificate if there are many subdomains.

Running the certificate issuance/renewal command too often

Let’s Encrypt applies rate limits to certificate requests. In particular, if domain validation fails more than 5 times per hour, the address is blocked and you must wait for it to be unblocked.

Therefore, you should carefully read the error messages, check the web server configuration and network access settings, and only then run the command again.

For debugging, you can use the ACME v2 staging environment with the –test-cert or –dry-run options. The limits there are significantly higher; for example, authorization failures are limited to 200 per hour instead of 5.

However, even if renewal completes without errors, you should not run it too often: the limit for issuing certificates with the same set of names is no more than 5 per week. In most cases, renewing certificates once every 1.5–2.5 months is sufficient.

Auto-renewal not verified

After SSL has been installed successfully, it is easy to assume that everything is ready. However, a Let’s Encrypt certificate must be renewed. If auto-renewal is not working, the problem will appear later, when the certificate expires.

Therefore, after installation, you should always run: sudo certbot renew –dry-run

If the check completes successfully, Certbot will be able to renew the certificate in the future. If an error occurs, it should be fixed immediately rather than left until the certificate expiration date.

The causes of auto-renewal failures are often the same as during initial issuance:

  • The domain no longer points to the VPS;
  • Port 80 is closed;
  • The web server configuration has changed;
  • The redirect is broken;
  • The required virtual host has been deleted;
  • A wildcard certificate cannot be renewed without a DNS API.

You should also check that the server has a systemd timer or cron job for Certbot: systemctl list-timers | grep certbot

Auto-renewal cannot be considered configured simply because Certbot is installed. It must be verified with a dry run, and the certificate expiration date should be checked periodically.

Mixed content remains after SSL installation

Even if the certificate is installed correctly, the site may still show a browser warning. A common cause is mixed content.

Mixed content occurs when a page is loaded over HTTPS, but some resources are still loaded over HTTP. These can include images, CSS, JavaScript, fonts, iframes, videos, API requests, or external widgets.

For example, the page opens as: https://example.com

But an image on it is loaded as: http://example.com/uploads/image.jpg

The browser may block that resource or show a warning that the connection is not fully secure.

After installing SSL, you need to check the page source, the browser console, and the CMS settings. In WordPress, for example, you often need to update the site address, replace old HTTP links in the database, and check caching plugins.

You should also check external resources: CDNs, analytics, widgets, fonts, iframes, and APIs. If an external service does not support HTTPS, it is better to replace it or remove it.

Installing SSL is not just about issuing a certificate. The site must fully switch to HTTPS: pages, stylesheets, scripts, images, forms, APIs, and all internal links.

When the ports are open, DNS points to the correct IP address, redirects are working, the certificate has been issued for the required domains, auto-renewal has been verified, and mixed content has been fixed, the SSL configuration can be considered complete.

Conclusion

Installing SSL on a VPS is not just a matter of running a Certbot command or clicking a button in a control panel. A certificate is issued for a specific domain, and the entire chain must work correctly: DNS, the web server, open ports, the ACME challenge, HTTPS configuration, and automatic renewal.

For Nginx and Apache, the easiest approach is to use Certbot with the appropriate plugin. It can issue a Let’s Encrypt certificate, configure it on the web server, and help set up a redirect from HTTP to HTTPS.

If the VPS is managed through a control panel, issuing an SSL certificate is usually simpler: the certificate can be installed through the interface. However, a control panel does not remove the need for basic diagnostics. The domain must still point to the correct IP address, the web server must respond over HTTP, and ports 80 and 443 must be open.

Not every project needs a wildcard certificate. It is useful when a project has many subdomains, but it requires a DNS challenge and more careful automatic renewal configuration.

After installing SSL, the main thing is not to stop at the fact that the certificate has been issued. You need to check HTTPS, the redirect, the domains in the certificate, mixed content, and automatic renewal using certbot renew –dry-run.

If all of this works, SSL can be considered properly configured: the site opens over HTTPS, the browser does not show warnings, and the certificate can be renewed without manual intervention.

FAQ

Can I set up SSL on a VPS for free?

Yes. Let’s Encrypt is a free, automated certificate authority that lets you issue SSL/TLS certificates for domains. Certbot is typically used for installation on a VPS, or certificates can be issued using the built-in certificate issuance feature in the control panel.

The certificate itself is free, but configuration work is still required: DNS, the web server, the firewall, redirects, automatic renewal, and mixed content checks.

Is port 80 required for Let’s Encrypt?

Yes, if the HTTP-01 challenge is used. In this scenario, Let’s Encrypt connects to the domain over HTTP and checks a special file on the server. For this to work, port 80 must be accessible from the outside.

After SSL is installed, port 80 is usually not closed; instead, it is used to redirect HTTP traffic to HTTPS. Closing it without understanding the setup can break certificate issuance or renewal.

How does an HTTP challenge differ from a DNS challenge?

An HTTP challenge verifies control over a domain through a web server. Let’s Encrypt connects to the site over HTTP and checks whether the server can serve the required validation file.

A DNS challenge verifies control over a DNS zone. To do this, you need to add a special TXT record to DNS. This method is suitable for wildcard certificates and for situations where the web server should not be directly accessible from the internet.

In simple terms, an HTTP challenge validates the site through port 80, while a DNS challenge validates the domain through a DNS record.

When do you need a wildcard certificate?

A wildcard certificate is needed when you need to secure multiple subdomains at the same level. For example, *.example.com covers app.example.com, api.example.com, dev.example.com, and other similar subdomains.

However, it does not automatically cover the apex domain. If you need to secure both example.com and all subdomains, you typically specify both names: example.com and *.example.com.

Let’s Encrypt issues wildcard certificates, but they require the DNS-01 challenge.

Why does the website still show “Not secure” after installing SSL?

There may be several reasons. The certificate may have been issued for a different domain, the site may be opening with www while the certificate covers only the non-www version, or the browser may be detecting mixed content.

Mixed content occurs when a page is loaded over HTTPS but some resources are loaded over HTTP, such as images, stylesheets, scripts, fonts, iframes, or API requests.

It is also worth checking redirects, the browser cache, the CDN, CMS settings, and which certificate the web server is actually serving.

How do I check Certbot auto-renewal?

Use the following command to check it: sudo certbot renew –dry-run

This simulates certificate renewal and shows whether Certbot can complete the renewal process without actually replacing the production certificate. In the official Certbot documentation, this command is used specifically to test automatic renewal.

You can also check the systemd timer: systemctl list-timers | grep certbot

If the dry run completes successfully, auto-renewal is configured correctly. If an error occurs, it should be fixed before the certificate expires.

Can Let’s Encrypt be used for multiple domains on a single VPS?

Yes. You can use Let’s Encrypt for multiple domains and websites on a single VPS. Each domain must point to that VPS, and the web server must correctly serve the corresponding virtual host or server block.

For example, for a single website, you can issue a certificate for two names at once: sudo certbot –nginx -d example.com -d www.example.com

A single certificate can potentially include up to 100 additional names.

For another website on the same VPS, you can issue a separate certificate. The key is not to mix up domains, web server configurations, and certificate paths.

Sources

1. Let’s Encrypt — Getting Started

2. Let’s Encrypt — Challenge Types

3. Let’s Encrypt — FAQ

4. Certbot — Instructions and automatic renewal check

Subscribe to our newsletter and receive articles and news

    Check out our other materials