~/blog/own-vercel-vps-coolify-dokploy.md
Your own Vercel on a VPS: deployments with Coolify and Dokploy
How to run your own deployment platform on a VPS with Coolify or Dokploy: git push to auto-deploy, Let's Encrypt SSL, databases and previews, plus an honest comparison with Vercel and its real limits.
- author
- Alejandro Peñaloza
- Published
- Reading
- 6 min
- Español
- Leer en español →

In this article
Vercel, Netlify and Railway made deploying as simple as running git push. The problem shows up with the bill: once you have several projects, databases, workers and growing traffic, per-project and usage-based pricing adds up fast.
The alternative that has convinced me the most is running my own deployment platform on a VPS, with the same "push and done" experience. Today there are two open-source tools that handle this really well: Coolify and Dokploy.
What exactly they solve
Both are a web dashboard you install on your server that takes care of:
- Building and deploying from a Git repository on every push (using a Dockerfile, Docker Compose or automatic stack detection).
- Reverse proxy and automatic SSL with Let's Encrypt, without touching Nginx.
- Domains and subdomains per application.
- Environment variables and secrets per environment.
- One-click databases (PostgreSQL, MySQL, Redis, MongoDB) with scheduled backups to S3.
- Logs, restarts and rollbacks from the browser.
- Notifications when a deployment fails.
In other words: the part of Vercel you use every day, running on a server you pay a flat price for.
Coolify vs. Dokploy
| Coolify | Dokploy | |
|---|---|---|
| License | Open source | Open source |
| Foundation | Docker, Traefik or Caddy proxy | Docker (Swarm), Traefik proxy |
| Builds | Nixpacks, Dockerfile, Compose, static | Nixpacks, Buildpacks, Dockerfile, Compose |
| Databases | Yes, with S3 backups | Yes, with S3 backups |
| Pull request previews | Yes | Yes |
| Multiple servers | Yes, manages remote servers over SSH | Yes, with Docker Swarm nodes |
| Service templates | Very large catalog | Smaller catalog |
| Overall feel | More complete, more options | Lighter and more straightforward |
Both work very well. My recommendation: Coolify if you want the broadest catalog of one-click services and lots of options; Dokploy if you prefer something simpler with a lower footprint. Both are moving fast, so check their current versions and features before choosing.
Server requirements
- A clean VPS running Ubuntu or Debian. Don't install this on a server that already has Nginx or Apache using ports 80 and 443, because the platform's proxy needs those ports.
- At least 2 vCPUs, 4 GB of RAM and 40 GB of disk to work comfortably. It runs with less, but Next.js builds use quite a bit of memory.
- A domain with access to its DNS.
Before installing, cover the security basics: a non-privileged user, SSH key-only login and a firewall allowing ports 22, 80 and 443 (I go into detail in my post From localhost to production without tears).
Installation
Both are installed with an official script. As always when you run a remote script with elevated privileges, review it first.
Coolify:
curl -fsSL https://cdn.coollabs.io/coolify/install.sh -o install-coolify.sh
less install-coolify.sh # review it
sudo bash install-coolify.shThe dashboard will be available at http://IP_DEL_SERVIDOR:8000.
Dokploy:
curl -sSL https://dokploy.com/install.sh -o install-dokploy.sh
less install-dokploy.sh
sudo sh install-dokploy.shThe dashboard will be available at http://IP_DEL_SERVIDOR:3000.
First thing after installing: create the admin account right away (whoever signs in first gets it), assign a domain to the dashboard so you can reach it over HTTPS, and then close the dashboard port in the firewall.
DNS: one wildcard and you're done
Instead of creating a record for every application, point a wildcard at the server:
| Type | Name | Value |
|---|---|---|
| A | deploy.midominio.cl |
VPS IP |
| A | *.apps.midominio.cl |
VPS IP |
With that, any new application can use nombre.apps.midominio.cl and the platform issues its certificate on its own. For each project's "real" domains (like miproducto.cl), add an A record pointing to the same server.
If you use Cloudflare with the proxy enabled (orange cloud), set SSL to Full (strict) mode. If certificate issuance fails, temporarily disable the proxy so Let's Encrypt can validate the domain.
Deploying an application step by step
- Connect GitHub. Both platforms let you create a GitHub App from the dashboard: that's how they access private repositories and receive a webhook on every push.
- Create the application by choosing the repository and branch (for example,
mainfor production anddevelopfor staging). - Choose how to build: if the repo has a
Dockerfile, use it; if not, Nixpacks detects Node, PHP, Python or Go and builds it on its own. - Set the port the application listens on, and the domain.
- Load the environment variables.
- Deploy and follow the build log live.
A Dockerfile that works well for Next.js
Nixpacks does the job, but with your own Dockerfile you control the image size and build time. With output: "standalone" in next.config.js:
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM node:22-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production PORT=3000 HOSTNAME=0.0.0.0
RUN addgroup -S app && adduser -S app -G app
COPY --from=build /app/.next/standalone ./
COPY --from=build /app/.next/static ./.next/static
COPY --from=build /app/public ./public
USER app
EXPOSE 3000
CMD ["node", "server.js"]And one for Laravel
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --prefer-dist --no-interaction
FROM php:8.3-fpm-alpine
RUN apk add --no-cache nginx supervisor libpq-dev \
&& docker-php-ext-install pdo_pgsql opcache
WORKDIR /var/www
COPY --from=vendor /app/vendor ./vendor
COPY . .
RUN php artisan optimize:clear \
&& chown -R www-data:www-data storage bootstrap/cache
COPY docker/nginx.conf /etc/nginx/http.d/default.conf
COPY docker/supervisord.conf /etc/supervisord.conf
EXPOSE 80
CMD ["supervisord", "-c", "/etc/supervisord.conf"]For Laravel, add a post-deployment command in the platform with php artisan migrate --force && php artisan optimize, and create a separate service for the queue worker (php artisan queue:work) and another one for the scheduler.
Pull request previews
One of Vercel's most useful features is here too: when you open a PR, the platform deploys that branch to its own subdomain (for example, pr-42.apps.midominio.cl) and removes it when the PR is closed. Perfect for letting a client or your team review changes before merging. Keep an eye on RAM, though: every preview is one more running container.
Databases and backups
Spinning up PostgreSQL takes one click, but don't expose it to the internet: let your applications connect over Docker's internal network using the service name. If you need to connect from your own machine, use an SSH tunnel:
ssh -L 5433:localhost:5432 deploy@mi-servidorSet up scheduled backups to S3 right away (or to a compatible service such as Cloudflare R2 or Backblaze B2) and test a restore. A VPS is a single disk in a single place; without off-site backups, a disk failure or an accidental deletion is final.
What you give up compared to Vercel
It's worth being honest about the limits:
- There's no global edge network. Your application lives in one datacenter. For users in Chile / Latin America, a VPS in South America or on the US East Coast works well; for a global audience, put Cloudflare in front to cache static assets.
- You are the ops team. OS, platform and Docker updates are on you.
- One server is a single point of failure. If it goes down, everything goes down. For critical projects, consider a second server or keep those projects on a managed platform.
- Builds compete with your applications for CPU and RAM. If a heavy build slows down production, build the images in GitHub Actions, push them to a registry and let the platform just pull them.
When does it make sense?
- It makes sense: several projects of your own or for clients, APIs, workers and databases, a predictable budget, and a desire to learn what happens under the hood.
- It doesn't: a single static frontend that fits in a free tier, a team where nobody wants to own the server, or high-availability requirements that a single VPS can't meet.
Conclusion
Coolify and Dokploy give a VPS the experience that used to belong only to managed platforms: push, build, SSL and a domain without writing a single line of Nginx config. In exchange, you take on running the server. For someone juggling several projects who wants fixed costs, it's a trade-off well worth making, as long as you don't forget the boring but vital stuff: updates, firewall and off-server backups.
Comments
No comments yet. Want to leave the first one?
Leave a comment
$ ls ~/blog | grep related
Keep reading

War log: debugging CORS, refactoring my own code and integrating Webpay without losing the afternoon
Real problems and how I solved them: a CORS error that only failed in production, a memory leak on the server, my own year-old code refactored without shame, and a practical guide to integrating Webpay Plus, Mercado Pago and Flow.

Developer productivity: VS Code, advanced Git, agile project management and automation scripts
My daily workflow as a developer: the VS Code extensions and settings that actually help, Git beyond commit and push (rebase, cherry-pick and bisect), how to manage small projects without bureaucracy, and the scripts that automate the repetitive work.

From localhost to production without tears: VPS, DNS, hosting and Docker for developers
A practical guide to taking a project to production: how to secure a VPS from scratch, set up DNS and Cloudflare, choose between shared hosting, a VPS or the cloud, and spin up your local database with Docker Compose in seconds.