homeautomation homeassistant hobby tech nginx

HomeAutomation: Nginx Quick Setup with SSL (Draft)

2019-05-05

Seeing as more and more people ask similar questions about Home Automation, Home Assistant, Nginx, SSL and the like I decided to just start writing up some guides and directing them here instead of trying to explain same things multiple times :) I figure that's better for all parties involved.

This and other posts will be updated based on new questions and user feedback.


Here's how you could quickly(ish) setup nginx as reverse proxy for any service that runs directly off a port, like HomeAssistant. I'm going to mostly discuss based on Debian systems, but if you're using RHEL\CentOS\Fedora and the like you should have no problem translating these commands. This guide is mostly aimed at people trying to setup nginx and ssl for HomeAssistant but will just as well work as a starting point for Nginx+SSL for any other services you may use, including hosting websites on VPS. This guide will only cover basic proxy_pass setup and using certbot to get Let's Encrypt SSL certificate. It will not cover using more advanced features of nginx like php\html serving and the like.

I'll start with manual approach, one I use mostly because I'm used to it. It also allows to use the full power of nginx when I need it and to easily server multiple different services.

Nginx and Encryption with Hass.io

This is probably the easiest way if you already has Hass.io or HassOS running, or if you want to set it up FOR Hass.io or HassOS.

Go to Hass.io and install this Community Addon: https://github.com/hassio-addons/addon-nginx-proxy-manager/blob/v0.1.0/README.md

T Note that if you set it up by following instructions on addon's page this nginx instance will become main nginx instance in your network, so you'll be able to use it to serve any services from your network. You won't need any other nginx server in your network.

This addon has limited configuration options compared to manual nginx install, for example it does not seem to be able to serve PHP services directly. However it is designed to be used with Docker containers, and all Docker containers that serve any kind of web service (including php websites like Nextcloud, Bookstack) do that through a port already.

I did not try this personally but from the looks of it this approach seems to be the most user-friendly and actually quite quick to setup. I might even switch to it some time later.

Manual setup

First of all we need to install nginx, if not already installed. There are different ways you could install it.

Installing Nginx directly on host system

You can install nginx directly on your system, no dockers, no containers. This works best if you're installing it on a VPS or

On debian based systems apt is the command you use to install new software from repositories. In older systems it was apt-get , and you may still need to use apt-get in some cases. But for this guide using apt will suffice.

So, to install nginx directly on your system run the following command:

sudo apt install nginx

Config files will be located at: /etc/nginx/

HINT: sudo prefix is used to run a command with administrative (root) priviligies. Instead of using sudo each time you can run sudo su once, enter password and you'll be logged into root account and then you can run all commands without the sudo prefix. Use it with caution.

Installing Nginx using docker

If you're familiar with Docker you may install nginx container.

My first "goto" provider of docker containers is "linuxserver.io". They have lots of containers and update them regularly and all have similar setup and parameters. In some rare cases when their docker containers don't work for me I go looking for others, but that's rare.

You can find their docker container and installation instructions here: https://hub.docker.com/r/linuxserver/nginx/

Their default command to create container is this:

docker create \
  --name=nginx \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=Europe/London \
  -p 80:80 \
  -p 443:443 \
  -v :/config \
  --restart unless-stopped \
  linuxserver/nginx

I would update it with:

docker create \
  --name=nginx \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=Europe/London \
  -p 80:80 \
  -p 443:443 \
  -v /path/to/where/you/want/nginx/config/to/be/on/host:/config \
  --restart unless-stopped \
  linuxserver/nginx
  ```

I suggest providing a path on the system driver, preferably SSD, not HDD, this should make Nginx operate and respond faster as it won't need to wait for HDD to spin up to get or write data.

Config files will be located at the path you provided.

#### Installing certbot

```bash
sudo apt-get update 
sudo apt-get install software-properties-common 
sudo add-apt-repository ppa:certbot/certbot 
sudo apt-get update 
sudo apt-get install python-certbot-nginx 

Configuring nginx

To configure Nginx you need to first create configuration file under /etc/nginx/sites-available . Just create a file there (name it however you want, no extension eneded, for example hass ) with this contents:

server {
    listen 80;
    server_name hass.domain.com;
    return         301 https://$server_name$request_uri;
}

server {
    listen       443 ssl;
    server_name  hass.domain.com;

    location / {
        proxy_pass http://IP:PORT; # REPLACE IP AND PORT WITH YOUR SERVICE'S! HASS PORT IS 8123. If Hass is installed on the same machine you can use it's LAN IP or 'localhost'
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # This block is required by HASS, may not be required by other services
    location /api/websocket {
        proxy_pass http://IP:PORT/api/websocket;
        proxy_set_header Host $host;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

    }
}

Once you created this file, run following commands:

sudo ln -s /etc/nginx/sites-available/hass /etc/nginx/sites-enabled/ # To enable the website, this will create a symlink (like a shortcut but better) from sites-available to sites-enabled folder
sudo nginx -s reload && service nginx restart # Reload config and restart nginx
sudo certbot --nginx # To start certbot

After this certbot will guide you through the rest of the setup process. When promted whether to create a Redirect answer No, because we already created it (the listen 80 and return 301 part).

Port Forwarding

You'll need to forward ports 443 and 80 from the router to the machine that you installed Nginx on. It is usually done under WAN settings of your router. Consult with your router's manual or google for your router's port forwarding guides.

After that requests to your IP through a domain name will be served by nginx!

DNS

Setting up DNS is out the scope of this guide, but here are a few things to read about it.

DNS (Domain Name System or Domain Name Server) is a world wide system that allows binding human readable domain names (domain.com) to IP addresses (111.111.111.111). In very basic words it's a world-wide network of interconnected servers that contain a distributed database of domain.name -> ip pairs. You can find a lot of cool YouTube videos explaining how it all works in detail.

Easiest way to set up a domain name is to request your ISP to give you a static IP. Some ISPs will take additional (small) charge for that. Once that's done go to one of the domain name registrars' websites (domain.com, godaddy.com, reg.ru, etc) and register a domain you like. Once there you should be able to create subdomains and forward domain and subdomains to different (or same) IPs.

You can also wish to use other DNS server, not the one of your registrar. I personally like CloudFlare. You can register on CloudFlare, then go to your registrar and change NS settings as described on CloudFlare's guide.