Introduction
Nginx (pronounced "engine-x") is one of the most popular web servers in the world. It powers a huge share of the internet's busiest sites because it is fast, lightweight, and excellent at handling many simultaneous connections with very little memory. If you are setting up a VPS, a personal project, or a client website, Nginx is very likely the web server you want.
In this guide, you will install Nginx on Ubuntu 22.04 LTS (Jammy Jellyfish), open the right firewall ports, serve the default welcome page, set up a server block for your own domain, and secure everything with free HTTPS from Let's Encrypt. By the end, you will have a production-ready web server and the skills to manage it.
This guide is written for developers, students, and anyone configuring their first Linux server. Every command is explained as we go, so you will understand what you are doing — not just copy and paste.
Prerequisites
- A server or virtual machine running Ubuntu 22.04 LTS.
- A non-root user with
sudoprivileges (or root access). - Basic comfort with the Linux terminal — you can run commands and edit a text file.
- Optional: a domain name whose DNS A record points to your server's public IP (only needed for the server-block and HTTPS steps; the install itself works fine with just an IP address).
Step 1 — Update the system packages
Before installing anything, refresh the package index and apply pending updates. This makes sure you install Nginx against current dependencies and pick up the latest security fixes.
sudo apt update && sudo apt upgrade -y
apt update downloads the newest list of available packages, while apt upgrade -y installs the updates automatically without asking for confirmation. This step can take a couple of minutes on a fresh server.
Step 2 — Install Nginx
Ubuntu's official repositories include Nginx, so installation is a single command:
sudo apt install nginx -y
This downloads and installs Nginx along with its default configuration. Ubuntu 22.04 ships Nginx 1.18.0 in its repositories — a stable, well-tested release that is perfectly fine for most uses.
Confirm the installed version:
nginx -v
You should see output like nginx version: nginx/1.18.0 (Ubuntu). If you ever need a newer release, Nginx maintains its own official PPA — but for a standard setup, the repository version is the safest choice.
Step 3 — Allow Nginx through the firewall
Ubuntu 22.04 usually ships with UFW (Uncomplicated Firewall) installed but disabled. If your firewall is active, web traffic will be blocked until you explicitly allow it. Nginx conveniently registers three application profiles with UFW:
- Nginx HTTP — opens port 80 only (plain HTTP).
- Nginx HTTPS — opens port 443 only (encrypted HTTPS).
- Nginx Full — opens both ports 80 and 443.
Allow full web traffic with one command:
sudo ufw allow 'Nginx Full'
The profile name must be quoted because it contains a space. This single rule covers both HTTP and HTTPS, so you will not need to touch the firewall again when you add SSL later.
Now check the firewall status:
sudo ufw status
If UFW is inactive and you want to turn it on, run sudo ufw enable — but allow SSH first (sudo ufw allow OpenSSH) or you will lock yourself out of a remote server. If you are on a cloud VPS (AWS, DigitalOcean, Hetzner), also check the provider's security group / firewall panel and open ports 80 and 443 there.
Step 4 — Start and enable the Nginx service
On Ubuntu, Nginx is managed by systemd. Start it now and make it launch automatically on every boot:
sudo systemctl start nginx
sudo systemctl enable nginx
start launches the Nginx process immediately, while enable creates the symlink that makes systemd start Nginx whenever the server reboots. For a web server, you always want both.
Check that the service is healthy:
sudo systemctl status nginx
Look for Active: active (running) in green. Press q to exit the status view and return to your prompt.
Step 5 — Verify the installation
The quickest local check is to request the default page with curl:
curl -I http://localhost
You should see HTTP/1.1 200 OK along with a Server: nginx/1.18.0 header. That header is Nginx announcing itself — the install worked.
For the real-world check, open http://your_server_ip in your own browser (replace your_server_ip with the server's public IP address). You should see the familiar "Welcome to nginx!" page. If you see it, Nginx is installed, running, and reachable from the internet.
You can find your server's public IP with:
curl -4 icanhazip.com
Step 6 — Learn the essential Nginx management commands
You will use these four commands constantly, so it is worth learning them now:
sudo systemctl stop nginx
sudo systemctl reload nginx
sudo systemctl restart nginx
sudo nginx -t
stop shuts Nginx down. reload applies configuration changes without dropping active connections — this is the command you will use after editing config files. restart fully stops and starts the service, which briefly interrupts traffic; use it only when reload is not enough.
nginx -t tests your configuration files for syntax errors before you reload. Make it a habit: edit config, run nginx -t, then reload. It prints the exact file and line number when something is wrong.
Step 7 — Set up a server block for your domain
A server block (Nginx's version of Apache's virtual host) lets one Nginx instance serve multiple websites. Even with a single site, using a server block instead of the default config keeps things clean and easy to extend.
First, create a directory to hold your site's files:
sudo mkdir -p /var/www/example.com/html
sudo chown -R $USER:$USER /var/www/example.com/html
sudo chmod -R 755 /var/www/example.com
This creates the document root, gives your user ownership so you can edit files without sudo, and sets permissions so Nginx can read them.
Create a simple test page:
nano /var/www/example.com/html/index.html
Paste in the following, save, and exit (Ctrl+O, Enter, Ctrl+X):
<html>
<head><title>Welcome to example.com</title></head>
<body><h1>Success! example.com is served by Nginx.</h1></body>
</html>
Now create the server block configuration file:
sudo nano /etc/nginx/sites-available/example.com
Add this configuration (replace example.com with your real domain):
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Here is what each part does: listen 80 tells Nginx to accept IPv4 traffic on port 80; server_name matches incoming requests by domain name; root points at your site's files; index defines the default file; and try_files serves the requested file, then the directory index, then a 404 page.
Enable the site by linking it into the active directory, then test and reload:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
The symlink pattern (available vs. enabled) lets you keep configs for sites you are not currently serving. If nginx -t reports success, visiting http://example.com should now show your test page. If the default welcome page still appears, your browser may be hitting the old default server block — clear the cache or check the symlink.
Step 8 — Secure Nginx with free HTTPS using Let's Encrypt
HTTPS is no longer optional: browsers flag plain-HTTP sites as "Not secure," and search engines rank HTTPS pages higher. Certbot from the EFF automates free certificates from Let's Encrypt, and its Nginx plugin edits your server block for you.
Install Certbot and its Nginx plugin:
sudo apt install certbot python3-certbot-nginx -y
Then request and install a certificate (your domain's DNS must already point to this server):
sudo certbot --nginx -d example.com -d www.example.com
Certbot will ask for an email address (for expiry warnings), have you agree to the terms, and ask whether to redirect HTTP to HTTPS — choose the redirect. It then modifies your server block automatically to serve port 443 with the new certificate.
Let's Encrypt certificates expire after 90 days, but Certbot installs a systemd timer that renews them automatically. Verify the renewal process works with a dry run:
sudo certbot renew --dry-run
If the dry run succeeds, renewals will happen silently in the background. Your site is now served over HTTPS with a valid certificate — confirm the padlock icon in your browser.
Verify it worked
Run through this checklist to confirm your Nginx setup is complete and healthy:
sudo systemctl is-active nginxshould printactive.curl -I http://localhostshould returnHTTP/1.1 200 OKwith aServer: nginxheader.- Open
http://your_server_ip(orhttps://example.comafter Step 8) in a browser — your page should load. sudo ss -tulpn | grep nginxshould show Nginx listening on ports 80 and 443.- Visit an SSL checker like
ssllabs.com/ssltestafter enabling HTTPS to confirm your certificate chain is clean.
Common issues and fixes
1. "bind() failed — address already in use" on port 80
Something is already listening on port 80 — very often an Apache installation. Find the culprit:
sudo ss -tulpn | grep ':80'
If you see apache2, stop and disable it, then start Nginx:
sudo systemctl stop apache2
sudo systemctl disable apache2
sudo systemctl start nginx
A server should run one web server on port 80, not two.
2. The site loads locally but not from your browser
This is almost always a firewall problem. First, re-check UFW:
sudo ufw status
Make sure Nginx Full shows as ALLOW. Second, check your cloud provider's firewall — AWS security groups, DigitalOcean firewalls, and Hetzner Cloud firewalls all filter traffic before it reaches UFW, and port 80/443 must be open there too.
3. 403 Forbidden after creating a server block
Nginx cannot read your files. The web root and everything above it must be readable by the www-data user that Nginx workers run as. Fix ownership and permissions:
sudo chown -R www-data:www-data /var/www/example.com/html
sudo chmod -R 755 /var/www/example.com
Then reload Nginx and try again.
4. nginx: [emerg] unknown directive when reloading
There is a typo in your configuration. Run sudo nginx -t — it prints the exact file and line number of the error. The most common cause by far is a missing semicolon at the end of a directive line.
5. Certbot fails with a connection timeout
Let's Encrypt must reach your server on port 80 to validate the domain. Check three things: the domain's DNS A record points to your server's IP (dig +short example.com), port 80 is open in UFW and your cloud firewall, and Nginx is running. Fix those and re-run sudo certbot --nginx -d example.com.
Conclusion
You have now installed Nginx on Ubuntu 22.04, opened the right firewall ports, verified the installation, created a server block for your own domain, and secured it with a free Let's Encrypt certificate that renews itself. That is a complete, production-ready web server — the same foundation used by millions of sites.
From here, the natural next steps are tuning Nginx performance, setting up PHP-FPM or a reverse proxy for your application, and adding monitoring. If you would rather have an expert handle it, XpertBees sets up, secures, and maintains production Linux servers for businesses — reach out through our contact page and we will take it from here.



