A Beginner's Guide to Self Hosting With a VPS

👉 TLDR? Skip to the technical setup

👉 Video

Your Own Corner of the Internet

There's a moment - somewhere between your third streaming subscription price hike, your fifth "we've updated our privacy policy" email, and the realization that a company you've never heard of has been selling your browsing history to data brokers - where you start to wonder if maybe you should just... do it yourself?

Not all of it, but maybe some of it - just for the stuff that matters to you.

That's what a VPS is for. And if you've never set one up before, this is the article where I try to convince you that it's not as scary as it sounds, that it's genuinely worth doing, and that it opens up a whole world of things you probably didn't know you could run yourself.


What Even Is a VPS?

A VPS - Virtual Private Server - is a computer that lives in a data center somewhere, running 24/7, that you rent for a few bucks a month. It's not physically yours. But as long as you keep paying for it, you control what runs on it, what it stores, who can access it, and what it does with your data.

Think of it like renting a small apartment in the cloud. You get the keys, you decide what and who goes inside, and nobody else has a copy of those keys unless you hand them out (which you should try to avoid).

Now - ideally, you'd run your own physical hardware like maybe a small machine at home. If you can do that, I'd genuinely recommend it. But let's be real: not everyone has the space or the upfront cash (especially nowadays) to buy and run a machine 24/7 at home. A VPS gets you 90% of the benefit at a fraction of the cost and complexity. You're still trusting a hosting provider with the physical hardware, but you control everything that runs on it. For most people, right now, that's the more practical path - and there's nothing wrong with starting there.

The cheapest ones start at around $4-5/month. That's less than a single streaming service. For that, you get a Linux server with its own IP address, sitting in a data center with a fast internet connection, available at all times. Providers like Contabo, Hetzner, Vultr, DigitalOcean, or Linode all offer entry-level plans in that range.

You pick a location (Frankfurt, New York, Singapore, Krakozhia - whatever), you pick a size (start small, you can always upgrade), and within a few minutes you have a server. It comes with an IP address and a root password, and from that point on it's yours to shape.


Why Would You Want One?

Quite simple:

  • You stop being the product. Every "free" service you use - Gmail, Google Drive, Dropbox, the note-taking app that mysteriously knows you were shopping for running shoes - pays for itself by monetizing your data. When you start self-hosting, the economics flip - you pay a few dollars a month for compute and storage, and in return nobody is parsing your emails to sell you ads (I'm looking at you Microsoft Outlook 🫵). Your files sit on a server you control, in a jurisdiction you chose, accessible only to you and people you've, hopefully, explicitly allowed in.

  • You own your stuff. The photo backup service that just announced they're shutting down; the note-taking app that got acquired and is pivoting to enterprise; the cloud storage provider that decided your free tier is now 2GB instead of 15GB.
    When you self-host, migrations like these become someone else's problem. Your data lives where you put it, and it stays there until you decide otherwise.

  • You learn things. Setting up a server is not as easy as downloading an app on your phone. But the gap between "I have no idea what I'm doing" and "I have a working server running three services" is genuinely smaller than most people think. Especially nowadays - you have AI you can ask an unlimited amount of questions to and it will give you decent answers. That is a huge advantage as to how I learned all this stuff. And the things you learn along the way - how networking works, how to serve and app, what a firewall does and why it matters - these aren't abstract concepts. They're practical knowledge that makes you better at understanding the digital world you already live in every day.

  • It's surprisingly cheap. A basic VPS and maybe a domain name and a wildcard SSL certificate (which you can get for free from Let's Encrypt) gets you infrastructure that would cost a small business hundreds of dollars a month if they bought it as managed services. You're trading money for time and learning - which, depending on where you are in life, might be an excellent deal.

  • Privacy isn't paranoia. I keep hearing this framing where anyone who cares about their data is treated like they're wearing a tinfoil hat or even "well what do you have to hide that's so important nobody sees?". 🤦 It's not about hiding and it's not a conspiracy. You lock your front door, don't you? And I hope you don't hand your house keys to strangers. It's the same thing when you don't want random entities on the internet to read your mail. Wanting the digital equivalent of that is just... normal. The fact that we've been conditioned to think otherwise is insane.


What Can You Actually Run On It?

This is where it gets fun. Here's a non-exhaustive list of things people self-host on a $5-10/month VPS, and every single one of these has a free, open-source option that you can deploy in minutes using Docker:

  • Your own VPN. Run WireGuard and route your traffic through your server instead of trusting a commercial VPN provider. Your ISP sees an encrypted tunnel and nothing else. I wrote a whole article about this and built nullGuard, which is a VPN manager app to make managing it less painful.

  • Cloud storage. Nextcloud gives you your own Dropbox/Google Drive - file sync, calendar, contacts, document editing, the works. It runs on basically anything and the mobile apps are solid.

  • Password manager. Vaultwarden is a lightweight, self-hosted implementation of the Bitwarden API. All the convenience of a cloud password manager, except the vault lives on your server and nobody else's. Browser extensions, mobile apps, auto-fill - it all works.

  • Media server. Plex or Jellyfin let you stream your own media library to any device, anywhere. Jellyfin is fully open-source with no account required. Your own Netflix, basically - minus the monthly price increases and the enshittification of the content library.

  • Ad blocking for your entire network. Pi-hole or AdGuard Home block ads and trackers at the DNS level. Point your devices at your VPS as their DNS server and ads disappear across everything - browsers, apps, smart TVs, all of it. No browser extension needed.

  • Git hosting. Gitea or Forgejo give you a lightweight GitHub-like experience on your own server. Great for private projects or if you just don't want Microsoft knowing about every side project you start and abandon after three days.

  • Bookmarks and read-later. Linkding or Wallabag replace Pocket or Instapaper. Save articles, tag them, read them later - from your own server.

  • RSS reader. Miniflux or FreshRSS bring back RSS - the technology that lets you follow websites without an algorithm deciding what you see. Remember chronological feeds? Yeah. You can have those again.

  • Dashboard. Once you're running a few services, you'll want something to keep track of them. WebUI Manager (which I also built) gives you a clean overview of everything running across your servers.

  • Monitoring. Uptime Kuma monitors your services and alerts you when something goes down. Clean UI, easy setup, supports notifications through email, Slack, Discord, Telegram - basically anything.

This is barely scratching the surface. There are self-hosted alternatives for almost everything: email, chat, wikis, project management, home automation, analytics, databases, CI/CD pipelines - the list is genuinely endless. The awesome-selfhosted repository on GitHub catalogues hundreds of them.
Subscribe to my YouTube channel, follow on X and enroll in the mailing list on my website to see future posts for many of these!


The first-Time Setup Isn't That Bad

Here's where people usually bail. "I don't know Linux."; "I've never used a terminal."; "What if I break something?"

You're renting a virtual machine for five dollars. If you break it, you click "reinstall" in your provider's dashboard and start over. The stakes are genuinely low. Nobody's production system is going down because you mistyped a command on your personal VPS. It's a playground with training wheels that you can torch and rebuild in a few minutes.

What follows is the full walkthrough. Sign up with a provider, spin up an Ubuntu server (it's the most beginner-friendly Linux), and let's go.


Step 1 - First Login & System Update

Once your VPS is provisioned, you'll get an IP address and a root password. On Mac or Linux, open a terminal. On Windows, use PuTTY or the built-in Windows Terminal. Then:

ssh root@your-server-ip

You're in. First thing you do - update everything. This is the Linux equivalent of "check for updates," and you should always run it first:

apt update && apt upgrade -y && apt autoremove -y

Give the server a name while you're at it:

hostnamectl set-hostname your-server-name

Step 2 - Create a Sudo Admin User

Working as root (the all-powerful admin account) all the time is like driving without a seatbelt - technically possible, but not recommended for normies. One wrong command and you can nuke things you really didn't mean to. Create a regular user and give it sudo privileges instead:

adduser adminuser
usermod -aG sudo adminuser

From here on you'll use this account for everything. Root stays in the drawer for emergencies.


Step 3 - SSH Key Authentication

Passwords can be guessed. Keys can't - at least not in any meaningful timeframe. Instead of logging in with a password, you set up a cryptographic key pair. Your computer has the private key, the server has the public key. When your computer calls the server with the private key, they try to do a handshake 🫱🫲 and if both of them know all the right moves, as in the keys match, you're in. No password to steal.

On your local machine, generate a key pair if you don't already have one:

ssh-keygen -t ed25519 -C "[email protected]"

Copy your public key to the server:

ssh-copy-id adminuser@your-server-ip

Or if you prefer doing it manually, on the server:

mkdir -p /home/adminuser/.ssh
nano /home/adminuser/.ssh/authorized_keys
# Paste your public key, save and exit
chmod 700 /home/adminuser/.ssh
chmod 600 /home/adminuser/.ssh/authorized_keys
chown -R adminuser:adminuser /home/adminuser/.ssh

Before you do anything else - open a new terminal window and confirm you can log in as adminuser with your key. Don't lock yourself out of your own server. Trust me on this one.


Step 4 - Harden SSH

This is where you slam the door on the most common attacks. Open the SSH config:

nano /etc/ssh/sshd_config

Find and set (or add) these lines:

Port 2222                        # Change from default 22
PermitRootLogin no               # Disable root login
PasswordAuthentication no        # Keys only, no passwords
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
X11Forwarding no
AllowTcpForwarding no
MaxAuthTries 3
LoginGraceTime 20
AllowUsers adminuser             # Whitelist only your user(s)

What you just did: changed the SSH port so automated scanners mostly miss you, disabled root login entirely, turned off password authentication (keys only), and limited login attempts. Every server on the internet gets hammered by bots trying root/password123 within minutes of going online. This step makes all of that pointless.

Restart SSH - but keep your current session open and test in a new terminal first:

systemctl restart sshd

Test: ssh -p 2222 adminuser@your-server-ip

If it works, you're good. If it doesn't, you still have your original session to fix things. This is why you test before closing anything.


Step 5 - Firewall Setup with UFW

UFW stands for Uncomplicated Firewall - and it actually lives up to the name. The idea is simple: deny everything by default, then explicitly allow only the ports you need.

apt install ufw -y

Set default policies - block everything incoming, allow everything outgoing:

ufw default deny incoming
ufw default allow outgoing

Now poke holes for the stuff you actually want to reach:

ufw allow 2222/tcp        # SSH (your custom port)
ufw allow 80/tcp          # HTTP if you need it
ufw allow 443/tcp         # HTTPS if you need it

Enable it:

ufw enable
ufw status verbose

Make absolutely sure your SSH port is allowed before you enable UFW. If you skip this, you will lock yourself out. I've seen it happen. It's not fun.


Step 6 - Fail2Ban

Even with key-only SSH on a non-standard port, bots will still poke at your server. Fail2Ban watches log files and automatically bans IP addresses that fail too many login attempts. Think of it as a bouncer for your server.

apt install fail2ban -y

Create a local config - never edit the original:

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
nano /etc/fail2ban/jail.local

Find the [sshd] section and set it up:

[sshd]
enabled = true
port    = 2222
filter  = sshd
logpath = /var/log/auth.log
maxretry = 4
bantime = 1h
findtime = 10m

This means: if someone fails to log in 4 times within 10 minutes, they get banned for an hour. More than enough to make brute-forcing completely impractical.

systemctl enable fail2ban
systemctl start fail2ban
fail2ban-client status sshd

Step 7 - Install Webmin (Optional)

If the command line feels like a lot and you'd prefer a web-based control panel for managing your server, Webmin is a solid option. It gives you a browser UI for system administration - file management, service monitoring, user management, all that stuff.

apt install curl -y
curl -o webmin-setup-repo.sh https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh
sudo sh webmin-setup-repo.sh
apt install --install-recommends webmin -y

Verify it's running:

systemctl status webmin

Access it at https://your-server-ip:10000 - log in with your adminuser credentials. Your browser will complain about the self-signed certificate; that's normal, just accept it.

If you're using Webmin, remember to open the port in UFW:

ufw allow 10000/tcp

Step 8 - Install Docker

Docker is what makes the rest of this article possible. It lets you run applications in isolated containers - self-contained packages that include everything the app needs. Instead of installing software directly on your server and dealing with dependency conflicts and cleanup, you run a container and it just works. When you're done with something, you remove the container and your server is clean.

Remove any old versions that might be lingering:

apt remove docker docker-engine docker.io containerd runc 2>/dev/null

Install dependencies:

apt install ca-certificates curl gnupg lsb-release -y

Add Docker's official repository:

mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | \
  tee /etc/apt/sources.list.d/docker.list > /dev/null

Install Docker:

apt update
apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

Verify it's all there:

docker --version
docker compose version
systemctl status docker

Step 9 - Create a Docker User

You don't want to run all your containers as root either. Create a dedicated user for Docker deployments:

adduser dockeruser
usermod -aG docker dockeruser

This lets dockeruser run Docker commands without sudo. Test it:

su - dockeruser
docker run hello-world
exit

If you see the hello-world output, you're set.


Step 10 - Set Up Your Volumes Directory

Docker containers need somewhere to store persistent data - configs, databases, uploaded files. Create a clean structure for it:

mkdir -p /opt/volumes
chown dockeruser:dockeruser /opt/volumes
chmod 755 /opt/volumes

If you want your adminuser to also be able to manage files there:

usermod -aG dockeruser adminuser
chown -R dockeruser:docker /opt/volumes
chmod -R 775 /opt/volumes

A typical setup ends up looking something like this:

/opt/volumes/
├── nginx/
│   ├── docker-compose.yml
│   ├── config/
│   └── data/
├── postgres/
│   ├── docker-compose.yml
│   └── data/
└── myapp/
    ├── docker-compose.yml
    └── data/

Each service gets its own directory with its own compose file and data. Clean, organized, easy to back up.


Step 11 - Secure Shared Memory

This is a quick one-liner hardening step. Shared memory (/run/shm) can be abused by certain exploits, so we mount it with restrictions:

nano /etc/fstab

Add this line at the bottom:

tmpfs /run/shm tmpfs defaults,noexec,nosuid 0 0

Step 12 - Automatic Security Updates

You don't want to manually log in every week to install security patches. Set up unattended upgrades:

apt install unattended-upgrades -y
dpkg-reconfigure --priority=low unattended-upgrades

Select Yes when prompted. Your server will now automatically install security updates without you lifting a finger.


Step 13 - Final Checks

Run through this checklist to make sure everything landed correctly:

# Firewall is active
ufw status verbose

# SSH is on the right port
ss -tlnp | grep sshd

# Docker is running
systemctl status docker

# Volumes directory ownership
ls -la /opt/

# dockeruser is in docker group
id dockeruser

# Root login is disabled
grep PermitRootLogin /etc/ssh/sshd_config

# Fail2Ban is active
fail2ban-client status

If all of that checks out, you're done. Here's the summary:

What Detail
SSH port 2222
Root login Disabled
SSH auth Key-based only
Admin user adminuser (sudo)
Docker user dockeruser (docker group)
Volumes path /opt/volumes
Firewall UFW - 2222, 80, 443
Brute force protection Fail2Ban on SSH

Your server is updated, hardened, firewalled, has Docker ready to go, and is set up with proper user separation. The whole thing takes maybe thirty to forty-five minutes the first time, and most of that is reading and understanding what you're doing rather than the actual typing.


The Honest Trade-Offs

I'm not going to pretend this is all upside. There are real trade-offs and you should know about them before you commit.

  • You are the sysadmin now. If something breaks at 2 AM, there's no support ticket to file. You fix it, or it stays broken until you do. For most personal services this is fine - if your Jellyfin server is down for a few hours, nobody dies. But it's worth understanding that you're accepting responsibility for the thing.

  • Backups are your problem. Cloud services handle backups invisibly. When you self-host, you need to think about this yourself. The good news is that it's not complicated - a scheduled script that copies your important data to a second location (another VPS, an object storage bucket, even a local drive at home) is usually enough. But you have to actually set it up, because the data fairy isn't going to do it for you.

  • Some things are harder to self-host than others. Email, for example, is notoriously painful to run yourself - not because the software is hard, but because getting other mail servers to accept your messages without marking them as spam is an ongoing battle that even experienced sysadmins find tedious. For email specifically, I'll post a whole deep dive thread down the line, so make sure to follow so you can see these posts.

  • You're trading convenience for control. Commercial services are polished. They have apps, they sync seamlessly, they handle edge cases. Self-hosted alternatives are often 90% as good, which is plenty for most people - but that remaining 10% can occasionally be annoying. A Nextcloud sync might hiccup where Dropbox wouldn't. A Vaultwarden setup might need a manual restart after an update. It's small stuff, but it's there.

  • Learning curve exists. The terminal is not intuitive if you've never used one. Linux file permissions are confusing the first time and Docker concepts may take a minute to click. But here's the thing - every single one of these is a one-time learning cost. Once you understand how Docker Compose works, deploying the next ten services is copy-paste with minor changes. The curve is front-loaded and you get used to it fast.


Who Is This Actually For?

More people than you'd think. If you're:

  • privacy-conscious and tired of being the product - this is for you.
  • curious about technology and want to understand how the internet actually works under the hood - this is a fantastic way to learn.
  • a hobbyist or tinkerer who likes building things and having projects - self-hosting is an endless rabbit hole of interesting stuff to set up and play with.
  • a small business owner who's currently paying for fifteen different SaaS subscriptions and wondering if there's a better way - there might be, and it might cost you $10/month instead of $200.
  • a developer who wants a staging environment, a private Git server, or a place to deploy side projects - a VPS is the obvious answer.
  • none of the above but the idea of having your own little corner of the internet where you call the shots sounds appealing - that's reason enough.

Getting Started Without Drowning

If I've managed to convince you and you want to try this, here's my honest advice for not getting overwhelmed:

Start with one thing. Don't try to replace your entire digital life in a weekend. Pick the one service that bothers you most - maybe it's your VPN, which I'd recommend with nullGuard, maybe it's your cloud storage, maybe it's ad blocking - and set up just that. Get it working and see how cool it feels to do it yourself. Then think about what's next.

Use Docker for everything. Don't install software directly on the server. Docker containers are isolated, easy to update, easy to remove, and easy to back up. Almost everything you'd want to run has an official Docker image.

Don't skip security. I know the firewall and SSH hardening steps feel like busywork when you just want to get to the fun stuff. Do them anyway. Your server will be scanned by bots within minutes of going online. The security setup takes ten minutes and saves you from a world of pain.

Join a community. r/selfhosted on Reddit is genuinely one of the most helpful communities on the platform. People share their setups, help troubleshoot issues, and recommend alternatives. The selfhosted.show podcast is also worth a listen if you want ideas.

Accept that you'll mess up. You will mistype a command. You will lock yourself out of SSH at least once. You will forget to open a port and spend twenty minutes wondering why something isn't working. This is normal. This is the learning process. And because it's a $5 VPS and not a production server, the consequence of messing up is "spend five minutes fixing it" and not "get fired."

Ask AI. As long as you don't give it your credentials, IP addresses and keys you can ask it about anything related and it would be able to help. Just don't let it do things for you without your cognitive involvement. 🙂 Don't become the Borg. 🤖


The Bigger Picture

We're living through a period where the services we depend on are getting worse on purpose. Streaming services raise prices while removing content. Social platforms optimize for engagement (read: outrage) over utility. Cloud storage providers shrink free tiers. Privacy policies get longer and more permissive in what they allow companies to do with your data. And the trend is accelerating, not slowing down.

Self-hosting isn't about rejecting all of that and going to live in a cabin. It's about selectively taking back control over the things that matter to you. Maybe that's your files. Maybe that's your passwords. Maybe that's your DNS. Maybe it's just the principle of the thing - the idea that some part of your digital life should belong to you and not to a company whose incentives are fundamentally misaligned with yours.

A VPS is the foundation for all of that. Five dollars a month, a Saturday afternoon, and a willingness to learn - and you've got your own little corner of the internet that nobody can enshittify but you.

Imho there's something deeply satisfying about typing an address into your browser and landing on something that's running on your server, configured your way, serving your data, answerable to nobody but you.

That feeling alone is worth the five bucks.


Video


Live long and prosper. 🖖👽

Share this article

Copied!