Step-by-Step Guide to Install ACME SSL Certificates on Apache & NGINX
If you run a website or a web app, then HTTPS is a must. Without it, visitors see warnings, and trust disappears fast. At the core of HTTPS is an SSL/TLS certificate which proves your site is secure and that people can safely interact with it. Years ago, setting one up was a painful process, but today it’s much easier. Thanks to the ACME protocol and tools like Certbot, you can get a certificate in minutes and have it renew automatically.
This guide walks through exactly how to do that. We’ll cover the setup on Debian-based and Red Hat–based systems, along with Snap packages. You’ll see the commands you need and how to handle wildcard certificates and set up automatic renewal.
Prerequisites
Before we dive into installing Certbot and grabbing your SSL certificate. There are a couple of things you should have ready first. They don’t take long to check but skipping them is one of the most common reasons people run into errors later.
-
Sudo or Root Access
Certbot needs to configure your web server and write certificates to system directories. This means you’ll need administrative privileges. If you’re on a VPS or dedicated server, make sure you can run commands with sudo.
-
A Registered Domain with Correct DNS Records
Your domain should already be registered and pointing to your server. Create an A record in your DNS. This record should resolve your domain like example.com to its public IP address. If you are planning to use subdomains then make sure those DNS records are also set up.
-
Open Ports 80 and 443
ACME certificate validation requires inbound access on port 80/HTTP and 443/HTTPS. If you have a firewall enabled like UFW, Firewalld, or security groups in the cloud then confirm that both ports are open. Certbot won’t be able to complete the domain validation challenge without this.
Step 1 – Installing Certbot
The first step in securing your Apache or Nginx server with ACME SSL is installing Certbot. Certificate requests and renewals can be handled by this tool. It can be installed in several ways depending on your Linux distribution and package manager.
-
Installing Certbot with APT for Debian/Ubuntu
Certbot can be directly installed from APT repository if you’re running a Debian-based distribution like Ubuntu. Start by updating your package index
sudo apt update
Depending on your web server, install the correct Certbot plugin
-
For Apache
sudo apt install certbot python3-certbot-apache
-
For Nginx
sudo apt install certbot python3-certbot-nginx
-
-
Installing Certbot with DNF or YUM for CentOS, RHEL, Fedora
On Red Hat–based distributions, you’ll first need to enable the EPEL repository or Extra Packages for Enterprise Linux. This contains many additional utilities including Certbot.
sudo dnf install epel-release
or for older systems
sudo yum install epel-release
Next, refresh your repositories
sudo dnf clean all && sudo dnf update
or
sudo yum clean all && sudo yum update
Now install Certbot with the appropriate plugin
-
For Apache
sudo dnf install certbot python3-certbot-apache
or on older Yum-based systems
sudo yum install certbot python-certbot-apache
-
For Nginx
sudo dnf install certbot python3-certbot-nginx
or
sudo yum install certbot python-certbot-nginx
-
-
Installing Certbot with Snap
Snap is another universal method of installing Certbot. It often provides the latest version. If you’re on a system that supports Snap, this is a good choice.
First, install Snap, (if it’s not already installed
-
For Debian-based
sudo apt install snapd
-
for Red Hat-based
sudo dnf install snapd
Then install Certbot via snap
sudo snap install core sudo snap refresh core sudo snap install --classic certbot
Create a symlink to make Cerbot globally accessible
sudo ln -s /snap/bin/certbot /usr/bin/certbot
With Certbot installed, you’re ready to actually request and install your SSL certificate. The installation method doesn’t matter much once Certbot is set up. The commands for certificate issuance will look the same.
-
Step 2 – Request and Install Your ACME Certificate
The next step is to actually request and install your ACME SSL certificate. This process is slightly different depending on whether you are issuing a certificate for a single domain or multiple domains, or for a wildcard domain.
-
Standard Certificates for Single or Multi-Domain
Only a standard SSL certificate is required by most websites. This same certificate is used for main domain and a few subdomains. For example, ssl2buy.com, www.ssl2buy.com and maybe api.ssl2buy.com. Certbot makes this straightforward.
Here’s a common structure
sudo certbot --nginx \ --non-interactive \ --agree-tos \ --server <ACME_endpoint> \ --email <your-email> \ --eab-kid <EAB_ID> \ --eab-hmac-key <EAB_Key> \ --domain <DOMAINNAME> \ --cert-name <friendlyname>
Replace --nginx with --apache if you’re running Apache.
Let’s break down the important flags
- nginx / apache tells Certbot which web server to configure.
- non-interactive runs the process without user prompts (ideal for automation).
- agree-tos agrees to the CA’s terms of service automatically.
- email provides an email address for renewal notifications.
- server is the CA’s ACME endpoint, usually found in your certificate order details.
- eab-kid and eab-hmac-key are credentials provided by your CA for ACME authentication.
- domain is the domain you want the certificate to cover. You can repeat this flag multiple times for additional domains.
- cert-name is an optional friendly name to identify this certificate later.
Once this command completes successfully, Certbot will automatically configure your Apache or Nginx server to use the new certificate.
-
Wildcard Certificates using DNS Validation
Wildcard certificates like *.securedomain.com are a bit trickier. ACME requires DNS-01 validation for these, which means Certbot must create special DNS TXT records during the verification process. Unlike standard certificates, HTTP validation via port 80 won’t work here.
-
Using a Supported DNS Provider Plugin
Certbot has plugins for many popular DNS providers
- AWS Route53 -> certbot-dns-route53
- Google Cloud DNS -> certbot-dns-google
- DigitalOcean -> certbot-dns-digitalocean
- GoDaddy community plugin -> certbot-dns-godaddy
- Cloudflare via Lexicon or plugin
For example, on Ubuntu/Debian with DigitalOcean
sudo apt install python3-certbot-dns-digitalocean
Then create a credentials file
~/.secrets/certbot/digitalocean.ini dns_digitalocean_token = YOUR_DO_API_TOKEN chmod 600 ~/.secrets/certbot/digitalocean.ini
Now run Certbot with the plugin
sudo certbot certonly \ --dns-digitalocean \ --dns-digitalocean-credentials ~/.secrets/certbot/digitalocean.ini \ --server <ACME_endpoint> \ --domain *.example.com \ --eab-kid <EAB_ID> \ --eab-hmac-key <EAB_Key> \ --email <your-email> \ --agree-tos \ --cert-name example-wildcard
-
If No Plugin Exists
If your DNS provider doesn’t have a plugin then you can use the manual mode with hooks.
certbot certonly \ --manual \ --preferred-challenges dns \ --manual-auth-hook /path/to/auth.sh \ --manual-cleanup-hook /path/to/cleanup.sh \ --server <ACME_endpoint> \ --domain *.example.com \ --eab-kid <EAB_ID> \ --eab-hmac-key <EAB_Key> \ --email <your-email> \ --agree-tos \ --cert-name example-wildcard
- manual-auth-hook is the script that creates the DNS TXT record.
- manual-cleanup-hook is the script that removes the TXT record after validation.
-
You can either write these scripts yourself or use tools like Lexicon to manage DNS records via API.
Once the DNS challenge is verified, Certbot will issue the wildcard certificate. You’ll then need to manually configure Apache or Nginx to point to the new cert files which are usually stored under /etc/letsencrypt/live/ path.
Step 3 – Verifying the Installation
It is time to confirm that everything is actually working once you have requested and installed your certificate. It’s easy to assume Certbot did its job but a quick verification guarantees your site is serving traffic over HTTPS correctly.
-
Check Your Web Server Status
Make sure your web server is running without errors
- Apache for Debian-based
sudo systemctl status apache2
- Apache for Red Hat–based
sudo systemctl status httpd
- Nginx for any distro
sudo systemctl status nginx
If the service shows as “active (running),” your server is up and running with the new certificate.
- Apache for Debian-based
-
Verify the Certificate with OpenSSL
You can inspect the SSL handshake directly with openssl for a deeper check.
openssl s_client -connect yourdomain.com:443
Common Name and Subject Alternative Names (SAN) can be seen using this command. It’s a quick way to confirm that the certificate you expected is actually being served.
-
Browser Test
Open your domain in a browser using https://. You should see the familiar trust icon if everything was configured correctly. The certificate will show the issuing CA and expiration date if you click on it.
If something doesn’t look right like the site still serving HTTP, the wrong certificate showing or SSL errors in the browser then it usually points to one of three issues
- DNS not pointing to the correct server.
- Web server configuration not reloaded after installing the cert.
- Firewall or reverse proxy interfering.
Fix those, reload the service, and re-check.
Step 4 – Automating Certificate Renewal
You don’t need to keep track of expiration dates manually if you use ACME certificates with Certbot. It is one of the biggest advantages compared to other similar solutions. Organization administrators are usually stuck renewing certificates, as they typically last from a few days to a year. With certbot, this thing is automated and your site stays secure without any downtime.
-
Test a Renewal First
Before setting up automation, it’s a good idea to run a dry-run renewal. This checks whether everything is configured correctly without actually replacing your certificate
sudo certbot renew --dry-run
If this runs without errors, you’re ready to automate.
-
Automatic Renewal with systemd for modern Linux distros
Ubuntu 18.04+, CentOS 8+ and RHEL 8+ distributions use systemd timers to handle renewal automatically. You can check if it’s enabled with
systemctl list-timers | grep certbot
You should see an entry like
“Mon 2025-08-25 10:00:00 UTC 12h left n/a n/a certbot.timer certbot.service”It means Certbot is scheduled to run twice every day. If your certificate is within 30 days of expiring then it will be renewed automatically.
-
Automatic Renewal with Cron for older systems
You can use a cron job if your Linux distribution does not support systemd timers. Edit the crontab with
sudo crontab -e
Then add this entry to run renewal twice a day:
0 */12 * * * certbot renew --quiet --post-hook "systemctl reload nginx"
- quiet suppresses output unless there’s an error.
- post-hook reloads your web server only if a certificate was renewed.
For Apache, replace the post-hook with
--post-hook "systemctl reload apache2"
-
Renewal Hooks (Optional)
Sometimes you’ll need more than just a server reload. Maybe updating a load balancer, restarting a reverse proxy or syncing certs across multiple nodes. Certbot supports hooks for these cases
- /etc/letsencrypt/renewal-hooks/pre/ -> runs before renewal
- /etc/letsencrypt/renewal-hooks/deploy/ -> runs after a successful renewal
- /etc/letsencrypt/renewal-hooks/post/ -> runs after every attempt
Example deploy hook (/etc/letsencrypt/renewal-hooks/deploy/reload.sh)
#!/bin/bash systemctl reload nginx
Don’t forget to make it executable
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload.sh
Conclusion
Getting SSL running with Certbot is about making your site trustworthy for the people who use it. Once you see that secure sign in the browser and know renewals are handled, the whole thing becomes part of the background. That is the point of good infrastructure. It keeps working quietly while you focus on building, writing, or shipping whatever matters most to you.
Related Articles: