Build Vercel

KINDAreplaces $20/mosaves $240/yrback to the verdict

0%0 of 20 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

Coolify on one server, deploying your application on every push, giving each branch its own preview URL with its own certificate, keeping the previous release ready for an instant rollback, and backing up both the application data and the platform's own configuration off the machine.

estimated effort multi-daythe files for this build are in the project pack

PlatformCoolify, self-hostedHostOne Linux server with 4 GB of memory, more if you build on itRoutingTraefik, which Coolify manages, with Let's EncryptRegistryLocal image builds on the same server to startBackupsThe application's own data plus Coolify's configuration, both off the machine

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. have readyroughly 10 to 25 USD a month depending on provider and memory

    Why Coolify idles around 2 GB and a build wants the rest. On 2 GB the build kills production, which looks like a mystery outage.

    Get it Any virtual server provider. Choose a region close to your users, because that choice is now your entire content delivery strategy. open ↗

    Verify free -m reports 4 GB or more

  2. have readya few USD if deleted the same day

    Why The drill proves nothing on the machine that already has the state. Create it for a day and destroy it after.

    Get it The same provider, smallest plan meeting the memory floor.

    Verify You can SSH to it

  3. have readyroughly 10 to 15 USD a year

    Why Wildcard certificates for preview hostnames need a DNS challenge, which needs an API token. A registrar without an API makes previews far harder.

    Get it Use a registrar or DNS host with an API, create a token scoped to the zone, and add both the A record and the wildcard record.

    Verify The wildcard hostname resolves and the token can create a TXT record

  4. free for personal repositories

    Why The whole pipeline is webhook driven. Without it you are deploying by hand, which is the thing you were trying to stop doing.

    Get it GitHub, GitLab or a self-hosted forge. Connect it in the platform and authorise the webhook.

    Verify A test push shows up as a deployment

  5. a few USD a month at these volumes

    Why Backups on the server die with the server. This includes the platform configuration, which exists nowhere else.

    Get it Object storage from any provider, with credentials scoped to write into one bucket.

    Verify A test file uploads and lists from your laptop

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- This is infrastructure, so the state worth writing down is operational.
- server · address, memory, disk, and what else is running on it
- services · one per application, with its repository, branch, build command and environment variables
- domains · production hostname, and the wildcard used for preview hostnames
- secrets · every environment variable per service, kept somewhere that is not the server
- backups · application data, Coolify configuration, and the date of the last restore drill

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
COOLIFY_DOMAINrequireddeploy.example.comHostname for the platform dashboard. Keep it off your production domain so an application misconfiguration cannot shadow it.
PREVIEW_WILDCARD_DOMAINrequired*.preview.example.comThe wildcard used for per-branch preview hostnames.
DNS_API_TOKENsecretrequiredreplace-with-provider-tokenYour DNS provider's API token, scoped to the zone. Needed for wildcard certificate issuance.
PRODUCTION_DATABASE_URLsecretrequiredpostgres://user:pass@db:5432/appSet in the platform, never in the repository.
PREVIEW_DATABASE_URLsecretrequiredpostgres://user:pass@db:5432/app_previewA different database from production. This variable is the isolation.
BACKUP_DESTrequireds3://your-bucket/deployWhere both nightly artefacts go: application data and platform configuration.

The build, in order

  1. Server, DNS and the platform

    Coolify runs, you can reach its dashboard safely, and DNS is ready for preview hostnames.

    1. A non-root user, SSH keys only, and a firewall allowing SSH, 80 and 443. Verify with a scan from your laptop rather than by reading the configuration.

      terminal
      ufw allow OpenSSH && ufw allow 80,443/tcp && ufw enable
      nmap -Pn YOUR_SERVER_IP
    2. Its installation script sets up Docker and the platform. Change the initial dashboard credentials immediately.

      terminal
      curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
    3. An A record for the dashboard and for production, plus a wildcard for preview hostnames. Add a DNS provider API token so wildcard certificates can be issued.

      terminal
      dig +short app.example.com
      dig +short test.preview.example.com
    done when · tick each as it passes
    watch out
    • Preview deployments need a wildcard DNS record, and a wildcard needs a wildcard certificate, which needs a DNS challenge rather than the usual HTTP one. That means an API token for your DNS provider. Sort this out in Phase 1, because discovering it when your first preview URL fails to get a certificate is a bad afternoon.
  2. First deploy from a push

    Pushing to the main branch deploys, without you touching the server.

    1. Point at the repository and branch. Let the platform detect the build, then check what it detected rather than assuming it guessed right.

    2. Every secret goes in the platform's own storage, never into the repository. This is also what makes preview environments possible later.

    3. Run top on the server while the build runs. This one observation prevents the most common self-hosting outage.

      terminal
      free -m
      top -o %MEM
    done when · tick each as it passes
    watch out
    • Builds run on the same server as production by default, and a Node build can consume more memory than the running application. On a 4 GB server this shows up as the build killing production, which looks like a random outage. Watch memory during the first build, and add swap or move builds elsewhere before it bites.
  3. Preview deployments per branch

    Every pull request gets its own URL, which is the feature you were actually paying for.

    1. Configure the wildcard domain for previews and confirm certificate issuance works through the DNS challenge.

    2. A separate database, seeded rather than copied from production. Override the connection variable at the preview level.

    3. Write a record from a preview and confirm it is absent from production. Do this once, deliberately, before you trust it.

    done when · tick each as it passes
    watch out
    • A preview environment that inherits production environment variables will happily write to the production database, and the first time it does you will find out through data rather than through an error. Give previews their own database and their own variables from the very first preview, not after the first accident.
  4. Rollback and health

    A bad deploy is a one-click problem rather than an emergency.

    1. An endpoint that queries the database. A static endpoint returns healthy while the application is unable to serve anyone, which is worse than no check.

      Files src/health

    2. The old container keeps serving until the new one passes. Verify by watching requests during a deploy.

    3. Push a commit that fails to start. Confirm the site stays up, then roll back and time it.

    done when · tick each as it passes
    watch out
    • A deployment strategy that stops the old container before the new one is healthy gives you downtime on every deploy and an outage on every bad one. Configure the health check and confirm the old container keeps serving until the new one passes.
  5. Backups, including the platform itself

    You can rebuild everything, including the configuration that describes everything.

    1. Database dumps and any uploaded files, dated, off the machine, several generations retained.

      Files scripts/backup.sh

    2. Coolify's own database and configuration directory. This is what stores your services, domains and variables.

      Files scripts/backup.sh

    3. Check each morning that today's files exist. Silence is not evidence that a backup ran.

      Files scripts/check_backup.sh

    done when · tick each as it passes
    watch out
    • Backing up your database and not the platform configuration means a restore leaves you re-entering every service, domain and environment variable from memory. The environment variables in particular exist nowhere else once the server is gone.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more hosting.