Apache with Let’s Encrypt Certificates on CentOS 8

ADVERTISEMENTS



How to secure 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.

The procedure is as follows to obtaining an SSL certificate:

Install SSL/TLS module for the Apache HTTP server in CentOS 8: sudo yum install mod_ssl Get acme.sh software, run git clone https://github.com/Neilpang/acme.sh.git Create a new /.well-known/acme-challenge/ directory using: mkdir -p /var/www/html/.well-known/acme-challenge/ Obtain an SSL certificate your domain: acme.sh --issue -w /DocumentRootPath/ -d your-domain Configure TLS/SSL for Apache on CentOS Linux 8: vi /etc/httpd/conf.d/ssl.conf Setup a cron job for auto renewal of SSL/TLS certificate 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



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



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 = ======================================================================================== Installing: git x86_64 2.18.1- 3 .el8 AppStream 186 k socat x86_64 1.7.3.2- 6 .el8 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 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 ========================================================================================= Installing: git x86_64 2.18.1-3.el8 AppStream 186 k socat x86_64 1.7.3.2-6.el8 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



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:

https://github.com/Neilpang/acme.sh v2.8.3 https://github.com/Neilpang/acme.sh v2.8.3

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



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



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



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 SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA: ! DSS ### 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 </ FilesMatch > < Directory "/var/www/cgi-bin" > SSLOptions +StdEnvVars </ Directory > 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" </ VirtualHost > ### OCSP stapling config SSLUseStapling on SSLStaplingResponderTimeout 5 SSLStaplingReturnResponderErrors off SSLStaplingCache shmcb: / var / run / ocsp ( 128000 ) ### 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 SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS ### 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 </FilesMatch> <Directory "/var/www/cgi-bin"> SSLOptions +StdEnvVars </Directory> 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" </VirtualHost> ### 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 SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 SSLHonorCipherOrder off SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384

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'



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 ) ) 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:

< html > < head > < title > CentOS8 Apache test server - nixCraft < / title > < / head > < body > < h2 > Hello, world! < / h2 > < p > 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. < / p > < hr > < small > Apache 2 server running on CentOS 8 with Let's Encrypt < / small > < / body > < / html > <html> <head> <title>CentOS8 Apache test server - nixCraft</title> </head> <body> <h2>Hello, world!</h2> <p> 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. </p> <hr> <small>Apache 2 server running on CentOS 8 with Let's Encrypt</small> </body> </html>

Save and close the file. Fire a web browser and type your domain such as:

https://centos8.cyberciti.biz



Test it with SSLlabs test site:

https://www.ssllabs.com/ssltest/analyze.html?d=centos8.cyberciti.biz



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

Conclusion

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.

