Reasons to add HTTPS encryption to a website:
- Protect private user data entered into forms, as it travels from browser to server
- Keep user navigation and content subject matter private
- Improve user perception that the website is safe. Most users haven't a clue but rather than have them be alarmed by an icon labeling a website as unencrypted, it is easier to add HTTPS
- Perceived SEO benefits (search rank)
Prerequisites:
This tutorial assumes that one has a Bind based DNS configured for the domain as well as the Apache web server configured for virtual hosting of web content. See the following tutorial on Bind DNS and Apache Web Site Configuration on Linux.
Certificates:
This tutorial will cover the installation and use of encryption keys and certificates from LetsEncrypt.org which are available for free for a duration of 90 days after which they must be renewed. The TLS or SSL (TLS is a newer and improved version of encryption than SSL) keys, certificates and CA chain files are obtained from the LetsEncrypt.org server using a client script which employs the Automatic Certificate Management Environment (ACME) protocol. The ACME protocol supports deployment between the Certificate authority (CA), the entity that stores, signs and issues digital certificates to certify the ownership of a public key, and a user's web server. ACME version 2 supports wildcards: *.megacorp.com. This allows the domain certificates obtained to support megacorp.com, www.megacorp.com, mail.megacorp.com and all nodes supporting the domain.
ACME Client:
An ACME client is run to obtain browser trusted certificates from Let's Encrypt. The issued certificate can be used for SSL/TLS for use by web servers, mail servers (but not for email encryption), ftp servers, etc.
When verifying domain ownership, the user must show a working DNS or web server configuration to show that they control the domain. This tutorial assumes the use of Bind as a DNS name server if using DNS for domain verification or use of the Apache web server for HTTP domain verification.
Apache Configuration:
This tutorial will show the additional required configuration settings to an existing "Virtual Hosts" HTTP web server. See the YoLinux Linux Internet Web Server and Domain Configuration Tutorial for instructions on configuring bind DNS and Apache.
Three files are referenced by the Apache server for an HTTPS website:
- SSLCertificateFile: crt fle
- SSLCertificateKeyFile: key file
- SSLCertificateChainFile: crt file. This file defines the certificate authorities (CAs) hierarchy chain of trust from the root CA through the intermediate CAs to the end user certificate. The browser will travers this chain until a trusted CA is found after which a secure connection will be established. The browser installation includes the root certificates. The SSLCertificateChainFile defines the intermediate certificates.
ACME Client:
The Let's Encrypt website lists a lot of eligible ACME clients
Using the bash script getssl:
- Install getssl
- Generate getssl configuration files and edit
- Request certificate generation
- Create DNS record for domain ownership verification
- Configure Apache web server for HTTPS using the certificates generated
Install getssl from github: https://github.com/srvrco/getssl
curl --silent https://raw.githubusercontent.com/srvrco/getssl/latest/getssl > getssl ; chmod 700 getssl
Also download from github:
File: /opt/bin/dns_add_manual#!/usr/bin/env bash echo "In the DNS, a new TXT record needs to be created for;" echo "_acme-challenge.${1}" echo "containing the following value" echo "$2" read -r -p "Press any key to obtain the certificate once the records have been updated..."File: /opt/bin/dns_del_manual
#!/usr/bin/env bash echo "In the DNS, the following DNS record should be deleted ;" echo "_acme-challenge.${1}" read -r -p "Press any key to obtain the certificate once the records have been updated..."usage:
- -c: create default config files to edit
- -q: Quiet mode
- -h: Help
Certificate Generation and Deployment Options:
There are two primary options:
- Generate certificates for base and www domains:
- megacorp.com
- www.megacorp.com
- Generate certificates for base and all wildcard "*" domains:
- megacorp.com
- *.megacorp.com
This approach supports website access using the base domain (eg. https://megacorp.com) or www subdomain (eg. https://www.megacorp.com) as the URL to access a website.
Create initial configuration files for the domain: getssl -c megacorp.comMaking domain directory - /home/user1/.getssl/megacorp.com creating domain config file in /home/user1/.getssl/megacorp.com/getssl.cfg created domain config file in /home/user1/.getssl/megacorp.com/getssl.cfg
Will generate the following configuration files:
- ~/.getssl/getssl.cfg - global server config file
- ~/.getssl/megacorp.com/getssl.cfg - edit this domain specific file
CA="https://acme-v02.api.letsencrypt.org" ACCOUNT_EMAIL="user1@megacorp.com" ACCOUNT_KEY_LENGTH=4096 ACCOUNT_KEY="/home/user1/.getssl/account.key" ACCOUNT_KEY_TYPE="rsa" PRIVATE_KEY_ALG="rsa" FULL_CHAIN_INCLUDE_ROOT="true" RELOAD_CMD="sudo apachectl restart" RENEW_ALLOW="90" SERVER_TYPE="https" CHECK_REMOTE="true" VALIDATE_VIA_DNS="false" DNS_ADD_COMMAND="/opt/bin/dns_add_manual" DNS_DEL_COMMAND="/opt/bin/dns_del_manual" PUBLIC_DNS_SERVER="XXX.XXX.XXX.XXX" AUTH_DNS_SERVER="XXX.XXX.XXX.XXX"
Note that the renew period was increased to the maximum of 90 days (max for letsencrypt.org).
Must set VALIDATE_VIA_DNS to false in order to validate via http your authority by installing the verification files (files with encrypted hash as a file name) in the directory /.well-known/acme-challenge/ in your web content root directory. The presence of the files are what is being validated by the certificate authority.
Edit (or use default) this domain specific file: ~/.getssl/megacorp.com/getssl.cfg
CA="https://acme-v02.api.letsencrypt.org" PRIVATE_KEY_ALG="rsa" SANS="www.megacorp.com" ACL=('/home/user1/www/megacorp.com/html/.well-known/acme-challenge') USE_SINGLE_ACL="true" DOMAIN_CERT_LOCATION="/etc/ssl/websites/megacorp.com/megacorp.com.crt" DOMAIN_KEY_LOCATION="/etc/ssl/websites/megacorp.com/megacorp.com.key" DOMAIN_CHAIN_LOCATION="/etc/ssl/websites/megacorp.com/fullchain.crt" RELOAD_CMD="sudo apachectl restart" SERVER_TYPE="https"
The SANS is set to support a single subdomain (www). This can be a comma separated list of additional domains / subdomains. This should not include the primary domain (eg. megacorp.com).
Now is a good time to edit the Apache website conf file (see below).
Run the script; ./getssl megacorp.commegacorp.com: Certificate on remote domain does not match, ignoring remote certificate (host.name-of-computer.com != megacorp.com) creating key - /home/user1/.getssl/megacorp.com/megacorp.com.key Generating RSA private key, 4096 bit long modulus ..............................................................................................................................++ ............................................................................................................................++ e is 65537 (0x10001) creating domain csr - /home/user1/.getssl/megacorp.com/megacorp.com.csr Registering account Verify each domain Verifying megacorp.com copying challenge token to /home/user1/www/megacorp.com/html/.well-known/acme-challenge/asdfJNzw934567rKbeJqVVa2Wepl_z4fUohjkljjzD0 sending request to ACME server saying we're ready for challenge checking if challenge is complete Pending checking if challenge is complete Verified megacorp.com Verifying www.megacorp.com copying challenge token to /home/user1/www/megacorp.com/html/.well-known/acme-challenge/eP40xphT2134rkCwPjp7fghjk4SbmuzMUZasdfV5JAc sending request to ACME server saying we're ready for challenge checking if challenge is complete Pending checking if challenge is complete Verified www.megacorp.com Verification completed, obtaining certificate. Requesting Finalize Link Requesting Order Link Requesting certificate Certificate saved in /home/user1/.getssl/megacorp.com/megacorp.com.crt copying domain certificate to /etc/ssl/websites/megacorp.com/megacorp.com.crt copying private key to /etc/ssl/websites/megacorp.com/megacorp.com.key copying full chain to /etc/ssl/websites/megacorp.com/fullchain.crt reloading SSL services megacorp.com - rsa certificate installed OK on server certificate obtained for megacorp.com
Automating Certificate Renewal:
File: /etc/crontabAdd the following line.
0 18 1 */2 * root /opt/bin/getssl -u -a -q &>> /var/log/getssl.logwhere:
- crontab:
- 0 : zero minutes (0 - 59)
- 18 : hour of the day is 6pm during the day (0 - 24)
- 1 : day of month (1 - 31)
- */2 : every two months. Execute in a specific month (1 -12)
- * : wildcard "*" refers to any day of the week (0 - 6)
- run as user specified
- getssl arguments:
- -a, --all : Renew all certificates
- -u, --upgrade : Upgrade getssl if a more recent version is available - can be used with or without domain(s)
- -q, --quiet : Quiet mode (only outputs on error, success of new cert, or getssl was upgraded)
/var/log/getssl.log { yearly rotate 10 copytruncate delaycompress compress notifempty missingok }
This approach supports wildcards and thus requires adding a DNS record to verify domain ownership.
Create initial configuration files for the domain: getssl -c megacorp.comcreating main config file /home/user1/.getssl/getssl.cfg Making domain directory - /home/user1/.getssl/megacorp.com creating domain config file in /home/user1/.getssl/megacorp.com/getssl.cfg Adding SANS=*.megacorp.com from certificate installed on megacorp.com to new configuration file created domain config file in /home/user1/.getssl/megacorp.com/getssl.cfg
May take a few seconds to run.
Will generate the following configuration files:- ~/.getssl/getssl.cfg - global server config file
- ~/.getssl/megacorp.com/getssl.cfg - edit this domain specific file
CA="https://acme-v02.api.letsencrypt.org" ACCOUNT_EMAIL="user1@megacorp.com" ACCOUNT_KEY_LENGTH=4096 ACCOUNT_KEY="/home/user1/.getssl/account.key" ACCOUNT_KEY_TYPE="rsa" PRIVATE_KEY_ALG="rsa" FULL_CHAIN_INCLUDE_ROOT="true" RELOAD_CMD="apachectl restart" RENEW_ALLOW="90" SERVER_TYPE="https" CHECK_REMOTE="true" VALIDATE_VIA_DNS="true" DNS_ADD_COMMAND="/opt/bin/dns_add_manual" DNS_DEL_COMMAND="/opt/bin/dns_del_manual" PUBLIC_DNS_SERVER="XXX.XXX.XXX.XXX" AUTH_DNS_SERVER="XXX.XXX.XXX.XXX"
Tip for AWS EC2 users. Use public "elastic" IP addresses rather than private VPC (Virtual Private Cloud) IP addresses.
Note that the renew period was increased to the maximum of 90 days.
Must set VALIDATE_VIA_DNS to true or you will get the following error:megacorp.com: cannot use http-01 validation for wildcard domains
Edit (or use default) this domain specific file: ~/.getssl/megacorp.com/getssl.cfg
CA="https://acme-v02.api.letsencrypt.org" PRIVATE_KEY_ALG="rsa" SANS="*.megacorp.com" RELOAD_CMD="apachectl restart" SERVER_TYPE="https"
The SANS is set to support wildcards so that all network nodes for the domain are included.
Run the script; ./getssl megacorp.commegacorp.com: Certificate on remote domain does not match, ignoring remote certificate ( != megacorp.com) creating account key /home/user1/.getssl/account.key creating key - /home/user1/.getssl/account.key Generating RSA private key, 4096 bit long modulus .....................++ ........................................................++ e is 65537 (0x10001) creating key - /home/user1/.getssl/megacorp.com/megacorp.com.key Generating RSA private key, 4096 bit long modulus ...................................................................................................................................................................++ .............++ e is 65537 (0x10001) creating domain csr - /home/user1/.getssl/megacorp.com/megacorp.com.csr Registering account Registered Verify each domain Verifying megacorp.com In the DNS, a new TXT record needs to be created for; _acme-challenge.megacorp.com containing the following value X93NZI6785A63HB4wazUFdZhj6qtyopwERpp6QLTCRk Press any key to obtain the certificate once the records have been updated...
It is at this point in running the getssl script that one will have to make an entry in the DNS configuration. The purpose is to show and verify to the certificate authority (CA) that you legitimately own and control the domain. Add a TX entry to the domains DNS record. Here we show a text entry for a bind DNS configuration:
File: /var/named/chroot/var/named/data/named.megacorp.com... .... 2014123113 ; serial ... ... _acme-challenge.megacorp.com. IN TXT "X93NZI6785A63HB4wazUFdZhj6qtyopwERpp6QLTCRk"
Remember to increment the serial value.
Note that there is a "." at the end of the challenge value: _acme-challenge.megacorp.com.
Note that there may be multiple "_acme-challenge" TXT entries.
Restart bind: service named restart
Verify: dig +trace _acme-challenge.megacorp.com
Return to the terminal window running getssl and press enter.
checking DNS at XXX.XXX.XXX.XXX checking DNS at XXX.XXX.XXX.XXX sleeping 60 seconds before asking the ACME server to check the dns sending request to ACME server saying we're ready for challenge checking if challenge is complete Pending checking if challenge is complete Verified megacorp.com In the DNS, the following DNS record should be deleted ; _acme-challenge.megacorp.com Press any key to obtain the certificate once the records have been updated...Press "Enter"
Verifying *.megacorp.com In the DNS, a new TXT record needs to be created for; _acme-challenge.megacorp.com containing the following value GPm2_R6W1bPKh2FQ1234EnJsTdQDtf6Ifk5Uqf85y_s Press any key to obtain the certificate once the records have been updated...
Add another record to your DNS.
Return to the terminal window running getssl and press "Enter".
checking DNS at XXX.XXX.XXX.XXX checking DNS at XXX.XXX.XXX.XXX sleeping 60 seconds before asking the ACME server to check the dns sending request to ACME server saying we're ready for challenge checking if challenge is complete Pending checking if challenge is complete Verified *.megacorp.com In the DNS, the following DNS record should be deleted ; _acme-challenge.megacorp.com Press any key to obtain the certificate once the records have been updated...
Remove previously added DNS records.
Return to the terminal window running getssl and press "Enter".
Verification completed, obtaining certificate. Requesting Finalize Link Requesting Order Link Requesting certificate Certificate saved in /home/user1/.getssl/megacorp.com/megacorp.com.crt reloading SSL services
Delete the bind DNS TXT "_acme-challenge" line, increment the serial value and restart bind (service named restart).
At this point the encryption certificates will be generated and will be ready for use by the Apache web server.
Copy encryption certificates to an Apache accessible directory.
sudo cp '.getssl/megacorp.com/megacorp.com.key' /etc/ssl/websites/megacorp.com/megacorp.com.key sudo cp '.getssl/megacorp.com/megacorp.com.crt' /etc/ssl/websites/megacorp.com/megacorp.com.crt sudo cp '.getssl/megacorp.com/fullchain.crt' /etc/ssl/websites/megacorp.com/fullchain.crt
Configure Apache for multiple HTTPS domains on the same IP, using virtual hosts with Server Name Indication (SNI) to allow the server to determine the correct certificate for each domain.
Edit the configuration for the domain by adding the HTTPS configuration to the HTTP configuration. The working HTTP configuration is not altered. One will add an HTTPS configuration.
File: /etc/httpd/sites.d/megacorp.conf... ... <VirtualHost *:443> ServerName megacorp.com ServerAlias www.megacorp.com DocumentRoot /home/websites/www/megacorp.com/html/ <Directory "/"> Options FollowSymLinks AllowOverride None </Directory> <Directory /home/websites/www/megacorp.com/html> XBitHack Full Options FollowSymLinks MultiViews Includes IndexOptions SuppressLastModified SuppressDescription AllowOverride All Order allow,deny allow from all Require all granted </Directory> SSLEngine on SSLProtocol all -SSLv3 -TLSv1 SSLCertificateFile /etc/ssl/websites/megacorp.com/megacorp.com.crt SSLCertificateKeyFile /etc/ssl/websites/megacorp.com/megacorp.com.key SSLCertificateChainFile /etc/ssl/websites/megacorp.com/fullchain.crt ErrorLog /var/log/httpd/megacorp.com-error.log LogLevel warn CustomLog /var/log/httpd/megacorp.com-access.log combined ServerSignature Off </VirtualHost>
Verify the Apache webserver configuration: apachectl configtest
Look for the response Syntax OK
Restart the Apache webserver: apachectl restart
Firewall Rules:
[Pitfall] The webpage does not load but stalls and reaches timeout. Try flushing the firewall rules on the web server: iptables -F
Apache Restart Fails:
[Pitfall] Restart (apachectl restart) fails and give the following error:
(13)Permission denied: AH00058: Error retrieving pid file /var/run/httpd/httpd.pid AH00059: Remove it before continuing if it is corrupted. getssl: error running: apachectl restartOne must be root user in order to restart the server.
Check Virtual Hosts:
apachectl -t -D DUMP_VHOSTS | grep megacorp
port 443 namevhost megacorp.com (/etc/httpd/sites.d/megacorp.conf:140) alias www.megacorp.com port 80 namevhost megacorp.com (/etc/httpd/sites.d/megacorp.conf:1) alias www.megacorp.com alias aws1.megacorp.com port 80 namevhost megacorp.com (/etc/httpd/sites.d/megacorp.conf:44) alias mail.megacorp.com
Check Error Logs:
File: /var/log/httpd/megacorp.com-error.log
[Mon Mar 31 06:30:08.280026 2025] [ssl:warn] [pid 26852:tid 26852] AH01909: megacorp.com:443:0 server certificate does NOT include an ID which matches the server name
Examine the certificate: openssl x509 -text -in /etc/ssl/websites/megacorp.com/megacorp.com.crt
Look for: "Subject: CN=megacorp.com"
and SAN (can contain multiple lines): "X509v3 Subject Alternative Name:" DNS:megacorp.com
Certificate: Data: Version: 3 (0x2) Serial Number: 05:de:82:...................................:a4:c9:c9 Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, O=Let's Encrypt, CN=R10 Validity Not Before: Mar 31 08:28:08 2025 GMT Not After : Jun 29 08:28:07 2025 GMT Subject: CN=megacorp.com ... ... ... X509v3 Subject Alternative Name: DNS:*.megacorp.com, DNS:megacorp.com ...
Using Curl:
- Fetch page header:
- curl -I https://megacorp.com
- curl -I https://www.megacorp.com
HTTP/1.1 200 OK Date: Sun, 30 Mar 2025 23:06:24 GMT Server: Apache/2.4.61 (Amazon) OpenSSL/1.0.2k-fips PHP/5.6.40 Last-Modified: Tue, 15 Oct 2024 09:52:39 GMT Accept-Ranges: bytes Content-Type: text/html; charset=UTF-8
- Examine certificate:
Extract CA cert from a server
- curl -w %{certs} https://megacorp.com > cacert.pem
- curl -w %{certs} https://www.megacorp.com > cacert.pem
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 9110 0 9110 0 0 23562 0 --:--:-- --:--:-- --:--:-- 23601
- Man page: curl
Check certificate expiration date:
- openssl x509 -text -in chain.crt
- openssl x509 -text -in domain.crt
Certificate: Data: Version: 3 (0x2) Serial Number: 05:de:82:...................................:a4:c9:c9 Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, O=Let's Encrypt, CN=R11 Validity Not Before: Mar 31 08:28:08 2025 GMT Not After : Jun 29 08:28:07 2025 GMT Subject: CN=megacorp.com ... ...
Man page: openssl
Stale Certificate:
Close the browser and then restart the browser application.
Here are some websites which can be used to test and examine your HTTPS installation and give an assessment:
The system default website applies HTTPS to the server "localhost" is defined in /etc/httpd/conf/httpd.conf where DocumentRoot "/var/www/html" with HTTPS certificates and keys set in /etc/httpd/conf.d/ssl.conf where the following is defined:
- SSLCertificateFile /etc/pki/tls/certs/localhost.crt
- SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/pki/tls/private/localhost.key -out /etc/pki/tls/certs/localhost.crtWhere:
- -x509: Indicates that you are creating a self-signed certificate.
- -nodes: Prevents the key from being encrypted with a password.
- -days 365: Sets the certificate's validity period to 365 days.
- -newkey rsa:2048: Generates a new RSA key with a 2048-bit length.
Linux documentation:
Free Certificate Authorities::