Verified: tested on WSL2 Ubuntu 24.04 — apt install, nginx -t, systemctl start/reload, static site, and reverse proxy all passed.
Install Nginx on Ubuntu/Debian with apt, then walk through config files, starting the service, static sites, and reverse proxy.
1. Install Nginx
Debian/Ubuntu provides the nginx package in the official repositories; install it and it works out of the box[1]:
sudo apt update
sudo apt install nginx
Confirm the version and service status after install:
nginx -v
systemctl status nginx --no-pager
Nginx runs as one master process and several worker processes: the master reads config and manages workers, workers handle requests[2]. It listens on port 80 by default, so the welcome page is reachable right after install.
2. Configuration file layout
The main config /etc/nginx/nginx.conf consists of the global block, events block, and http block; the http block includes site files at the end[2]:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events { worker_connections 768; }
http {
include /etc/nginx/mime.types;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
On Debian/Ubuntu, each site lives in /etc/nginx/sites-available/<name> and is enabled by symlinking into /etc/nginx/sites-enabled/[3]. Validate before reloading after adding a config.
3. Configure a static site
Create a site file and enable it:
sudo tee /etc/nginx/sites-available/mysite <<'EOF'
server {
listen 80;
server_name example.com;
root /var/www/mysite;
index index.html;
}
EOF
sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/mysite
sudo nginx -t
sudo systemctl reload nginx
nginx -t only checks syntax and does not change running state; reload only after it passes, so a bad config never reaches production[4]. reload sends HUP: the master starts new workers and gracefully retires old ones without dropping connections[4].
4. Configure a reverse proxy
Forward requests to a backend app (e.g. 127.0.0.1:3000):
sudo tee /etc/nginx/sites-available/app <<'EOF'
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
EOF
sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/app
sudo nginx -t && sudo systemctl reload nginx
5. Common commands and troubleshooting
| Phenomenon | Cause | Fix |
|---|---|---|
nginx: [emerg] ... |
config syntax error | nginx -t to locate the line, fix, then reload |
Address already in use |
port in use | ss -ltnp | grep :80 to find the process |
| content unchanged after reload | browser cache or no reload | confirm systemctl reload nginx succeeded |
| 502 Bad Gateway | backend down or wrong port | check backend process and proxy_pass address |
| permission denied reading file | root path permissions | chown -R www-data:www-data /var/www/... |
Stop/start/reload: systemctl start|stop|restart|reload nginx, or directly nginx -s reload[4][3].
6. Rollback and limitations
Rollback: remove the symlink in sites-enabled, delete the sites-available file, then nginx -t && systemctl reload nginx; for non-systemd setups, just restore the backed-up config.
Limitations: this machine (WSL2) cannot verify a real public domain, TLS certificate issuance/renewal, or multi-worker behavior under high concurrency; test those in production. TLS config (listen 443 ssl, certificate paths) was not tested locally.
Test record
- Test machine: WSL2 Ubuntu 24.04.4 LTS, kernel 6.6.114.1-microsoft-standard-WSL2; 2026-11-05.
- Nginx version: 1.24.0 (Ubuntu).
- Verified: apt install,
nginx -v,nginx -t, systemctl start/reload, static site on port 8080 returned 200, reverse proxy on 8081 forwarded to python http.server and returned content, purge left no dpkg residue. - Not tested: TLS, real domains, multi-worker concurrency.
FAQ
- What is the difference between apt’s Nginx and the nginx.org official package? The former is slightly older but easier to maintain; follow the official docs to add the repository when you need newer features or specific modules[1].
- Must I reload after editing config? Yes — Nginx does not auto-read new config; run
nginx -t, then reload. - What happens if a symlink in sites-enabled is broken? The include is skipped, so the site is inactive without an error; check with
nginx -t. - Can I skip sites-enabled? Yes — include a custom path directly in the http block of nginx.conf, but the conventional directory is easier to manage.
- Does a trailing slash on proxy_pass matter? Yes — with a slash the matched prefix is stripped before forwarding; without it the URI is forwarded as-is. Choose per your backend routing.
References
- [1] nginx: Linux packages (nginx.org) (nginx-linux-packages)
- [2] Beginner’s Guide (nginx.org) (nginx-beginner)
- [3] nginx(8) – Linux manual page (Debian) (debian-nginx-man)
- [4] Controlling nginx (nginx.org) (nginx-control)
Main commands above were tested on WSL Ubuntu (24.04) and checked against Debian-family and general distribution docs.