Files
spothole/docs/nginx.md
T
2026-08-08 08:42:29 +01:00

5.3 KiB

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.)

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/v1/(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—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:

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