How to Use HTTPS on Arch Linux Webserver

Updated on November 21, 2023
How to Use HTTPS on Arch Linux Webserver header image

Prerequisites

  • A Vultr server running up to date Arch Linux (see this article.)
  • A running webserver, either Apache or Nginx
  • Sudo access
  • Commands required to be ran as root are prefixed by #, and ones that can be ran as a regular user by $. The recommended way to run commands as root is to, as a regular user, prefix each of them with sudo.
  • Have a text editor installed, and be familiar with it, such as vi, vim, nano, emacs or another similar editor.

Secure Serving Via HTTPS

Serving content via HTTPS can use extremely strong encryption, so no one intercepting traffic between the user and web server can read it. It not only encrypts the traffic itself, but also the URL being accessed, which can otherwise expose information. For some time, Google has been partially determining search rankings based on whether a page uses HTTPS, as part of the HTTPS Everywhere initiative.

Note: a DNS lookup does expose the domain name being connected to, but the entire URL is not exposed during that process.

Obtain SSL/TLS Certificate

Technically, TLS replaced SSL for HTTPS Certificates, but, most places simply continued calling TLS Certificates by the more popular term SSL Certificates. Following common usage, this guide will do the same.

To use HTTPS, your web server needs a private key (.key) for it to privately use, and a certificate (.crt) to publicly share which includes a public key. A certificate must be signed. You can sign it yourself, but modern browsers will complain that they do not recognize the signer. For example, Chrome will show: Your connection is not private. Attackers might be trying to steal your information... NET::ERR_CERT_AUTHORITY_INVALID. If only a private group of people will be using the website, this can be acceptable, because browsers will allow a way to proceed. For example, on Chrome, click "Advanced", then "Proceed to... (unsafe)"; it will still show "Not secure" and cross out the "https".

Note that this process will ask you for your country, state/providence, locality, organization, organizational unit, and common names, and your email address; all of which is accessible in anyone's browser connecting to your site via HTTPS.

Also note that if you are giving virtual hosts certificates, you will need to give distinct filenames below, and point to them in your virtual host configurations.

Change into the proper directory for your web server.

If you installed Apache:

$ cd /etc/httpd/conf

If you installed Nginx:

$ cd /etc/nginx

Once in the proper directory, generate a private key (server.key) and self-signed certificate (server.crt):

# openssl req -new -x509 -nodes -newkey rsa:4096 -keyout server.key -out server.crt -days 825

Set read-only permissions, and only allow the private key to be read by root:

# chmod 400 server.key
# chmod 444 server.crt

Alternatively, you can obtain a certificate signed by a trusted certificate authority. You can pay various companies (certificate authorities) to sign your certificate for you. When considering certificate authorities, it can be important to look into which browsers and which versions will recognize them. Some newer certificate authorities may not be recognized as any more official than a self-signed certificate on old browser versions.

You typically not only need a public IP address, but also a domain name. Some certificate authorities can issue a certificate to a public IP address, but it's rarely done.

Many providers offer a free 30 day trial, which is recommended to start with so you can make sure the process works for you before you pay for it. Prices can vary from a few dollars per year to hundreds, depending on what type it is and options such as multiple domains or sub-domains. A standard certificate will only indicate that the signing authority has verified the person obtaining the certificate could make changes on the domain. An Extended Validation certificate will also indicate the signing authority performed some due diligence vetting the requester and will, in modern browsers, show a green bar in or near the URL. When verifying that you can make changes on the domain, some signing authorities will require you to receive email at an important sounding address at the domain name, such as admin@your-domain.com. Many offer alternative verification, such as giving you a file to place on your server, such as placing their file in /srv/http/.well-known/pki-validation/ for Apache or /usr/share/nginx/html/.well-known/pki-validation/ for Nginx, for single hosting directory configurations; or temporarily creating a CNAME entry they provide you in your domain's DNS records.

The signing authority you choose may have slightly different steps, but most will accept the following procedure:

In the proper directory, generate a private key (server.key):

# openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out server.key

Set the private key to read-only, only by root:

# chmod 400 server.key

Generate a certificate signing request (server.csr). You must put your domain name in when it asks you for the Common Name, and you can leave the challenge password blank:

# openssl req -new -sha256 -key server.key -out server.csr

Set the certificate signing request to read-only, only by root:

# chmod 400 server.csr

View the contents of the certificate signing request. This information is base64 encoded, so will look like random characters:

# cat server.csr
-----BEGIN CERTIFICATE REQUEST-----
.....
-----END CERTIFICATE REQUEST-----

Go through your signing authority's process, and when requested to paste in your CSR, copy and paste this entire file including the ----- lines. Depending on the signing authority you chose and the type of certificate, they might immediately give you the signed certificate, or it could be a number of days. Once they give you the signed certificate, copy it (including the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines) into a file named server.crt, in the proper directory, given above for your web server, and set it to read-only:

# chmod 444 server.crt

Configure Your Web Server to Use the Private Key and Certificate

If you are using a firewall, you will need to enable incoming TCP traffic to port 443.

For Apache

Edit /etc/httpd/conf/httpd.conf and uncomment these lines:

LoadModule ssl_module modules/mod_ssl.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
Include conf/extra/httpd-ssl.conf

Note if you are using virtual hosts, making the above change to /etc/httpd/conf/httpd.conf will use the same certificate on all hosts. To give each host its own certificate to avoid browsers complaining about the certificate not matching the domain name, you need to edit each of their configuration files in /etc/httpd/conf/vhosts/ to point to its own certificate and private key:

  • Change <VirtualHost *:80> to <VirtualHost *:80 *:443>.

  • Within the VirtualHost section, add the following:

      SSLEngine on
      SSLCertificateFile "/etc/httpd/conf/YOUR-DOMAIN-NAME.com.crt"
      SSLCertificateKeyFile "/etc/httpd/conf/YOUR-DOMAIN-NAME.com.key"

Restart Apache:

# systemctl restart httpd

For Nginx

Edit /etc/nginx/nginx.conf and near the bottom, uncomment out the HTTPS server section and change the lines to the following:

ssl_certificate      server.crt;
ssl_certificate_key  server.key;
root                /usr/share/nginx/html;

Note if you are using virtual hosts, making the above change to /etc/nginx/nginx.conf will send all hosts into that location. To give each host its own certificate, you need to edit each of their configuration files in /etc/nginx/sites-enabled/ to have an additional server block to point to its own certificate and private key:

server {
    listen 443 ssl;
    server_name YOUR-DOMAIN-NAME.com;

    ssl_certificate      YOUR-DOMAIN-NAME.com.crt;
    ssl_certificate_key  YOUR-DOMAIN-NAME.com.key;

    ssl_session_cache   shared:SSL:1m;
    ssl_session_timeout 5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    location / {
        root /usr/share/nginx/YOUR-DOMAIN-NAME.com;
        index  index.html index.htm;
    }
}

Restart Nginx:

# systemctl restart nginx