Apache with Let’s Encrypt Certificates on CentOS 8

I read that Let’s Encrypt is a free, automated, and open certificate for web server and other usages. How do I secure Apache with Let’s Encrypt Certificates on CentOS 8?

Let’s Encrypt is a free, automated, and open certificate authority for your website powered by the Apache webserver. This page shows how to use Let’s Encrypt to install a free SSL certificate for Apache webserver. You will learn how to properly deploy Diffie-Hellman on your server to get SSL labs A+ score on a CentOS Linux 8.
Tutorial requirements
Operating system/appCentOS 8 + Apache 2
Root privileges required Yes
Difficulty Intermediate (rss)
Estimated completion time 15m
Table of contents


How to secure Apache with Let’s Encrypt Certificates on CentOS 8

The procedure is as follows to obtaining an SSL certificate:

  1. Install SSL/TLS module for the Apache HTTP server in CentOS 8: sudo yum install mod_ssl
  2. Get acme.sh software, run git clone https://github.com/Neilpang/acme.sh.git
  3. Create a new /.well-known/acme-challenge/ directory using: mkdir -p /var/www/html/.well-known/acme-challenge/
  4. Obtain an SSL certificate your domain: acme.sh --issue -w /DocumentRootPath/ -d your-domain
  5. Configure TLS/SSL for Apache on CentOS Linux 8: vi /etc/httpd/conf.d/ssl.conf
  6. Setup a cron job for auto renewal of SSL/TLS certificate
  7. Open port 443 (HTTPS) using firewall :sudo firewall-cmd --add-service=https

Our sample setup is as follows

My sample Let’s Encrypt SSL certificate to secure Apache on CentOS 8
Apache with Let's Encrypt Certificates on CentOS 8
Let us see how to install acme.sh client and use it on a CentOS 8 to get an SSL certificate from Let’s Encrypt. Before you start apply all patches on CentOS 8:
sudo yum update

Step 1 – Install mod_ssl for the Apache

Type the following yum command:
$ sudo yum install mod_ssl
Installing mod_ssl on CentOS 8 Linux

Step 2 – Install acme.sh Let’s Encrypt client

You need to install wget on CentOS 8, curl, bc, socat and git client on CentOS 8 in order use acme.sh, run:
$ sudo yum install wget curl bc git socat

Last metadata expiration check: 0:06:51 ago on Wednesday 02 October 2019 05:49:51 PM UTC.
Package wget-1.19.5-7.el8_0.1.x86_64 is already installed.
Package curl-7.61.1-8.el8.x86_64 is already installed.
Dependencies resolved.
 Package                  Arch           Version                 Repository         Size
 git                      x86_64         2.18.1-3.el8            AppStream         186 k
 socat                    x86_64           AppStream         298 k
 bc                       x86_64         1.07.1-5.el8            BaseOS            129 k
Installing dependencies:
 git-core                 x86_64         2.18.1-3.el8            AppStream         4.1 M
 git-core-doc             noarch         2.18.1-3.el8            AppStream         2.3 M
 perl-Error               noarch         1:0.17025-2.el8         AppStream          46 k
 perl-Git                 noarch         2.18.1-3.el8            AppStream          77 k
 perl-TermReadKey         x86_64         2.37-7.el8              AppStream          40 k
 emacs-filesystem         noarch         1:26.1-5.el8            BaseOS             69 k
Transaction Summary
Install  9 Packages
Total download size: 7.1 M
Installed size: 38 M
Is this ok [y/N]: y

Clone the repo

Execute the following commands:
$ cd /tmp/
$ git clone https://github.com/Neilpang/acme.sh.git

Next, install acme.sh client on to your system, run:
$ cd acme.sh/
$ sudo -i
# cd acme.sh/
# ./acme.sh --install

Set up Apache with Let's Encrypt Certificates on CentOS 8
Now we have needed software on the CentOS 8 server. You must close the current terminal or ssh session and reopen again to make the alias take effect. Or type the following source command:
$ sudo source ~/.bashrc
Verify that acme.sh working, run:
# acme.sh --version
Sample outputs:


Step 3 – Create acme-challenge directory

Type the following mkdir command. Make sure you set $D to actual DocumentRoot path as per your needs:
# D=/var/www/html/
# mkdir -vp ${D}/.well-known/acme-challenge/
###---[ NOTE: Adjust permission as per your setup ]---###
# chown -R apache:apache ${D}/.well-known/acme-challenge/
# chmod -R 0555 ${D}/.well-known/acme-challenge/

Also, create a directory to store SSL certificate:
# mkdir -p /etc/httpd/ssl/cyberciti.biz/

Step 4 – Create dhparams.pem file

Run the openssl command:
# cd /etc/httpd/ssl/cyberciti.biz/
# openssl dhparam -out dhparams.pem -dsaparam 4096

Step 3 and 4 openssl

How to speed up OpenSSL/GnuPG Entropy For Random Number Generation On Linux

Turn on Apache service if not eanbled

Is Apache running? If not start the Apache service it as follows using the systemctl command:
$ sudo systemctl status httpd.service
$ sudo systemctl enable httpd.service
$ sudo systemctl start httpd.service
$ sudo systemctl status httpd.service

CentOS 8 enable and start httpd.service command

Make sure TCP port 80 opend too

Run the following firewall-cmd command to turn on TCP port 80 on CentOS 8:
$ sudo firewall-cmd --permanent --add-service=http --zone=public
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --list-services --zone=public

Step 5 – Obtain a SSL/TLS certificate for domain

Issue a certificate for your domain. The syntax is:
# acme.sh --issue -w /path/to/www/htmlRoot/ -d your-domain-example-com -k 2048
# acme.sh --issue -w /path/to/www/htmlRoot/ -d www.cyberciti.biz -k 4096
# acme.sh --issue -w /var/www/html/ -d centos8.cyberciti.biz -k 4096

Create a free Apache SSL certificate with Let'ss Encrypt on CentOS 8 Linux

Step 6 – Configure Apache to use SSL/TLS

Edit the file named /etc/httpd/conf.d/ssl.conf using a text editor such as vi command:
$ sudo vi /etc/httpd/conf.d/ssl.conf
Append/update as follows:

### Start config for port 443 #
Listen 443 https
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache         shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout  300
SSLCryptoDevice builtin
### Turn on HTTP2 support #
Protocols h2 http/1.1
### Redirect all http urls to https #
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]
# SSL/TLS config for domain centos8.cyberciti.biz #
<VirtualHost centos8.cyberciti.biz:443>
        ### Log files  #
        ErrorLog logs/ssl_error_log
        TransferLog logs/ssl_access_log
        LogLevel warn
        SSLEngine on
        ### No more SSL3/2 #
        SSLProtocol             all -SSLv3
        SSLHonorCipherOrder on
        SSLCompression          off
        SSLSessionTickets       off
        ### Path to certs #
        SSLCertificateFile      /etc/httpd/ssl/cyberciti.biz/centos8.cyberciti.biz.cer
        SSLCertificateKeyFile   /etc/httpd/ssl/cyberciti.biz/centos8.cyberciti.biz.key
        #Forward Secrecy & Diffie Hellman ephemeral parameters
        SSLOpenSSLConfCmd DHParameters "/etc/httpd/ssl/cyberciti.biz/dhparams.pem"
        # HSTS (mod_headers is required) (15768000 seconds = 6 months)
        Header always set Strict-Transport-Security "max-age=15768000"
        <FilesMatch "\.(cgi|shtml|phtml|php)$">
            SSLOptions +StdEnvVars
        <Directory "/var/www/cgi-bin">
                SSLOptions +StdEnvVars
        BrowserMatch "MSIE [2-5]" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0
         CustomLog logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
### OCSP stapling config
SSLUseStapling          on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache        shmcb:/var/run/ocsp(128000)

Save and close the file and exit from vim text editor.

A note about more secure SSL options

Update above config as follows to disable SSL and TLS version 1/1.1. The following is general-purpose Apache servers with a variety of clients, recommended for almost all systems:

SSLProtocol             all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder     off

Please see this page for more info.

Step 7 – Install certificate

Type the following command:
# acme.sh --installcert -d centos8.cyberciti.biz \
--keypath /etc/httpd/ssl/cyberciti.biz/centos8.cyberciti.biz.key \
--fullchainpath /etc/httpd/ssl/cyberciti.biz/centos8.cyberciti.biz.cer \
--reloadcmd 'systemctl reload httpd'

Set up and secure Apache with Let's Encrypt certificates

Step 8 – Firewalld configuration on CentOS Linux 8 to open HTTPS tcp port 443

Now our Apache up and running with mod_ssl. It is time to open TCP port # 443 (HTTPS) on CentOS 8 server so that clients can connect to it. Update the rules as follows:
$ sudo firewall-cmd --permanent --add-service=https --zone=public
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --list-services --zone=public

Verify that port 443 and 80 open and listing state with the help of ss command along with the grep command/egrep command:
$ sudo ss -tulpn
$ sudo ss -tulpn | egrep ':(80|443)'

Sample outputs:

tcp    LISTEN   0        128                     *:443                 *:*       users:(("httpd",pid=12079,fd=9),("httpd",pid=12078,fd=9),("httpd",pid=12077,fd=9),("httpd",pid=10782,fd=9))
tcp    LISTEN   0        128                     *:80                  *:*       users:(("httpd",pid=12079,fd=4),("httpd",pid=12078,fd=4),("httpd",pid=12077,fd=4),("httpd",pid=10782,fd=4))

Step 9 – Test it

Make a test page called index.html:
sudo vi /var/www/html/index.html
Append the following html:

    	<title>CentOS8 Apache test server - nixCraft</title>
	<h2>Hello, world!</h2>
		I run on CentOS Linux 8. I act as a testbed for nixCraft test lab.
		I exist to help sysadmins and developers to help learn CentOS 8.
	<small>Apache 2 server running on CentOS 8 with Let's Encrypt</small>

Save and close the file. Fire a web browser and type your domain such as:
Test it with SSLlabs test site:
ssllabs a+ result for centos8

Step 10 – acme.sh commands

List all SSL/TLS certificates, run:
# acme.sh --list
Renew a cert for domain named server2.cyberciti.biz
# acme.sh --renew -d centos8.cyberciti.biz
Please note that a cron job will try to do renewal a certificate for you too. This is installed by default as follows (no action required on your part). To see job run:
# crontab -l
Sample outputs:

38 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

Upgrade acme.sh client:
# acme.sh --upgrade
Getting help:
# acme.sh --help | more


You just learned how to install a free SSL/TSL certificate from Let’s Encrypt to secure communication between Apache and browsers/clients, on a CentOS Linux 8 server. For more info see Apache mod_ssl documents here.

This entry is 6 of 13 in the Secure Web Server with Let's Encrypt Tutorial series. Keep reading the rest of the series:
  1. Set up Lets Encrypt on Debian/Ubuntu Linux
  2. Secure Lighttpd with Lets Encrypt certificate on Debian/Ubuntu
  3. Configure Nginx with Lets Encrypt certificate on Alpine Linux
  4. Nginx with Lets Encrypt on CentOS 7
  5. Apache with Lets Encrypt Certificates on RHEL 8
  6. CentOS 8 and Apache with Lets Encrypt Certificates
  7. Install Lets Encrypt certificates on CentOS 8 for Nginx
  8. Forcefully renew Let's Encrypt certificate
  9. OpenSUSE Linux and Nginx with Let's Encrypt Certificates
  10. Configure Nginx to use TLS 1.2 / 1.3 only
  11. Let's Encrypt wildcard certificate with acme.sh and Cloudflare DNS
  12. Nginx with Let's Encrypt on Ubuntu 18.04 with DNS Validation
  13. AWS Route 53 Let's Encrypt wildcard certificate with acme.sh
🐧 If you liked this page, please support my work on Patreon or with a donation.
🐧 Get the latest tutorials on SysAdmin, Linux/Unix, Open Source/DevOps topics:
CategoryList of Unix and Linux commands
File Managementcat
FirewallAlpine Awall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network Utilitiesdig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNAlpine CentOS 8 Debian 10 Firewall Ubuntu 20.04


Comments on this entry are closed.

Use HTML <pre>...</pre>, <code>...</code> and <kbd>...</kbd> for code samples.