---
description: Setting up the secure "https" on web servers
---

# HTTPS Setup

## Overview for Beginners

Many online articles discuss setting up HTTPS for Apache HTTPD on cloud virtual machines like AWS EC2 or GCP Compute Engine. However, beginners often find gaps in the explanation, particularly regarding acquiring a free SSL certificate from Let's Encrypt, the "Certificate Authority CA", and configuring it on Apache HTTPD. The following step-by-step instructions aim to bridge this knowledge gap.

## Setup for Apache "httpd" web server

**NOTE**: the following should work for both AWS EC2 or GCP Compute Engine; (tested Jun, 2024)

### Install Apache httpd - AWS EC2 - Amazon Linux 2023 AMI

By default, the **Apache "httpd" web server** enable only the unencrypted "http" after installation. Additional steps are needed to enable the "https". These steps include installing the Apache "mod\_ssl" extension module and possibly additional steps.

The **Apache "mod\_ssl"** extension module provides strong cryptography using the Secure Sockets Layer (SSL) and Transport Layer Security (TLS) protocols, ensuring secure connections between the server and clients, safeguarding sensitive data transmitted over the network.

NOTE: _**to be confirmed via testing;**_ the additional steps may not be needed as it is enabled automatically during installation of the "mod\_ssl". For example, on the AWS EC2 with Amazon Linux 2023, the additional steps are not needed if the default SSL certificates are acceptable. (_Tested: Jun 2024_)

* Install Apache "httpd" web server and the `mod_ssl`

```
sudo yum update -y
sudo yum install -y httpd mod_ssl
sudo systemctl start httpd
sudo systemctl enable httpd
```

* Create a very simple web page

```
sudo echo "<h1>Hello from Region us-west-2a</h1>" > /var/www/html/index.html
```

### Create self-signed certificate

On the AWS EC2 with Amazon Linux 2023, the default SSL certificates are generated automatically during installation, and the "https" is also enabled.

* To validate: open the browser and enter the following URL: `https://<public_ip_address_assigned_to_ec2_instace>/index.html`
* The auto-generated SSL certificates can be found at:

```
// SSL private key
ls -al /etc/pki/tls/private
[...]
-rw-------. 1 root root 1704 Jun 14 01:38 localhost.key

// SSL Self-Signed Certificate
ls -al /etc/pki/tls/certs
[...]
-rw-r--r--. 1 root root 4309 Jun 14 01:38 localhost.crt
```

* Configuration of the Apache httpd to enable "https" and to use the auto-generated self-signed certificates can be found in the `/etc/httpd/conf.d/ssl.conf` as follow:

```
// ssl.conf
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
```

* \[Alternative] If the SSL certificates were not generated OR you want to create your own self-signed certificates, then follow the instructions below:
* \[Alternative] Check that `openssl` already installed; it should have been installed with `mod_ssl;` otherwise install it;

```
yum list openssl
Amazon Linux 2023 repository                    48 MB/s |  25 MB     00:00
Amazon Linux 2023 Kernel Livepatch repository   52 kB/s |  10 kB     00:00    
Installed Packages
openssl.x86_64                      1:3.0.8-1.amzn2023.0.12

// Otherwise, install
sudo yum update -y
sudo yum install -y openssl
Last metadata expiration check: 0:27:19 ago on Wed Jun 12 02:47:55 2024.
Package openssl-1:3.0.8-1.amzn2023.0.12.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!
```

* \[Alternative] **Generate Private Key** - this will be used to create the SSL self-signed certificate; the following command generates a 2048-bit RSA private key and saves it to a file named `server.key`. You can change the filename if desired.

```
cd ~
openssl genrsa -out server.key 2048
```

* \[Alternative] Generate Certificate Signing Request (CSR): using the private key generated above; the following command will prompt you to enter information such as: your organization details, common name (domain name), etc. It will then generate a CSR and save it to a file named `server.csr`.

```
openssl req -new -key server.key -out server.csr
```

* \[Alternative] Finally, Generate Self-Signed Certificate: using the private key and CSR files; the command creates a self-signed certificate valid for 365 days and saves it to a file named `server.crt`.

```
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
```

* \[Alternative] Copy the generated self-signed certificates to the commonly used folder for Apache httpd: `/etc/pki/tls/`, as shown below:

```
cd ~
sudo mv server.crt /etc/pki/tls/certs/
sudo mv server.key /etc/pki/tls/private/
```

* \[Alternative] Restart the Apache httpd server

```
sudo systemctl restart httpd
```

{% hint style="warning" %}
Please note that while self-signed certificates provide encryption, they are not inherently trusted by web browsers and may trigger security warnings that need to be manually bypassed. For production environments, it is recommended to use SSL certificates from a trusted Certificate Authority (CA) to avoid these warnings and ensure a seamless user experience.

The certificates (`fullchain.pem`) and the key (`privkey.pem`) from the CA will replace the (`localhost.crt` & `localhost.key`) or the (`server.crt` & `server.key`) discussed above.
{% endhint %}

### Create SSL certificates from FREE trusted Certificate Authority (CA)

"Let's Encrypt" is the trusted Certificate Authority (CA) that issues FREE SSL certificate, see [website](https://letsencrypt.org/getting-started/). The step-by-step instructions using "certbot" shell client can be found [here](https://certbot.eff.org/instructions?ws=apache\&os=pip) that can be customized based on the web server and OS type. The following instructions are for AWS Linux 2023 and Apache httpd web server; and based on python certbot module.

**NOTE**: the following instructions are for AWS EC2 using Amazon Linux 2023 AMI.

* Installing Certbot through pip is only supported on a best effort basis and when using a virtual environment. Instructions for installing Certbot through pip can be found [HERE](https://certbot.eff.org/instructions); and by selecting your server software and then choosing “pip” in the “System” dropdown menu. (Or see custom Instructions: https://certbot.eff.org/instructions?ws=apache\&os=pip). **Source**: https://eff-certbot.readthedocs.io/en/stable/install.html#alternative-2-pip
* Install python3 and other modules

```
sudo dnf install python3 augeas-libs
```

<details>

<summary>OUTPUT:</summary>

```
Last metadata expiration check: 2:43:43 ago on Fri Jun 14 21:01:56 2024.
Package python3-3.9.16-1.amzn2023.0.8.x86_64 is already installed.
Dependencies resolved.
========================================================================================================================================= Package                        Architecture              Version                                   Repository                      Size
=========================================================================================================================================Installing:
 augeas-libs                    x86_64                    1.13.0-1.amzn2023.0.2                     amazonlinux                    408 k

Transaction Summary
=========================================================================================================================================Install  1 Package

Total download size: 408 k
Installed size: 1.2 M
Is this ok [y/N]: y
Downloading Packages:
augeas-libs-1.13.0-1.amzn2023.0.2.x86_64.rpm                                                             3.0 MB/s | 408 kB     00:00    
-----------------------------------------------------------------------------------------------------------------------------------------Total                                                                                                    2.1 MB/s | 408 kB     00:00     
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                                 1/1 
  Installing       : augeas-libs-1.13.0-1.amzn2023.0.2.x86_64                                                                        1/1 
  Running scriptlet: augeas-libs-1.13.0-1.amzn2023.0.2.x86_64                                                                        1/1 
  Verifying        : augeas-libs-1.13.0-1.amzn2023.0.2.x86_64                                                                        1/1 

Installed:
  augeas-libs-1.13.0-1.amzn2023.0.2.x86_64                                                                                               

Complete!
```

</details>

* Setup a python virtual environment

```
sudo python3 -m venv /opt/certbot/
sudo /opt/certbot/bin/pip install --upgrade pip
```

<details>

<summary>OUTPUT:</summary>

```
Requirement already satisfied: pip in /opt/certbot/lib/python3.9/site-packages (21.3.1)
Collecting pip
  Downloading pip-24.0-py3-none-any.whl (2.1 MB)
     |████████████████████████████████| 2.1 MB 4.0 MB/s            
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 21.3.1
    Uninstalling pip-21.3.1:
      Successfully uninstalled pip-21.3.1
Successfully installed pip-24.0
```

</details>

* Install certbot & Prepare the Certbot command

```
sudo /opt/certbot/bin/pip install certbot certbot-apache
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
```

<details>

<summary>OUTPUT</summary>

```
Collecting certbot
  Downloading certbot-2.11.0-py3-none-any.whl.metadata (8.2 kB)
Collecting certbot-apache
  Downloading certbot_apache-2.11.0-py3-none-any.whl.metadata (1.5 kB)
Collecting acme>=2.11.0 (from certbot)
  Downloading acme-2.11.0-py3-none-any.whl.metadata (1.4 kB)
Collecting ConfigArgParse>=1.5.3 (from certbot)
  Downloading ConfigArgParse-1.7-py3-none-any.whl.metadata (23 kB)
Collecting configobj>=5.0.6 (from certbot)
  Downloading configobj-5.0.8-py2.py3-none-any.whl.metadata (3.4 kB)
Collecting cryptography>=3.2.1 (from certbot)
  Downloading cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl.metadata (5.3 kB)
Collecting distro>=1.0.1 (from certbot)
  Downloading distro-1.9.0-py3-none-any.whl.metadata (6.8 kB)
Collecting josepy>=1.13.0 (from certbot)
  Downloading josepy-1.14.0-py3-none-any.whl.metadata (1.8 kB)
Collecting parsedatetime>=2.4 (from certbot)
  Downloading parsedatetime-2.6-py3-none-any.whl.metadata (4.7 kB)
Collecting pyrfc3339 (from certbot)
  Downloading pyRFC3339-1.1-py2.py3-none-any.whl.metadata (2.0 kB)
Collecting pytz>=2019.3 (from certbot)
  Downloading pytz-2024.1-py2.py3-none-any.whl.metadata (22 kB)
Requirement already satisfied: setuptools>=41.6.0 in /opt/certbot/lib/python3.9/site-packages (from certbot) (59.6.0)
Collecting importlib-metadata>=4.6 (from certbot)
  Downloading importlib_metadata-7.1.0-py3-none-any.whl.metadata (4.7 kB)
Collecting python-augeas (from certbot-apache)
  Downloading python-augeas-1.1.0.tar.gz (93 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 93.7/93.7 kB 4.9 MB/s eta 0:00:00
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Installing backend dependencies ... done
  Preparing metadata (pyproject.toml) ... done
Collecting PyOpenSSL!=23.1.0,>=17.5.0 (from acme>=2.11.0->certbot)
  Downloading pyOpenSSL-24.1.0-py3-none-any.whl.metadata (12 kB)
Collecting requests>=2.20.0 (from acme>=2.11.0->certbot)
  Downloading requests-2.32.3-py3-none-any.whl.metadata (4.6 kB)
Collecting six (from configobj>=5.0.6->certbot)
  Downloading six-1.16.0-py2.py3-none-any.whl.metadata (1.8 kB)
Collecting cffi>=1.12 (from cryptography>=3.2.1->certbot)
  Using cached cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (1.5 kB)
Collecting zipp>=0.5 (from importlib-metadata>=4.6->certbot)
  Downloading zipp-3.19.2-py3-none-any.whl.metadata (3.6 kB)
Collecting pycparser (from cffi>=1.12->cryptography>=3.2.1->certbot)
  Using cached pycparser-2.22-py3-none-any.whl.metadata (943 bytes)
Collecting charset-normalizer<4,>=2 (from requests>=2.20.0->acme>=2.11.0->certbot)
  Downloading charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (33 kB)
Collecting idna<4,>=2.5 (from requests>=2.20.0->acme>=2.11.0->certbot)
  Downloading idna-3.7-py3-none-any.whl.metadata (9.9 kB)
Collecting urllib3<3,>=1.21.1 (from requests>=2.20.0->acme>=2.11.0->certbot)
  Downloading urllib3-2.2.1-py3-none-any.whl.metadata (6.4 kB)
Collecting certifi>=2017.4.17 (from requests>=2.20.0->acme>=2.11.0->certbot)
  Downloading certifi-2024.6.2-py3-none-any.whl.metadata (2.2 kB)
Downloading certbot-2.11.0-py3-none-any.whl (407 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 407.3/407.3 kB 18.0 MB/s eta 0:00:00
Downloading certbot_apache-2.11.0-py3-none-any.whl (269 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 269.8/269.8 kB 34.2 MB/s eta 0:00:00
Downloading acme-2.11.0-py3-none-any.whl (95 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 95.8/95.8 kB 14.8 MB/s eta 0:00:00
Downloading ConfigArgParse-1.7-py3-none-any.whl (25 kB)
Downloading configobj-5.0.8-py2.py3-none-any.whl (36 kB)
Downloading cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl (3.9 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.9/3.9 MB 77.2 MB/s eta 0:00:00
Downloading distro-1.9.0-py3-none-any.whl (20 kB)
Downloading importlib_metadata-7.1.0-py3-none-any.whl (24 kB)
Downloading josepy-1.14.0-py3-none-any.whl (32 kB)
Downloading parsedatetime-2.6-py3-none-any.whl (42 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 42.5/42.5 kB 6.4 MB/s eta 0:00:00
Downloading pytz-2024.1-py2.py3-none-any.whl (505 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 505.5/505.5 kB 49.4 MB/s eta 0:00:00
Downloading pyRFC3339-1.1-py2.py3-none-any.whl (5.7 kB)
Using cached cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (443 kB)
Downloading pyOpenSSL-24.1.0-py3-none-any.whl (56 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 56.9/56.9 kB 8.5 MB/s eta 0:00:00
Downloading requests-2.32.3-py3-none-any.whl (64 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 64.9/64.9 kB 10.7 MB/s eta 0:00:00
Downloading zipp-3.19.2-py3-none-any.whl (9.0 kB)
Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Downloading certifi-2024.6.2-py3-none-any.whl (164 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 164.4/164.4 kB 24.2 MB/s eta 0:00:00
Downloading charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (142 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 142.3/142.3 kB 20.7 MB/s eta 0:00:00
Downloading idna-3.7-py3-none-any.whl (66 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 66.8/66.8 kB 9.6 MB/s eta 0:00:00
Downloading urllib3-2.2.1-py3-none-any.whl (121 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 121.1/121.1 kB 19.2 MB/s eta 0:00:00
Using cached pycparser-2.22-py3-none-any.whl (117 kB)
Building wheels for collected packages: python-augeas
  Building wheel for python-augeas (pyproject.toml) ... done
  Created wheel for python-augeas: filename=python_augeas-1.1.0-py3-none-any.whl size=21224 sha256=a958c25c67369c58a4d07fccac58ccaf4cce0b7f017201d7744a997bc3a099fb
  Stored in directory: /root/.cache/pip/wheels/6e/68/47/25baeabcc9e90f81938e12ace4cb58eeba9deaeaae8bc3d577
Successfully built python-augeas
Installing collected packages: pytz, parsedatetime, zipp, urllib3, six, pyrfc3339, pycparser, idna, distro, ConfigArgParse, charset-normalizer, certifi, requests, importlib-metadata, configobj, cffi, python-augeas, cryptography, PyOpenSSL, josepy, acme, certbot, certbot-apache
Successfully installed ConfigArgParse-1.7 PyOpenSSL-24.1.0 acme-2.11.0 certbot-2.11.0 certbot-apache-2.11.0 certifi-2024.6.2 cffi-1.16.0 charset-normalizer-3.3.2 configobj-5.0.8 cryptography-42.0.8 distro-1.9.0 idna-3.7 importlib-metadata-7.1.0 josepy-1.14.0 parsedatetime-2.6 pycparser-2.22 pyrfc3339-1.1 python-augeas-1.1.0 pytz-2024.1 requests-2.32.3 six-1.16.0 urllib3-2.2.1 zipp-3.19.2

```

</details>

* Get certificate only but don't install.

```
sudo certbot certonly --webroot -w /var/www/html
```

<details>

<summary>OUTPUT</summary>

```
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): thendean@gmail.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf. You must agree in
order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N
Account registered.
Please enter the domain name(s) you would like on your certificate (comma and/or
space separated) (Enter 'c' to cancel): aiworking.online
Requesting a certificate for aiworking.online

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/aiworking.online/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/aiworking.online/privkey.pem
This certificate expires on 2024-09-12.
These files will be updated when the certificate renews.

NEXT STEPS:
- The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

```

</details>

* To find the generated certificates, see the following locations. Source: [https://eff-certbot.readthedocs.io/en/stable/using.html#where-are-my-certificates](https://eff-certbot.readthedocs.io/en/stable/using.html#where-are-my-certificates)

```
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/aiworking.online/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/aiworking.online/privkey.pem
```

* Config Apache httpd; update `/etc/httpd/conf.d/ssl.conf` with the following:

```
SSLCertificateFile /etc/letsencrypt/live/aiworking.online/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/aiworking.online/privkey.pem
```

* Restart Apache: after making changes to the Apache configuration, restart the Apache HTTP Server to activate the changes:

```
sudo systemctl restart httpd
```

* Finally, Set up automatic renewal using cron job:

```
echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; \
import time; time.sleep(random.random() * 3600)' && sudo certbot renew -q" | \
sudo tee -a /etc/crontab > /dev/null
```

* Monthly Upgrade certbot:

```
sudo /opt/certbot/bin/pip install --upgrade certbot certbot-apache
```

## References

* Let's Encrypt - [https://letsencrypt.org/getting-started/](https://letsencrypt.org/getting-started/)
* Certbot custom instructions - [https://certbot.eff.org/](https://certbot.eff.org/)
* Certbot User Manual - [https://eff-certbot.readthedocs.io/en/stable/intro.html](https://eff-certbot.readthedocs.io/en/stable/intro.html)&#x20;
* How to install certbot via snap on Amazon Linux 2023 - [https://unix.stackexchange.com/questions/744633/how-to-install-certbot-via-snap-on-amazon-linux-2023](https://unix.stackexchange.com/questions/744633/how-to-install-certbot-via-snap-on-amazon-linux-2023)
*
