Notes: How to configure HTTPS/SSL with Nginx (on a Linode Ubuntu server)

Without any introduction or discussion, here are the notes I made while learning how to get HTTPS working with Nginx. These are just for me, but if something helps you, that’s cool. I refer back to these notes every time I set up a new Linux server.

Summary

In the end this wasn’t hard, I just needed to find a couple of good resources. It doesn’t take long at all once you know what you’re doing.

New Linode Server

  • set up a new server
  • install Ubuntu 16.04
  • turn on firewall
  • create non-root user
  • shut off root ssh access
  • point a domain name at the IP address

Update Everything

sudo apt-get update && sudo apt-get upgrade
sudo apt-get upgrade nginx (or 'install')

Ubuntu Firewall

Initial:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw enable

Later:

sudo ufw allow 80
sudo ufw allow 443

Status:

sudo ufw status verbose

Other:

sudo ufw disable
sudo ufw app list  (output below)
    Available applications:
        Nginx Full
        Nginx HTTP
        Nginx HTTPS
        OpenSSH
sudo ufw allow 'Nginx HTTPS'

Add a New User

Command:

sudo adduser username

add user to “sudo” group:

sudo usermod -aG sudo username

or:

sudo adduser username sudo
  • note: sudo does not work, but i can su -

Disabling Root Login (sshd_config)

sudo vim /etc/ssh/sshd_config
PermitRootLogin no
sudo service sshd restart

Limit Login Attempts (sshd_config)

simple/naive:

PermitRootLogin no
LoginGraceTime 120
# allow only 1 login attempt per connection
MaxAuthTries 1

more info:

Change the SSH login port

I like to change the SSH port so it’s not at the default 22, so I edit this file:

vi /etc/ssh/sshd_config

Change the port to something like this:

Port 5150

Then restart the SSH server daemon:

service sshd restart
# or:
systemctl reload sshd

After you do this you’ll need to update your firewall rules to allow logins on the new port, and deny the old ssh port (being careful, because you may lock yourself out of your server):

ufw default deny incoming
ufw default allow outgoing
ufw deny ssh
ufw allow 5150/tcp
ufw enable
ufw status verbose

 

Install Nginx and MySQL

Install Nginx:

$ sudo apt-get update
$ sudo apt-get install nginx ssl-cert

Output:

The following additional packages will be installed:
  fontconfig-config fonts-dejavu-core libfontconfig1 libgd3 libjbig0 libjpeg-turbo8 libjpeg8 libtiff5
  libvpx3 libxpm4 libxslt1.1 nginx-common nginx-core
Suggested packages:
  libgd-tools fcgiwrap nginx-doc openssl-blacklist
The following NEW packages will be installed:
  fontconfig-config fonts-dejavu-core libfontconfig1 libgd3 libjbig0 libjpeg-turbo8 libjpeg8 libtiff5
  libvpx3 libxpm4 libxslt1.1 nginx nginx-common nginx-core ssl-cert

Install MySQL on Ubuntu:

$ sudo apt-get install mysql-server
$ mysql_secure_installation

Adjust Firewall

Use these commands, as needed:

sudo ufw allow 80
sudo ufw allow 443
sudo ufw allow 'Nginx HTTPS'

Nginx Configuration

Conf file:

/etc/nginx/nginx.conf

Commands:

nginx -t
service nginx reload (stop, start)

Can also use these:

systemctl status nginx
sudo systemctl stop nginx
sudo systemctl start nginx

Nginx log files:

/var/log/nginx/access.log
/var/log/nginx/error.log

Basic config:

server {
    server_name  100.200.200.50;
    listen       80;
    root         /var/www/default;
    index        index.html;
}

More:

server {
    server_name  www.fptracker.com;
    rewrite ^(.*) http://fptracker.com$1 permanent;
}

server {
    server_name  fptracker.com;
    listen       80;
    location / {
        root /var/www/html;
    }
    access_log  /var/log/nginx/fptracker_access.log  main;
    error_log   /var/log/nginx/fptracker_error.log  error;
}

Installing PHP and Composer on Ubuntu

For my purposes I also need to install PHP and Composer, and in September, 2021, I used the commands shown on this page.

Installing Java on Ubuntu

DigitalOcean has good notes on installing Java, but the basic command to install the OpenJDK JRE is:

apt-get install default-jre

and the command to install the OpenJDK JDK/SDK is:

apt-get install default-jdk

Let’s Encrypt

Initially I didn’t use Let’s Encrypt, but I later changed to use it, as I describe in my Notes about HTTPS and Let’s Encrypt.

Adjust the Firewall

sudo ufw allow 'Nginx Full'
sudo ufw status

Enable the Changes in Nginx

$ sudo nginx -t
$ service nginx restart

Test in Browser

kinda-sorta expected errors:

- "your connection is not secure"
- The certificate is not trusted because it is self-signed. 
~ (GONE THE SECOND TIME) The certificate is not valid for the name fptracker.com.

Nginx "default_server"

  • The default_server parameter has been available since version 0.8.21.
  • In this configuration nginx tests only the request’s header field “Host” to determine which server the request should be routed to. If its value does not match any server name, or the request does not contain this header field at all, then nginx will route the request to the default server for this port. In the configuration above, the default server is the first one — which is nginx’s standard default behaviour. It can also be set explicitly which server should be default, with the default_server parameter in the listen directive:

    server { listen 80 defaultserver; servername example.net www.example.net; ... }

Can change to a permanent redirect (301)

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name server_domain_or_IP;
    return 301 https://$server_name$request_uri;
}

More Security: Preventing Information Disclosure

  • https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-on-ubuntu-14-04#step-2-%E2%80%94-preventing-information-disclosure
  • /etc/nginx/nginx.conf:
http {
    server_tokens off;  <-- ADD THIS (show only 'nginx', no version number)

More Security: Fail2Ban

Restricting Access by IP Address

server {
...
    location /wp-admin/ {
        allow 192.168.1.1/24;
        allow 10.0.0.1/24;
        deny  all;
    }
...

See also