Nginx is a lightweight, high-performance web server and reverse proxy. As a reverse proxy, Nginx accepts requests from clients and forwards them to backend applications (e.g. Home Assistant on port 8123, Frigate on port 5000) — so everything is accessible through ports 80/443 with different domains.
http://192.168.1.10:8123, you can access it at https://ha.domain.com. One public IP can serve multiple services, with centralized SSL at Nginx.Requirements
- OS Ubuntu / Debian
- Root or sudo access
- A domain pointing to the server IP (for SSL setup)
- Ports 80 and 443 open in the firewall
Install Nginx
-
1
Install Nginx from the Official Repository
apt update apt install -y nginx # Make sure Nginx is running systemctl enable nginx systemctl start nginx systemctl status nginx
Open a browser to
http://Server-IP— if you see the "Welcome to nginx!" page, the installation was successful. -
2
Understand the Nginx Directory Structure
/etc/nginx/ ├── nginx.conf # Main configuration ├── sites-available/ # All virtual host configs (active/inactive) └── sites-enabled/ # Symlinks to active sites-available configs
Best practice: create a config per domain in
sites-available/, then activate it with a symlink tosites-enabled/.
Reverse Proxy Configuration
Example: Proxy to Home Assistant
Create a new config file at /etc/nginx/sites-available/homeassistant:
server {
listen 80;
server_name ha.domain.com;
location / {
proxy_pass http://127.0.0.1:8123;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support (required for Home Assistant)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}Example: Proxy to Frigate NVR
Create file /etc/nginx/sites-available/frigate:
server {
listen 80;
server_name frigate.domain.com;
# Increase upload limit for snapshots/clips
client_max_body_size 100M;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}Enable Virtual Hosts
# Create symlinks to enable the configs ln -s /etc/nginx/sites-available/homeassistant /etc/nginx/sites-enabled/ ln -s /etc/nginx/sites-available/frigate /etc/nginx/sites-enabled/ # Remove default config if not needed rm /etc/nginx/sites-enabled/default # Test configuration nginx -t # Reload Nginx systemctl reload nginx
nginx -t before reloading to ensure there are no syntax errors in the configuration files.SSL Setup with Let's Encrypt (Certbot)
-
1
Install Certbot
apt install -y certbot python3-certbot-nginx
-
2
Obtain an SSL Certificate
Certbot will automatically detect the domains from the Nginx config and handle HTTP verification:
certbot --nginx -d ha.domain.com -d frigate.domain.com
Follow the prompts: enter your email, agree to the ToS, and choose whether to auto-redirect HTTP → HTTPS (recommended: Yes).
-
3
Verify Auto-Renewal
Certbot automatically adds a cronjob to renew certificates before they expire (90 days). Test a dry run:
certbot renew --dry-run
After Certbot finishes, the Nginx config files will be automatically updated with SSL configuration. The result looks something like this:
server {
listen 443 ssl;
server_name ha.domain.com;
ssl_certificate /etc/letsencrypt/live/ha.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ha.domain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://127.0.0.1:8123;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
server {
listen 80;
server_name ha.domain.com;
return 301 https://$host$request_uri;
}Common Nginx Commands
# Test configuration (always run before reloading) nginx -t # Reload configuration without dropping connections systemctl reload nginx # Restart Nginx systemctl restart nginx # View access log tail -f /var/log/nginx/access.log # View error log tail -f /var/log/nginx/error.log
Tip: One Config for Multiple Subdomains
If you have many services, you can create a cleaner single file using upstream blocks:
# /etc/nginx/sites-available/services
upstream homeassistant { server 127.0.0.1:8123; }
upstream frigate { server 127.0.0.1:5000; }
server {
listen 443 ssl;
server_name ha.domain.com;
# ... ssl config ...
location / { proxy_pass http://homeassistant; }
}
server {
listen 443 ssl;
server_name frigate.domain.com;
# ... ssl config ...
location / { proxy_pass http://frigate; }
}ufw allow 'Nginx Full'. If using a cloud provider (AWS, GCP, etc.), open those ports in Security Group / Firewall rules.