Over the past few years, I’ve gradually moved many of my tools and services away from SaaS subscriptions and into self-hosted environments. Whether it’s knowledge bases, helpdesk software, automation tools, or even app prototypes — I now run most of them on my own VPS. This post walks you through how I set up a clean, secure, and scalable VPS on Hetzner Cloud , ready to host Dockerized applications and manage them easily via Portainer.
📦 Why Hetzner?
Hetzner is one of the best-kept secrets for developers and entrepreneurs who need affordable, powerful cloud servers. Their pricing is excellent, the performance is solid, and their dashboard is clean and simple. I use it to spin up lightweight production environments, staging servers, and internal tools.
🛠️ What We’ll Set Up
- A clean Ubuntu server on Hetzner
- Secure server configuration: SSH, firewall, non-root user
- Docker + Docker Compose installation
- Portainer for easy container management via GUI
- Nginx Proxy Manager for HTTPS and domain-based routing
- Future-ready setup for multiple apps
1. 🔧 Provisioning a New VPS on Hetzner
- Create an Account: console.hetzner.cloud
- Create a New Project and add an SSH key.
Create a Server:
- Image: Ubuntu 24.04
- Type: CX22 or higher (CX31 for heavier apps)
- Location: closest to your users
Choose SSH key login only. Avoid password-based logins.
2. 🔐 Initial Security Setup
SSH into your server as root:
ssh root@your.server.ip
Now secure the basics:
🧑💻 Create a non-root user
adduser tariq
usermod -aG sudo tariq'
🔐 Harden SSH
Edit the config:
sudo nano /etc/ssh/sshd_config
Make sure the following are set:
PermitRootLogin no
PasswordAuthentication no
Then reload SSH:
sudo systemctl reload sshd
🔥 Set up basic firewall
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
3. 🐳 Install Docker + Docker Compose
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo 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" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
Enable Docker:
sudo systemctl enable docker
sudo usermod -aG docker tariq
Logout and log back in to apply group changes.
4. 📦 Install Portainer (Optional but Recommended)
docker volume create portainer_data
docker run -d \
-p 9000:9000 -p 9443:9443 \
--name=portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
Then visit: https://your.server.ip:9443 to finish setup.
5. 🌐 Set Up Domain + HTTPS with Nginx Proxy Manager
docker volume create npm_data
docker volume create npm_letsencrypt
docker run -d \
--name npm \
-p 80:80 -p 81:81 -p 443:443 \
-v npm_data:/data \
-v npm_letsencrypt:/etc/letsencrypt \
--restart always \
jc21/nginx-proxy-manager:latest
Access NPM admin at http://your.server.ip:81. Default login:
- Email: admin@example.com
- Password: changeme
You can now add your domains, configure HTTPS, and reverse proxy traffic to your apps running in Docker.
🧱 Folder Structure and GitOps (Optional)
I recommend organizing your apps like this:
/opt/apps/
├── app1/
│ └── docker-compose.yml
├── app2/
│ └── docker-compose.yml
Version-control this folder using Git (private repo), and maintain infrastructure as code.
🔄 Next Steps
Once the server is up and secure with Docker, Portainer, and NPM, you’re ready to deploy your stack:
- 🧾 Zammad for helpdesk
- 🧠 Outline for internal docs
- 🤖 n8n for automation
- 🧰 Custom Rails or Node apps
💡 Final Thoughts
Running your own infrastructure isn’t as intimidating as it seems — and the flexibility, cost savings, and control are totally worth it. Whether you’re a startup founder, indie hacker, or just like to tinker, a Hetzner VPS with Docker is a powerful foundation for anything you want to self-host.
Let me know what you’re self-hosting — and feel free to reach out if you’re curious about how I run mine behind the scenes.