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.


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


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


sudo ufw allow 80
sudo ufw allow 443


sudo ufw status verbose


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

Add a New User


sudo adduser username

add user to “sudo” group:

sudo usermod -aG sudo username


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)


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


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:



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:


Basic config:

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


server {
    rewrite ^(.*)$1 permanent;

server {
    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

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; ... }

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

  • /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/ {
        deny  all;

See also