Setting up a secure SSL HTTPS website using Apache on CentOS - mhulse/mhulse.github.io GitHub Wiki

For this tutorial, I will be using a fictitious site called “example.com”.

Registrar settings

Navigate to your registrar; for this example, I will be using https://www.godaddy.com/.

  1. Sign in
    • If you are a “delegate” click on Account Settings > Delegate Access (e.g. your user is allowed to access your company’s products)
  2. Visit the products page (this is the default landing page once logged in)
  3. Click Manage All button or the Show More link and find the domain you want to manage
  4. On the domain you want to setup, click the Manage button
  5. If existing record, click the pencil icon to edit, otherwise click ADD
  6. For an “A” record (i.e. no a sub domain), set the “Host” to @ and the “Points to” to the IP of the server your site is hosted on. Leave TTL at default, or set to “Custom” and a value of 600 seconds (10 minutes)
  7. Click Save

HTTP

At this point, if you want to setup your HTTP site (not HTTPS), jump to Apache web server setup below.

Apache SSL setup

Switch to the root user (if not already):

$ sudo su

Navigate to here:

$ cd /var/www

If not already created, make these directories (skip this step if renewing a cert, see below):

# This is where we’ll put all of the SSL-related files:
$ mkdir ssls
$ cd ssls
$ mkdir example.com
$ cd example.com

Note: The location to store the SSL-related files is optional; feel free to do what you want.

Renew

If you are renewing your cert …

Open your site’s .conf file and find these lines:

SSLCertificateKeyFile /var/www/ssls/star.example.com/STAR_example.com.key
SSLCertificateFile /var/www/ssls/star.example.com/STAR_example_com.crt
SSLCertificateChainFile /var/www/ssls/star.example.com/STAR_example.com.ca-bundle

Next, generate a new CSR (if openssl does not work, try using the full path, /usr/bin/openssl):

$ openssl req -new -key /var/www/ssls/star.example.com/STAR_example_com.key -out STAR_example_com.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:US
State or Province Name (full name) []:OREGON
Locality Name (eg, city) [Default City]:SPRINGFIELD
Organization Name (eg, company) [Default Company Ltd]:COMPANY NAME, INC.
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:*.EXAMPLE.COM
Email Address []:[email protected]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Note: For “Common Name”, the *. will work for sub domains; the drawback is, this is more expensive in terms of buying the SSL certificate. In other words, if you don’t need sub domains, then save yourself some money and just use EXAMPLE.COM (no wildcard).

Note: Filling out the above in all-caps is optional.

From scratch

First-time setup …

This is the same as above, but you need to generate the key and the Certificate Signing Request (CSR) at the same time:

$ openssl req -new -newkey rsa:2048 -nodes -keyout example_com.key -out example_com.csr
Generating a 2048 bit RSA private key
......................................................................................................................+++
.................................+++
writing new private key to 'example_com.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:US
State or Province Name (full name) []:OREGON
Locality Name (eg, city) [Default City]:SPRINGFIELD
Organization Name (eg, company) [Default Company Ltd]:COMPANY NAME, INC.
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:EXAMPLE.COM
Email Address []:[email protected]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Note: For example’s sake, the above “Common Name” does not use a wildcard.

Purchase SSL

I recommend ssls.com (no affiliation). They are nice and cheap.

I usually pick the EssenetialsSSL option.

During the checkout process, you will be asked to upload your CSR file.

You will need to verify your identity via your choice of options:

  1. E-mail verification (they will then email you and ask you to verify by clicking on a link)
  2. Verification file (they will send you a txt file that you upload to the public directory of your website)

Once the checkout process is complete, you will receive a verification email.

Verification e-mail

Link

If you chose to verify via e-mail, click the link they send in the verification e-mail.

Text file

If you chose to verify your identity with a verification txt file, navigate to your site’s public root and create a .well-known/pki-validation directory. Move the validation txt file into this directory.

After a while (30 mins or up to 12-24 hours) you will get an email letting you know that your site has been validated and they will provide a zip file containing the needed cert files.

At this point, you can delete the .well-known directory.

Setup certificate files

Once you get the zip file from ssls.com, move them to your web server and put the files in /var/www/example.com/. This directory should now contain these files:

  • example_com.ca-bundle
  • example_com.crt
  • example_com.csr
  • example_com.key

Checking to see if things worked

You can go to your site in your browser of choice, click on the lock icon (Chrome browser) and then click on the certificate. A new window will appear that gives you all the details of your certificate, including dates.

Apache web server setup

First, ssh into your host.

Once logged in, check to see if you Apache httpd/conf file is setup to load additional config files from httpd/conf.d (this should be the default setting):

# CentOS linux flavor:
$ cd /etc/httpd
$ cat conf/httpd.conf
# ...
# Load config files from the config directory "/etc/httpd/conf.d".
#
Include conf.d/*.conf
# ...

If there is a # in front of Include ..., remove it and save and restart Apache sudo systemctl restart httpd

Now you can create a conf file for your site in the /etc/httpd/conf.d directory:

$ cd /etc/httpd/conf.d
# Switch to root user so you don’t have to sudo every command:
$ sudo su
# Create the config file for your domain:
$ touch example.com.conf
# Open the file to edit (`yum install nano` if needed, or use editor of choice):
$ nano example.com.conf

Edit the following to match your needs (for HTTP, comment-in the first block of code and comment-out the second block):

#
# HTTP configuration
# Comment-out when SSL is setup and ready ready.
#

# <VirtualHost *:80>
#   ServerAdmin [email protected]
#   DocumentRoot /var/www/example.com
#   ServerName example.com
#   ServerAlias www.example.com
#   ErrorLog /var/log/httpd/example.com-error.log
#   CustomLog /var/log/httpd/example.com-access.log combined
#   <Directory /var/www/example.com>
#     IndexOptions +FancyIndexing NameWidth=*
#     Options -Indexes +Includes +FollowSymLinks +MultiViews
#     AllowOverride All
#     Order allow,deny
#     Allow from all
#     Require all granted
#   </Directory>
# </VirtualHost>

#
# HTTPS configuration
# Comment-in when SSL is setup and ready.
#

<VirtualHost *:80>
  ServerAdmin [email protected]
  DocumentRoot /var/www/example.com
  ServerName example.com
  ServerAlias www.example.com
  ErrorLog /var/log/httpd/example.com-error.log
  CustomLog /var/log/httpd/example.com-access.log combined
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule ^/?(.*) https://example.com/$1 [R=301,L]
  <Directory /var/www/example.com>
    IndexOptions +FancyIndexing NameWidth=*
    Options -Indexes +Includes +FollowSymLinks +MultiViews
    AllowOverride All
  </Directory>
</VirtualHost>

<VirtualHost *:443>
  ServerAdmin [email protected]
  DocumentRoot /var/www/example.com
  ServerName example.com
  ServerAlias www.example.com
  <Directory /var/www/example.com>
    IndexOptions +FancyIndexing NameWidth=*
    Options -Indexes +Includes +FollowSymLinks +MultiViews
    AllowOverride All
  </Directory>
  RewriteEngine On
  RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
  RewriteRule ^(.*)$ https://%1$1 [R=301,L]
  SSLEngine on
  SSLCertificateKeyFile /var/www/ssls/example.com/example_com.key
  SSLCertificateFile /var/www/ssls/example.com/example_com.crt
  SSLCertificateChainFile /var/www/ssls/example.com/example_com.ca-bundle
  SSLProtocol -ALL +TLSv1.2
  SSLHonorCipherOrder Off
  SSLCipherSuite ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES256:ECDH+AES128:!aNULL:!SHA1
  Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
</VirtualHost>

Save and exit using CTRL + O and CTRL + X.

Check your configuration files to make sure nothing is broken:

$ apachectl configtest

Note: If you have multiple sites on your server, you may need to replace the * value of VirtualHost for an actual IP address.

Restart Apache:

$ apachectl graceful

If that does not work, use:

$ systemctl restart httpd

Navigate to your site; note that it may take up to one day for the DNS change to propagate and resolve to your site.

⚠️ **GitHub.com Fallback** ⚠️