DEV Community

Cover image for How to Set Up a Private VPS Server for Your Website
Arthur
Arthur

Posted on

How to Set Up a Private VPS Server for Your Website

I’m Henry, the author of this blog, and I want to show you how I’d actually set up a private VPS server for a website.

Not the “click three buttons and everything magically works” version.

I mean the real setup: SSH, users, Nginx, DNS, SSL, firewall rules, updates, backups, and a few things that are easy to forget until something breaks at 2 AM.

If you’re comfortable with the command line, this is a useful project to build. And honestly, managing your own server is one of those things where you learn a lot very quickly.

Sometimes the server teaches you.

Sometimes it teaches you with an error message that makes absolutely no sense.

What We’re Building

By the end, the setup will look roughly like this:

Domain
   |
   v
DNS
   |
   v
VPS Public IP
   |
   v
Nginx
   |
   +---- HTTPS
   |
   +---- Website
   |
   +---- Application
Enter fullscreen mode Exit fullscreen mode

I’ll use Ubuntu Server in the examples, but the same ideas apply to most Linux VPS environments.

You’ll need:

  • A VPS with root access
  • Ubuntu Server
  • A domain name
  • SSH access
  • A website or web application
  • A little patience

That last one is optional, but highly recommended.

1. Connect to the VPS

After creating the VPS, you’ll normally receive its public IP address.

Connect through SSH:

ssh root@YOUR_SERVER_IP
Enter fullscreen mode Exit fullscreen mode

The first thing I’d do is create a normal user instead of doing everything as root.

adduser henry
usermod -aG sudo henry
Enter fullscreen mode Exit fullscreen mode

Then test the new account:

su - henry
sudo whoami
Enter fullscreen mode Exit fullscreen mode

If the output is:

root
Enter fullscreen mode Exit fullscreen mode

you’re good.

Running everything as root because it’s “faster” is one of those shortcuts that feels clever right up until you accidentally delete something important.

2. Update the Server

Before installing anything, update the package lists and existing packages:

sudo apt update
sudo apt upgrade -y
Enter fullscreen mode Exit fullscreen mode

I also like checking whether the server needs a reboot:

[ -f /var/run/reboot-required ] && echo "Reboot required"
Enter fullscreen mode Exit fullscreen mode

If necessary:

sudo reboot
Enter fullscreen mode Exit fullscreen mode

Reconnect after the server comes back.

3. Set Up SSH Properly

SSH is going to be one of your main doors into the server, so don’t leave it wide open.

Ideally, use SSH keys instead of password authentication.

From your local machine:

ssh-keygen -t ed25519
Enter fullscreen mode Exit fullscreen mode

Copy the public key to the VPS:

ssh-copy-id henry@YOUR_SERVER_IP
Enter fullscreen mode Exit fullscreen mode

Then test:

ssh henry@YOUR_SERVER_IP
Enter fullscreen mode Exit fullscreen mode

Once key authentication is working, you can disable password authentication in the SSH configuration.

Open:

sudo nano /etc/ssh/sshd_config
Enter fullscreen mode Exit fullscreen mode

Look for:

PasswordAuthentication yes
Enter fullscreen mode Exit fullscreen mode

Change it to:

PasswordAuthentication no
Enter fullscreen mode Exit fullscreen mode

Then validate and restart SSH:

sudo sshd -t
sudo systemctl restart ssh
Enter fullscreen mode Exit fullscreen mode

Always test another SSH session before closing your current one.

That little habit can save you from locking yourself out of your own server.

4. Configure the Firewall

Ubuntu commonly uses UFW for basic firewall management.

First:

sudo ufw default deny incoming
sudo ufw default allow outgoing
Enter fullscreen mode Exit fullscreen mode

Allow SSH:

sudo ufw allow OpenSSH
Enter fullscreen mode Exit fullscreen mode

Then allow web traffic:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Enter fullscreen mode Exit fullscreen mode

Enable it:

sudo ufw enable
Enter fullscreen mode Exit fullscreen mode

Check the rules:

sudo ufw status verbose
Enter fullscreen mode Exit fullscreen mode

You generally don't want random application ports exposed to the internet.

For example, if your application listens internally on port 3000, there’s usually no reason to expose 3000 publicly when Nginx can proxy requests to it.

5. Install Nginx

Now we need something to actually serve the website.

Install Nginx:

sudo apt install nginx -y
Enter fullscreen mode Exit fullscreen mode

Check whether it is running:

sudo systemctl status nginx
Enter fullscreen mode Exit fullscreen mode

You can also enable it at boot:

sudo systemctl enable nginx
Enter fullscreen mode Exit fullscreen mode

Open the VPS IP in a browser.

If you see the Nginx welcome page, congratulations.

Your server is officially doing something useful.

6. Point Your Domain to the VPS

Now go to your DNS provider and create an A record.

For example:

Type: A
Name: @
Value: YOUR_SERVER_IP
TTL: 300
Enter fullscreen mode Exit fullscreen mode

For www:

Type: A
Name: www
Value: YOUR_SERVER_IP
TTL: 300
Enter fullscreen mode Exit fullscreen mode

DNS changes aren't always instant, so give it some time.

You can check the record with:

dig example.com
Enter fullscreen mode Exit fullscreen mode

Or:

nslookup example.com
Enter fullscreen mode Exit fullscreen mode

You want the domain to resolve to the VPS IP.

7. Create an Nginx Server Block

Let's assume the domain is:

example.com
Enter fullscreen mode Exit fullscreen mode

Create a directory for the site:

sudo mkdir -p /var/www/example.com
Enter fullscreen mode Exit fullscreen mode

Give your user access:

sudo chown -R henry:henry /var/www/example.com
Enter fullscreen mode Exit fullscreen mode

Create a simple page:

nano /var/www/example.com/index.html
Enter fullscreen mode Exit fullscreen mode

Add:

<!DOCTYPE html>
<html>
<head>
    <title>My VPS Website</title>
</head>
<body>
    <h1>Hello from my VPS!</h1>
    <p>The server is alive. Nobody panic.</p>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Now create an Nginx configuration:

sudo nano /etc/nginx/sites-available/example.com
Enter fullscreen mode Exit fullscreen mode

Use:

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;

    root /var/www/example.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
Enter fullscreen mode Exit fullscreen mode

Enable it:

sudo ln -s /etc/nginx/sites-available/example.com \
/etc/nginx/sites-enabled/example.com
Enter fullscreen mode Exit fullscreen mode

Test the configuration:

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

If everything looks good:

sudo systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

Now visit your domain.

8. Add HTTPS

Running a website over plain HTTP isn't something I’d recommend.

Install Certbot:

sudo apt install certbot python3-certbot-nginx -y
Enter fullscreen mode Exit fullscreen mode

Then request a certificate:

sudo certbot --nginx -d example.com -d www.example.com
Enter fullscreen mode Exit fullscreen mode

Certbot can configure the Nginx HTTPS settings for you.

After that, check:

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

And:

sudo systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

You should now be able to access:

https://example.com
Enter fullscreen mode Exit fullscreen mode

The browser lock icon isn't decoration. It means the connection is encrypted.

9. If You’re Hosting an Application

Static HTML is easy.

Real applications are where things get interesting.

Suppose your Node.js application listens on:

127.0.0.1:3000
Enter fullscreen mode Exit fullscreen mode

You don't necessarily need to expose port 3000 publicly.

Instead, Nginx can sit in front of it:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;

        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;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now the public traffic goes:

Internet
   |
 HTTPS
   |
 Nginx
   |
 localhost:3000
   |
 Node.js
Enter fullscreen mode Exit fullscreen mode

This is a much cleaner setup than exposing every service directly to the internet.

10. Keep the Application Running

If your application crashes, you probably don't want your website disappearing until you manually restart it.

For Node.js applications, a process manager such as systemd or another appropriate service manager can handle this.

A simple systemd service might look like:

[Unit]
Description=My Website
After=network.target

[Service]
User=henry
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/node /var/www/myapp/server.js
Restart=always
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

Save it as:

/etc/systemd/system/myapp.service
Enter fullscreen mode Exit fullscreen mode

Then:

sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
Enter fullscreen mode Exit fullscreen mode

Check it:

sudo systemctl status myapp
Enter fullscreen mode Exit fullscreen mode

This gives you something much closer to a proper production service instead of keeping a terminal window open and praying nobody closes it.

11. Don't Forget Backups

A VPS is not a backup.

This is worth repeating.

If the server disappears and your only copy of the database was sitting on that server, the backup plan was basically:

“Hopefully nothing happens.”

That isn't a backup strategy.

At minimum, think about:

  • Website files
  • Databases
  • Environment/configuration files
  • SSL configuration
  • Application data
  • Server configuration

For MySQL, for example:

mysqldump -u root -p database_name > database_backup.sql
Enter fullscreen mode Exit fullscreen mode

But don't just create backups.

Test restoring them.

A backup you've never successfully restored is an assumption, not proof.

12. Watch the Server

Once the website is online, the job isn't finished.

I usually keep an eye on:

free -h
Enter fullscreen mode Exit fullscreen mode

for memory,

df -h
Enter fullscreen mode Exit fullscreen mode

for disk usage,

and:

uptime
Enter fullscreen mode Exit fullscreen mode

for basic system load information.

For services:

sudo systemctl status nginx
Enter fullscreen mode Exit fullscreen mode

And for logs:

sudo journalctl -u nginx
Enter fullscreen mode Exit fullscreen mode

You can also use more advanced monitoring stacks when the server grows, such as metrics collection, centralized logging, alerting, and external uptime checks.

That's where VPS management starts becoming real infrastructure work rather than simply “I installed a website.”

13. Choose the Right VPS

You don't always need a huge server.

A small website might work perfectly well with a modest VPS. A busy application, database-heavy platform, or API service may need more CPU, memory, storage performance, or network capacity.

When comparing VPS hosting, I’d pay attention to:

  • Dedicated or guaranteed resources
  • NVMe storage
  • Network capacity
  • Backup options
  • Snapshot support
  • DDoS protection
  • Data-center location
  • IPv4/IPv6 availability
  • Root access
  • Upgrade options
  • Monitoring and support

If you're comparing VPS hosting providers, HelloServer is one option worth checking, especially if you want control over the server environment rather than being locked into a shared hosting setup.

The important part isn't choosing the biggest plan.

It's choosing a setup that gives your website enough headroom without paying for resources you'll never use.

14. A Few Production Checks

Before calling the server “finished,” I'd check a few things.

Test Nginx:

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

Check listening ports:

sudo ss -tulpn
Enter fullscreen mode Exit fullscreen mode

Check firewall rules:

sudo ufw status
Enter fullscreen mode Exit fullscreen mode

Check disk space:

df -h
Enter fullscreen mode Exit fullscreen mode

Check memory:

free -h
Enter fullscreen mode Exit fullscreen mode

Check failed services:

systemctl --failed
Enter fullscreen mode Exit fullscreen mode

And make sure your website actually works over HTTPS.

Not just the homepage.

Test forms, login, uploads, APIs, database connections, redirects, and anything else your application depends on.

Final Thoughts

Setting up a private VPS for a website isn't particularly difficult once you understand what each layer is doing.

The important thing is not memorizing commands.

It's understanding the architecture:

Domain
  ↓
DNS
  ↓
Firewall
  ↓
Nginx
  ↓
Application
  ↓
Database
Enter fullscreen mode Exit fullscreen mode

Then add the things that keep it reliable:

Backups
Monitoring
Updates
Logging
Security
Enter fullscreen mode Exit fullscreen mode

That's the difference between simply getting a website online and actually running your own server properly.

And yes, you'll probably break something while learning.

That's normal.

Just make sure you have a backup before you break it.

Top comments (0)