Skip to content

HOWTO devops SSL_server_setup

steveoro edited this page Jan 16, 2021 · 2 revisions

HOWTO: DevOps: SLL server setup, with Docker

References (updated, 2020):

Synopsis:

Using and enabling HTTPS instead of the plain HTTP protocol requires:

  • using port 443 instead of the standard web 80 & configure Apache2 accordingly;
  • having a valid SSL certificate associated to the running domain & server.

If the SSL certificate is missing, you need to:

  • create a private key associated to the running domain & server;
  • create a CSR certificate request to send to the certified provider of the SSL certificate;
  • install on the server the private key file, the returned SSL certificate and, in most cases, an intermediate certificate.

Giving the 2 or 3 files stored locally before the deploy, our deploy:setup Capistrano takes care of all the steps.

References:


Setup for a semi-automatic certificate from "Let's Encrypt":

Follow step-by-step procedure at How To Secure Apache with Let's Encrypt on Ubuntu 16.04.

Basically, you need to install their client ("Certbot") which will handle most of the details. The client is in frequent development, so installing directly from the repository is almost mandatory.

$> sudo add-apt-repository ppa:certbot/certbot
$> sudo apt-get update
$> sudo apt-get install python-certbot-apache

Use certbot to define a base domain (master-goggles.org) and an alternative domain (www.master-goggles.org), and follow the interactive procedure:

$> sudo certbot --apache -d master-goggles.org -d www.master-goggles.org

If you have multiple virtual hosts, you should run certbot once for each to generate a new certificate for each. You can distribute multiple domains and subdomains across your virtual hosts in any way.

When the installation is finished, you should be able to find the generated certificate files at /etc/letsencrypt/live. You can check that the installation of the new certificate has been successful, by checking https://www.ssllabs.com/ssltest/analyze.html?d=master-goggles.org&latest (only for the base domain).

Let’s Encrypt certificates only last for 90 days.

However, the certbot package we installed takes care of this for us by running certbot renew twice a day via a systemd timer. On non-systemd distributions this functionality is provided by a cron script placed in /etc/cron.d. The task runs twice daily and will renew any certificate that's within thirty days of expiration.

To test the renewal process, you can do a dry run with certbot: sudo certbot renew --dry-run.

If you see no errors, you're all set. When necessary, Certbot will renew your certificates and reload Apache to pick up the changes. If the automated renewal process ever fails, Let’s Encrypt will send a message to the email you specified, warning you when your certificate is about to expire.


Scripted/manual setup for a 3rd-party certificate from a Cert.Authority:

Assuming the server on which the certificate does not have any previous SSL certificate to be renewed, what follows is the setup procedure from scratch.

If a previous SSL certificate has already been obtained on the same machine, allegedly the CSR Certificate request file to send to the SSL cert provider should be the same (so keep this file safe somewhere).

1. Private Server Key generation

Generate the private key at 2048 bit for the remote server by typing:

$ root@master-goggles:/etc/apache2/cert> openssl genrsa -out ./master-goggles.org.key 2048
Generating RSA private key, 2048 bit long modulus
[...snip...]

$ root@master-goggles:/etc/apache2/cert> cat master-goggles.org.key
-----BEGIN RSA PRIVATE KEY-----
    [...snip...]
-----END RSA PRIVATE KEY-----

2. CSR Certificate Request generation

Generate a CSR certificate request by typing:

$ root@master-goggles:/etc/apache2/cert> openssl req -new -sha256 -key ./master-goggles.org.key -out ./master-goggles.org.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) [AU]:IT
State or Province Name (full name) [Some-State]:Modena
Locality Name (eg, city) []:Modena
Organization Name (eg, company) [Internet Widgits Pty Ltd]:FASAR Software
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:www.master-goggles.org
Email Address []:info@master-goggles.org

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

$ root@master-goggles:/etc/apache2/cert> cat master-goggles.org.csr
-----BEGIN CERTIFICATE REQUEST-----
MIIC7jCCAdYCAQAwgYkxCzAJBgNVBAYTAklUMQ8wDQYDVQQIDAZNb2RlbmExDzAN
    [...snip...]
tsLJ3S21xfXVVc6rAhRV+mb15LttxQZMI8pxM5E+M5XCwg==
-----END CERTIFICATE REQUEST-----

CSR Certificate verification

Perform a verification of the generated CSR certificate by typing:

$ root@master-goggles:/etc/apache2/cert> openssl req -noout -text -in ./master-goggles.org.csr

Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: [...snip...], CN=www.master-goggles.org/emailAddress=info@master-goggles.org
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
    [...snip...]

3. Obtain the actual SSL Certificate

As a backup strategy, copy the 2 certificates locally on the deploy workstation (assuming the local path exist and is correct) with a simple scp:

[Local]

$> cd ~/projects/goggles.docs/.secrets_and_sensible_stuff/SSL_certs
$> scp root@<REMOTE_SERVER_IP>:/etc/apache2/cert/* .

Copy the contents of just the public CSR certificate request file and paste them in the form for the renewal request. Once the renewal or a new subscription has been obtained, copy the attached files in the same directory of the locally stored CSR & KEY file.

Verify that the file names inside the configuration for the deploy context are all valid. Check out, for instance config/deploy/production.rb. The Capistrano deploy:setup should be configured to take care of all the rest.

4. Rebuild Apache2 configuration

Rebuild the Apache2 configuration with the dedicated Capistrano recipe:

$> ROLES=web cap production deploy:setup

This will recreate all the required setup files and directory structure on the remote server configured with the values contained inside the config/deploy/production.rb file (including the remote Apache2 configuration file).

If the server port parameter inside the Capistrano configuration file is configured as "443", in addition to regenerate a new configuration, the script will:

  • set the proper parameters to point to the certificate files;
  • check for missing certificate files on the remote server;
  • install any missing certificate by upload any missing file from the local path specified in the Capistrano configuration file to the desired remote directory.

In case of errors, check the values inside the "production.rb" script to verify the validity of any pathnames.

(Since a lot of stuff is accessed & pre-configured locally, the deploy configuration should be customized for each workstation that has to deploy to the remote server.)

5. Finishing touches and Apache2 restart

Make sure the Apache autoindex module is disabled, or HTTP traffic will show in plain sight the contents of the site:

$> a2dismod autoindex

Make sure there an Apache2 section for permanent redirect in its configuration, to redirect all insecure traffic to the secured 443 port: (This is also currently added automatically by the Capistrano recipe.)

-----8<----- [vi /etc/apache2/enabled-sites/master-goggles.conf]

# [...]

<VirtualHost *:80>
    ServerName www.master-goggles.org
    Redirect permanent / https://www.master-goggles.org/
    </VirtualHost>

    # [...]

-----8<-----

When editing the configuration by hand, test validate its syntax with:

$> apachectl configtest

If everything is ok, restart Apache service to switch to the newly generated configuration:

$> service apache2 restart

In case of errors, check both the error log files (web server & app server):

  • Apache2: typically, $ tail /var/log/apache2/error.log -n 50
  • Passenger/Rails: typically, $ tail /var/www/master-goggles.org/current/log/error.log -n 50

If everything is properly configured, by requesting something like "http://www.master-goggles.org/users/sign_in" you should find yourself redirected to "https://www.master-goggles.org/users/sign_in" instead.

Clone this wiki locally