ag@linux:~$

history 32 of 36

Set Up an SSL Certificate on a CentOS Apache Web Server

Creating a key, CSR and self-signed certificate with OpenSSL, adding them to Apache mod_ssl on CentOS, and redirecting HTTP to HTTPS.

Written

From my Linux study notes, 2018. Some commands and versions here are old, so please reuse them carefully. Anything marked "added later", and the notes at the end, explain what has changed since.

These are my notes for adding SSL (HTTPS) to an Apache web server on CentOS using mod_ssl and a certificate made with OpenSSL. The certificate here is self-signed, which is fine for testing but not for a public website (see the notes at the end).

Before you start

  • Run the commands as root (or with sudo).

  • Apache (httpd) should already be installed and working over HTTP.

  • Back up any Apache config file before you edit it, for example:

    Terminal window
    cp /etc/httpd/conf.d/ssl.conf /etc/httpd/conf.d/ssl.conf.bak
  • Replace your_name in the commands with a name for your site, such as the domain.

1. Install mod_ssl and OpenSSL

Terminal window
yum install mod_ssl openssl

(The original had Yum with a capital Y; Linux commands are case-sensitive, so it must be yum.) Installing mod_ssl also adds the file /etc/httpd/conf.d/ssl.conf, which sets Apache up to listen on port 443.

2. Create the key and certificate

The original commands used two different sets of file names (ca.key/ca.crt in some lines, your_name.key/your_name.crt in others), so they would not work as written. Here they are first as I wrote them, then corrected to use one set of names.

As originally written:

Terminal window
# Generate private key
openssl genrsa -out ca.key 1024
# Generate CSR
openssl req -new -key ca.key -out your_name.csr
# Generate Self Signed Key
openssl x509 -req -days 365 -in your_name.csr -signkey your_name.key -out your_name.crt

Corrected:

Terminal window
# Generate private key (2048 bits)
openssl genrsa -out your_name.key 2048
# Generate CSR (certificate signing request)
openssl req -new -key your_name.key -out your_name.csr
# Generate the self-signed certificate, valid for 365 days
openssl x509 -req -days 365 -in your_name.csr -signkey your_name.key -out your_name.crt

What changed and why:

  • One set of names. The certificate must be signed with the same key the CSR was made from, so -signkey must point to the key created in the first command.
  • 2048 bits instead of 1024. 1024-bit RSA keys are considered too weak: certificate authorities no longer issue certificates for them, and many current systems refuse them. 2048 bits is the usual minimum.

What each file is:

  • your_name.key: the private key. Keep it secret.
  • your_name.csr: the certificate signing request. You send this to a certificate authority if you buy a certificate. openssl req asks for details such as country and organisation; the Common Name must be the site’s host name, for example mysite.example.com.
  • your_name.crt: the certificate Apache presents to visitors.

3. Copy the files to the correct locations

As originally written:

Terminal window
cp ca.crt /etc/pki/tls/certs/your_name.crt
cp ca.key /etc/pki/tls/private/your_name.key
cp ca.csr /etc/pki/tls/private/your_name.csr

Corrected to match the file names above:

Terminal window
cp your_name.crt /etc/pki/tls/certs/your_name.crt
cp your_name.key /etc/pki/tls/private/your_name.key
cp your_name.csr /etc/pki/tls/private/your_name.csr

Make the private key readable by root only:

Terminal window
chmod 600 /etc/pki/tls/private/your_name.key

4. Point Apache at the certificate

Terminal window
vi /etc/httpd/conf.d/ssl.conf

Change the paths for SSLCertificateFile and SSLCertificateKeyFile:

SSLCertificateFile /etc/pki/tls/certs/your_name.crt
SSLCertificateKeyFile /etc/pki/tls/private/your_name.key

Restart Apache:

Terminal window
service httpd restart

5. Set up virtual host files

Edit the main Apache config:

Terminal window
vi /etc/httpd/conf/httpd.conf

Add this line at the end:

Include conf/vhosts/*.conf

The path is relative to Apache’s ServerRoot, which is /etc/httpd on CentOS, so this loads every .conf file in /etc/httpd/conf/vhosts/.

Create the folders:

Terminal window
mkdir /etc/httpd/conf/ssl-vhosts
mkdir /etc/httpd/conf/vhosts

Create the virtual host files:

Terminal window
vi /etc/httpd/conf/ssl-vhosts/vhosts-ssl.conf
vi /etc/httpd/conf/vhosts/vhosts.conf

My original note said only “add this line in this page” here, without saying which line. Two points to be aware of:

  • Only the vhosts folder is included by the line above. A file in ssl-vhosts is not loaded unless you also add Include conf/ssl-vhosts/*.conf to httpd.conf.
  • The virtual host blocks in the next step are what go in these files: the port 80 block in vhosts.conf and the port 443 block in vhosts-ssl.conf.

6. Redirect HTTP to HTTPS

To redirect, do as follows. This port 80 virtual host sends every visitor to the HTTPS address:

<VirtualHost *:80>
ServerName mysite.example.com
DocumentRoot /usr/local/apache2/htdocs
Redirect permanent / https://mysite.example.com
</VirtualHost>

Correction (added later): give the target a trailing slash, Redirect permanent / https://mysite.example.com/. Redirect adds the rest of the requested path to the target, so without the slash a request for /page is sent to https://mysite.example.compage.

/usr/local/apache2/htdocs is the document root of an Apache built from source. On a CentOS package install the usual folder is /var/www/html. Because this block only redirects, the DocumentRoot here is not used for serving pages. Redirect permanent sends a 301 response, so browsers and search engines remember the new address.

The HTTPS virtual host:

<VirtualHost _default_:443>
ServerName mysite.example.com
DocumentRoot /var/www/your_dir
SSLEngine On
</VirtualHost>

SSLEngine On turns on SSL but does not say which certificate to use, so add the certificate lines inside the block. Also note that the stock ssl.conf already contains a <VirtualHost _default_:443> block with the certificate paths from step 4. If you only have one HTTPS site, editing that existing block (its ServerName and DocumentRoot) is the simplest option; if you add your own block as well, check the Apache documentation on name-based virtual hosts for your version.

<VirtualHost _default_:443>
ServerName mysite.example.com
DocumentRoot /var/www/your_dir
SSLEngine On
SSLCertificateFile /etc/pki/tls/certs/your_name.crt
SSLCertificateKeyFile /etc/pki/tls/private/your_name.key
</VirtualHost>

Check the configuration, then restart Apache:

Terminal window
apachectl configtest
service httpd restart

apachectl configtest should print Syntax OK. If not, it shows the file and line with the problem.

How to check it worked

  • Visit http://mysite.example.com; it should redirect to https://mysite.example.com.

  • With a self-signed certificate the browser shows a warning; this is expected.

  • From the server, check the certificate Apache is presenting:

    Terminal window
    openssl s_client -connect localhost:443 -servername mysite.example.com

Notes for today

  • Use a free trusted certificate for real sites. Self-signed certificates make browsers show a security warning, so they are only suitable for testing or internal use. For a public website, free certificates from Let’s Encrypt are the common choice today. They are issued with the certbot tool, which can also set up Apache and renew the certificates automatically. Let’s Encrypt certificates are short-lived, so automatic renewal matters. Installation instructions for your system are at https://certbot.eff.org/.

  • Turn off old protocols. SSLv2, SSLv3, TLS 1.0 and TLS 1.1 are insecure and should not be enabled. In ssl.conf you can allow only TLS 1.2 and 1.3:

    SSLProtocol -all +TLSv1.2 +TLSv1.3

    +TLSv1.3 needs a recent Apache 2.4 built with OpenSSL 1.1.1 or later. If apachectl configtest rejects it on an older system, use SSLProtocol -all +TLSv1.2.

  • CentOS end of life: CentOS 7 reached end of life on 30 June 2024 (CentOS 6 on 30 November 2020). Rocky Linux and AlmaLinux are the common free replacements; the /etc/pki/tls/ and /etc/httpd/ paths are the same there.

  • Services and packages: service httpd restart became systemctl restart httpd, and yum became dnf on newer Red Hat-family systems.

  • Firewall: open HTTPS on Rocky Linux and AlmaLinux with sudo firewall-cmd --permanent --add-service=https then sudo firewall-cmd --reload.

  • Apache’s official documentation, including mod_ssl, is at https://httpd.apache.org/docs/.