## nginx Reverse Proxy configuration

Web servers generally serve their pages from port 80. However, it's best not to serve Spothole's web interface directly
on port 80, as that requires root privileges on a Linux system. It also and prevents us using HTTPS to serve a secure
site, since Spothole itself doesn't directly support acting as an HTTPS server. The normal solution to this is to use
a "reverse proxy" setup, where a general web server handles HTTP and HTTP requests (to port 80 & 443 respectively), then
passes on the request to the back-end application (in this case Spothole). nginx is a common choice for this general web
server.

To set up nginx as a reverse proxy that sits in front of Spothole, first ensure it's installed e.g.
`sudo apt install nginx`, and enabled e.g. `sudo systemd enable nginx`.

Create a file at `/etc/nginx/sites-available/` called `spothole`. Give it the following contents, replacing
`spothole.app` with the domain name on which you want to run Spothole. If you changed the port on which Spothole runs,
update that on the "proxy_pass" line, and if you installed Spothole somewhere other than `/home/spothole/spothole`,
adjust the alias location for serving static files.

(The latter section, configuring the nginx server to serve static files directly, improves efficiency because it saves
Spothole itself from serving JS, CSS etc. files. If you can't do this for some reason, e.g. your nginx and spothole are
on different computers, you can omit the `location /static/ {}` block.)

```nginx
server {
    server_name spothole.app;

    # Global proxy settings
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_connect_timeout 10s;
    proxy_buffering on;
    
    # Pass on IP address and host information to Spothole, in case logging this information is required
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;

    # Wellknown area for Lets Encrypt
    location /.well-known/ {
        alias /var/www/html/.well-known/;
    }

    # Load static assets directly from the Spothole static directory
    location /static/ {
        alias /home/spothole/spothole/static/;
        expires 1h;
        add_header Cache-Control "public, max-age=3600, must-revalidate";
    }
    
    # SSE endpoints
    location ~ ^/api/v\d*/(spots|alerts)/stream/? {
        proxy_pass http://127.0.0.1:8080;
        
        # Remove buffering, remove caching, add suitable timeouts for SSE API calls
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 24h;
        proxy_send_timeout 24h;
        proxy_set_header X-Accel-Buffering no;
        add_header Cache-Control no-store always;
        
        # Allow cross-origin requests to API
        proxy_hide_header Access-Control-Allow-Origin;
        add_header Access-Control-Allow-Origin * always; 
    }

    # Other API endpoints
    location /api/ {
        proxy_pass http://127.0.0.1:8080;
        
        # Remove buffering, remove caching, add suitable timeouts for API calls
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 30s;
        add_header Cache-Control no-store always;
        
        # Allow cross-origin requests to API
        proxy_hide_header Access-Control-Allow-Origin;
        add_header Access-Control-Allow-Origin * always;
    }

    # Templated pages
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_read_timeout 30s;
        add_header Cache-Control "no-cache, must-revalidate" always;
    }
}
```

One further change you might want to make to the file above is the `add_header Access-Control-Allow-Origin` statements.
These are what's used on
my own Spothole server to make sure that other third-party web-based software can get the data from my instance, and
applies to any endpoint underneath `/api`. If you want
*your* Spothole instance to be set up the same way, so that others can write software in JavaScript that can access it,
leave this intact. But if you want your Spothole instance to only be usable by scripts running on the web server you
write,
you can remove these lines. (Note that this doesn't stop other people writing *non-web-based* software that accesses
your
Spothole API&mdash;the enforcement of cross-origin headers only happens within the user's browser. If you need to lock
your
instance down so that no-one else can access it with *any* software, that's an aspect of nginx or firewall config that
you will need
to find help with elsewhere.)

Now, make a symbolic link to enable the site:

```bash
cd /etc/nginx/sites-enabled
sudo ln -sf ../sites-available/spothole
```

Test that your nginx config isn't broken using `nginx -t`. If it works, restart nginx with
`sudo systemctl restart nginx`.

If you haven't already done so, set up a DNS entry to make sure requests for your domain name end up at the server
that's running Spothole.

You should now be able to access the web interface by going to the domain from your browser.

Once that's working, [install certbot](https://certbot.eff.org/instructions?ws=nginx&os=snap) onto your server. Run it
as root, and when prompted pick your domain name from the list. After a few seconds, it should successfully provision a
certificate and modify your nginx config files automatically. You should then be able to access the site via HTTPS.
