VPS Setup with Dokploy — Complete Production Guide
- devops
- dokploy
- hetzner
- vps
- self-hosting
A step-by-step walkthrough for setting up a production-ready VPS with automated deployments, HTTPS, and preview environments using Dokploy.
Prerequisites
- A VPS running Ubuntu 24.04 LTS (minimum: 2 vCPUs, 8 GB RAM) — e.g., from Hetzner
- A domain managed via Cloudflare
- A GitLab (or GitHub) account with your app repository
- SSH access to the VPS
Step 1 — Initial VPS Hardening
Connect to your VPS as root:
ssh root@<your-vps-ip>
1a. Set up SSH keys
On your local machine, generate an SSH key if you don't have one:
ssh-keygen -t ed25519 -C "[email protected]"
# Copy your public key to the VPS
ssh-copy-id root@<your-vps-ip>
1b. Create a non-root user
adduser username
usermod -aG sudo username
# Copy SSH keys from root to the new user
rsync --archive --chown=username:username ~/.ssh /home/username
1c. Disable root and password login
nano /etc/ssh/sshd_config
Set these values:
PermitRootLogin no
PasswordAuthentication no
systemctl restart ssh
From now on, SSH via: ssh username@<your-vps-ip>
1d. Add the new user to the Docker group
Run this after Dokploy installs Docker (Step 2), or now — the group will be applied once Docker is present:
usermod -aG docker username
Step 1e — Install fail2ban
fail2ban monitors log files and automatically bans IPs that show signs of brute-force attacks. It continues to protect public-facing ports even after SSH is locked down.
apt install fail2ban -y
systemctl enable --now fail2ban
Create a local jail configuration for SSH:
cat > /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
maxretry = 5
bantime = 1h
findtime = 10m
EOF
Apply and verify:
systemctl restart fail2ban
fail2ban-client status sshd
Step 2 — Install Dokploy
Run the official one-line installer (as your non-root sudo user):
curl -sSL https://dokploy.com/install.sh | sudo sh
The installer will install Docker and Docker Swarm, pull and start all Dokploy containers, and take 2–5 minutes. Once done, Dokploy is available at http://<your-vps-ip>:3000.
Create your admin account: Open the Dokploy URL, enter an email and a temporary password — you will change it once HTTPS is configured.
Use a throwaway password until HTTPS is enabled, to avoid sending credentials in plaintext over HTTP.
Step 3 — Configure Cloudflare DNS and HTTPS
3a. Add DNS records in Cloudflare
In your Cloudflare dashboard, go to DNS → Records and add:
| Type | Name | Value | Proxy |
|---|---|---|---|
| A | @ (apex domain) |
<your-vps-ip> |
DNS only |
| A | dokploy |
<your-vps-ip> |
DNS only |
Set proxy status to DNS only (grey cloud) — Dokploy manages its own HTTPS via Let's Encrypt.
Verify propagation:
nslookup yourdomain.com
3b. Configure domain and HTTPS in Dokploy
- In Dokploy, go to Settings → Web Server
- Enter your Dokploy subdomain (e.g.,
dokploy.yourdomain.com) - Enter your Let's Encrypt email address
- Toggle HTTPS on and click Save
Dokploy will automatically request a certificate from Let's Encrypt (~30 seconds). Access Dokploy at https://dokploy.yourdomain.com and change your password to a strong one.
Step 4 — Connect GitLab (or GitHub)
- Go to Settings → Git in Dokploy
- Select your provider and click Create App
- Follow the OAuth flow to authorize Dokploy
- Select which repositories Dokploy should have access to
Step 5 — Create a Project
Projects are logical groups for related services (app + database).
- Click New Project
- Name it (e.g.,
myapp)
Step 6 — Deploy a Database
Inside your project:
- Click Add Service → Database
- Choose your database type (PostgreSQL, MySQL, MongoDB, or Redis)
- Configure the name, username, password, and Docker image version
- Click Deploy
The Internal URL shown after deployment is what your app will use as DATABASE_URL.
Step 7 — Deploy Your Application
Inside your project:
- Click Add Service → Application
- Name it (e.g.,
web)
Connect the repository: Under the Git tab, select your GitLab repository and branch. Auto-redeploy on push is enabled by default.
Choose a build method:
- Nixpacks — recommended; auto-detects your project type, no Dockerfile needed
- Dockerfile — if you have a custom Dockerfile
- Railpack — alternative to Nixpacks
Set environment variables: Go to the Environment tab and add your app's required variables:
DATABASE_URL=<internal URL from Step 6>
SECRET_KEY=<your secret>
API_KEY=<your api key>
With Nixpacks, env vars are available at both build time and runtime automatically.
Step 8 — Configure a Domain for the App
- Go to the Domains tab of your application
- Add your app's subdomain (e.g.,
app.yourdomain.com) - Enable HTTPS with Let's Encrypt
- In Cloudflare DNS, add an A record pointing
appto your VPS IP (DNS only) - Use the Validate DNS button in Dokploy to confirm propagation
- Click Deploy — your app is now live
Step 9 — Enable Preview Deployments
Preview deployments automatically build and host a live URL for every pull request opened on your repository.
9a. Create a wildcard DNS record
In Cloudflare DNS:
| Type | Name | Value | Proxy |
|---|---|---|---|
| A | * |
<your-vps-ip> |
DNS only |
This routes all subdomains (e.g., pr-42.yourdomain.com) to your VPS.
9b. Configure in Dokploy
- Go to your application → Preview Deployments tab
- Click Configure
- Set Wildcard Domain:
*.yourdomain.com - Enable HTTPS
- Paste your environment variables (same as production, or override as needed)
- Set Max concurrent preview deployments (e.g.,
5) - Toggle Enable and save
When a PR is opened, Dokploy automatically builds and deploys that branch, posts a comment on the PR with the preview URL, and destroys the preview when the PR is merged or closed.
Architecture Overview
yourdomain.com → Dokploy dashboard
app.yourdomain.com → Production app
*.yourdomain.com → Preview deployments (PR-based)
VPS
├── Dokploy (management layer)
├── Traefik (reverse proxy + HTTPS)
├── Your App container(s)
├── Database container(s)
└── Preview containers (ephemeral, per PR)
Useful Tips
Build performance: Dokploy builds on the same machine by default. For high-traffic production setups, use an external CI/CD pipeline (GitLab CI / GitHub Actions) to build and push Docker images, then configure Dokploy to pull pre-built images.
Monitoring: Dokploy includes built-in server and application monitoring — check the Monitoring tab for CPU, RAM, and container metrics.
Docker Compose migration: If you have an existing Docker Compose setup, you can import it directly into Dokploy — no rewrite needed.
Multiple apps: Repeat Steps 5–8 for each application. Each project can have multiple apps and databases sharing the same VPS.
Quick Reference
| Step | Action |
|---|---|
| 1 | SSH keys, create non-root user, disable root/password login, add to docker group |
| 1e | Install fail2ban, configure SSH jail |
| 2 | Install Dokploy, create admin account |
| 3 | Add Cloudflare DNS records, enable HTTPS in Dokploy, change password |
| 4 | Connect GitLab/GitHub |
| 5 | Create a project |
| 6 | Add and deploy database |
| 7 | Add app, connect repo, set env vars, deploy |
| 8 | Configure subdomain + HTTPS for the app |
| 9 | Set wildcard DNS + enable preview deployments |