Host a Website on a VPS with Nginx and Let's Encrypt SSL
Point your domain to your VPS, install Nginx, publish your site and secure it with a free Let's Encrypt certificate via Certbot. A practical Ubuntu 24.04 guide.
Running your website on your own VPS gives you far more control than shared hosting: you decide which software runs, how caching behaves and how your certificates are renewed. This guide walks you through installing Nginx on Ubuntu 24.04, publishing your first site and securing it with a free Let's Encrypt certificate using Certbot. By the end you will have a server that serves your site over HTTPS and renews its certificate on its own.
We use example.com throughout; replace it with your own domain. We assume you are logged in as a user with sudo privileges.
What you need
- A VPS running Ubuntu 24.04 with SSH access (new to SSH? See our What is SSH guide).
- A domain name and access to its DNS settings.
- Your server's public IP address.
Step 1: Point your DNS records to the server
Let's Encrypt validates your domain by connecting to it over HTTP, so the domain must resolve to your server before you request a certificate. Create these records at your DNS provider:
| Type | Name | Value |
|---|---|---|
| A | @ | Your server's IPv4 address |
| A | www | Your server's IPv4 address |
| AAAA | @ and www | Your IPv6 address (if you have one) |
If DNS is new territory, our What is DNS article explains the basics. Check propagation from your computer or the server:
dig +short example.com A
dig +short www.example.com A
dig +short example.com AAAA
If you see your server's IP, you are good to go. An empty answer or an old IP means you should wait a little longer. Important: don't add an AAAA record unless your server actually has that IPv6 address and Nginx listens on IPv6 — otherwise validation may hit the wrong address.
Step 2: Install Nginx
Refresh the package index and install Nginx:
sudo apt update
sudo apt install -y nginx
The service starts automatically. Check it:
systemctl status nginx --no-pager
If it says active (running), opening http://YOUR_SERVER_IP in a browser should show the default Nginx welcome page.
Step 3: Allow HTTP and HTTPS in the firewall
If you use UFW, open ports 80 and 443 while keeping SSH reachable:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status
The Nginx Full profile opens both 80/tcp and 443/tcp. Never run ufw enable without the OpenSSH rule, or you may lock yourself out. For the rest of the hardening basics, read our Linux server security checklist.
Step 4: Create the site directory
A separate directory per site makes it easy to host several sites on one server later:
sudo mkdir -p /var/www/example.com/html
sudo chown -R $USER:$USER /var/www/example.com/html
echo '<h1>example.com is live</h1>' > /var/www/example.com/html/index.html
You can upload your real files here later with scp, rsync or Git.
Step 5: Configure an Nginx server block
In Nginx, each site is defined by a "server block". Create a new config file:
sudo nano /etc/nginx/sites-available/example.com
Paste the following:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
Enable it with a symlink into sites-enabled. If you don't need the default site, disable it:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
After every change, test first and reload second:
sudo nginx -t
sudo systemctl reload nginx
Only reload once you see syntax is ok and test is successful. Visiting http://example.com should now show your page.
Step 6: Get a free Let's Encrypt certificate with Certbot
Let's Encrypt is a certificate authority that issues free certificates valid for 90 days. If you want the background, see What is an SSL certificate. Install Certbot and its Nginx plugin from the Ubuntu repositories:
sudo apt install -y certbot python3-certbot-nginx
Note: the Certbot project recommends its snap package for the newest release (
sudo snap install --classic certbot). The Ubuntu package is fine for most setups — just install one or the other, not both.
Request the certificate:
sudo certbot --nginx -d example.com -d www.example.com
On the first run Certbot asks for an email address and for you to accept the terms. It then validates the domain, obtains the certificate and adds listen 443 ssl directives to your server block. Recent Certbot versions also add the HTTP-to-HTTPS redirect automatically; older ones ask — choose "redirect".
Verify the result:
curl -I http://example.com
curl -I https://example.com
The first should return 301 Moved Permanently pointing to HTTPS, the second 200 OK.
Step 7: Confirm automatic renewal
Certbot installs a systemd timer that renews certificates before they expire. Check the timer and simulate a renewal:
systemctl list-timers | grep certbot
sudo certbot renew --dry-run
With the snap version, the timer shows up as snap.certbot.renew.timer. If the dry run passes, there's nothing else to do.
Bonus: Nginx as a reverse proxy for your app
Running a Node.js or Python app, or a Docker container, on port 3000? Put Nginx in front and terminate SSL there. Replace the location / block with:
location / {
proxy_pass http://127.0.0.1:3000;
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";
}
The Upgrade and Connection headers are needed for WebSocket apps. Bind your app to 127.0.0.1 so port 3000 stays closed to the internet. New to containers? Our Docker installation guide gets you started.
Troubleshooting common errors
Certbot reports "Timeout during connect" or "Connection refused". Port 80 isn't reachable. Check the firewall with sudo ufw status and confirm Nginx is listening with sudo ss -tlnp | grep :80.
"NXDOMAIN" or the wrong IP. DNS hasn't propagated or is misconfigured. Re-run dig +short; remove any AAAA record that points to a wrong IPv6 address.
"too many certificates already issued". You've hit Let's Encrypt rate limits. Experiment with --dry-run or --staging, and wait for the limit to reset.
502 Bad Gateway. With a reverse proxy, the backend app isn't running or is on another port. Test it directly with curl http://127.0.0.1:3000 and read sudo tail -n 50 /var/log/nginx/error.log.
Site breaks after an edit. Run sudo nginx -t; the error message usually names the file and line.
Frequently Asked Questions
Is a Let's Encrypt certificate really free?
Yes. Let's Encrypt issues domain-validated (DV) certificates at no cost. They last 90 days, but Certbot renews them automatically, and browsers trust them just like paid DV certificates.
Can I host several websites on one VPS?
Yes. Create a separate directory under /var/www and a separate server block under /etc/nginx/sites-available for each site, then run certbot --nginx -d yourdomain for each one. Your limit is the server's RAM and CPU.
Why Nginx instead of Apache?
Nginx serves static files and many concurrent connections with little memory and is the most common reverse proxy in front of apps — a real advantage on a small VPS. If your application depends on Apache-specific .htaccess rules, Apache is still a solid choice.
Host your site on a VPS in Istanbul
Everything in this guide runs comfortably on our smallest plans. TürkiyeVPS VPS plans start at $0.89/month and come with Ubuntu 24.04 or Debian 12, full root access and unlimited traffic, provisioned automatically as soon as your payment is confirmed. For busier sites or more predictable performance, take a look at our VDS plans with dedicated vCPU. Stuck on a step? Reach us via live chat on the site or open a support ticket.
You might also like
If apps keep dying on your 512 MB or 1 GB VPS, swap is the first aid. Learn how to add swap on Ubuntu 24.04, p...
Your bot shouldn't go silent when your laptop sleeps. Learn how to run a Python Telegram bot 24/7 on an Ubuntu...
Planning a Metin2 server but unsure whether a VPS is enough or you need a VDS? We compare shared vs dedicated...