Skip to content
Heartscale

lovablePublished on · Heartscale team

How to host a Lovable app on a VPS with Coolify

To host a Lovable app on a VPS with Coolify, install Coolify on a Linux server, connect the GitHub repository through a GitHub App and pick a build: Nixpacks with static output in /dist, or a Dockerfile. Then add the VITE_ variables as build variables, point the domain with https:// and turn on deploy on push.

Heartscale’s recommendation: run the first deployment on a test subdomain and check sign-in, writes and refreshes on internal routes before you point the production domain. If the app has real users, payments or personal data, get the variables and secrets reviewed before you switch DNS.

This guide covers hosting only. If you still need to get the code and the database out of Lovable, start with How to leave Lovable and come back here for the server step.

What you need before you start

  • A Linux VPS. Coolify needs 2 CPU cores, 2 GB of RAM and 10 GB of disk, with root or sudo SSH access (Coolify, Installation). The docs recommend a fresh server.
  • A domain whose DNS you can edit.
  • The code on GitHub. In Lovable, use Git sync under Project settings → Git (Lovable, GitHub).
  • Your project’s stack. Open package.json. If it lists @tanstack/react-start, it is TanStack Start and needs a running Node server. If not, it is React + Vite and the build outputs static files to dist/ (Lovable, Deploying outside Lovable).

Step 1: install Coolify

SSH into the VPS and run the official installer:

curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash

If Docker was installed through snap, remove it first. On Ubuntu, use an LTS release: 20.04, 22.04 or 24.04.

When it finishes, the terminal prints the dashboard link at http://<server-ip>:8000. Create the admin account right away. The docs warn that whoever reaches the registration page first becomes the instance admin and gets root access to the server.

Open the ports Coolify uses in your firewall (Coolify, Firewall):

Port Purpose
22 SSH
80 HTTP and certificate issuance
443 HTTPS
8000 Dashboard by IP
6001 and 6002 Real-time updates and web terminal by IP

Once the dashboard runs on a domain, you can close 8000, 6001 and 6002.

Keep a copy of /data/coolify/source/.env. It holds the APP_KEY, which encrypts Coolify’s data and is required to restore the instance.

Step 2: connect GitHub through a GitHub App

The repository Lovable creates is private by default. For private repositories with push events, Coolify points to the GitHub App (Coolify, GitHub App):

  1. In the dashboard, open Sources and choose GitHub App.
  2. Name the source. Leave Organization empty if the repository is on your personal account.
  3. Click Register with GitHub, give the app a unique name on GitHub and confirm with Create GitHub App.
  4. Under Install repositories, pick Only select repositories and check only your app’s repository.

Granting access to a single repository limits what Coolify can see in your account.

Step 3: create the application

  1. Open the project and environment in Coolify and click + New.
  2. Choose Private Repository (with GitHub App).
  3. Select the server. On a self-hosted instance it shows up as localhost.
  4. Pick the source from step 2, then the repository, and click Load Repository.
  5. Choose the branch Lovable syncs, usually main.

The next field is Build pack. It decides how the code becomes a site.

Step 4: choose the build

React + Vite with Nixpacks

This path adds the fewest files. Nixpacks detects the Node project and builds the image for you (Coolify, Nixpacks):

  1. Under Build pack, choose Nixpacks. Leave Base Directory at /.
  2. Under Output type, choose Static site and set Publish Directory to /dist.
  3. Keep port 80. The generated Nginx listens there.
  4. After creation, under General → Build pipeline → Site type, choose SPA.
  5. Check the Install Command, Build Command and Start Command fields under General. Override only what was detected wrong.

Lovable builds on Node 22. Nixpacks reads the version from engines.node in package.json, from .nvmrc, or from the NIXPACKS_NODE_VERSION variable.

React + Vite with a Dockerfile

Use this path if you want control over the image. Lovable suggests two stages: node:22-alpine to build and nginx:alpine to serve dist/ (Lovable, Deploying outside Lovable). An example in that shape:

FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
ARG VITE_SUPABASE_URL
ARG VITE_SUPABASE_PUBLISHABLE_KEY
ARG VITE_SUPABASE_PROJECT_ID
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

And the nginx.conf next to it, with the SPA fallback:

server {
  listen 80;
  root /usr/share/nginx/html;
  location / {
    try_files $uri $uri/ /index.html;
  }
}

In Coolify, choose Dockerfile under Build pack and set Ports Exposes to 80 (Coolify, Dockerfile). Coolify passes build variables as Docker build arguments, so the Dockerfile declares the ARG lines. Lovable notes it cannot run or test Docker builds, so test it yourself.

TanStack Start

Lovable projects created from May 13, 2026 use TanStack Start and need a running Node server. The build runs NITRO_PRESET=node-server npm run build, and the server starts with node .output/server/index.mjs on port 3000. In Coolify, set the internal port to 3000. The process must listen on 0.0.0.0 or the proxy cannot reach it, so set HOST=0.0.0.0. There is no SPA fallback here: the server handles routing.

Step 5: set the VITE_ variables

Variables with the VITE_ prefix are embedded at build time. In a Lovable project they are VITE_SUPABASE_URL, VITE_SUPABASE_PUBLISHABLE_KEY and VITE_SUPABASE_PROJECT_ID, with the values from the project’s .env.

In Coolify (Coolify, Environment variables):

  1. Open the application and click Environment Variables.
  2. Click Add, fill in Name and Value and save with Add variable. You can also paste the whole .env in Developer view.
  3. For VITE_ variables, keep Build time set to Available during build.

Changed a VITE_ value? Run a new deployment. Restart only applies runtime variables.

Anything with VITE_ ends up in every visitor’s browser. Payment, email or AI secrets never take that prefix. On TanStack Start, server function secrets stay as runtime variables, with Build time set to Not available during build.

In our reviews, before the first deployment, we list every variable and check whether any VITE_ one holds a secret. After the build, we search the files in dist/ for those values to confirm what reaches the browser.

Step 6: point the domain and turn on HTTPS

  1. In your DNS, point the hostname to the VPS IP. If you will use both www and the bare domain, create both records.
  2. In Coolify, open Domains and click Add domain.
  3. Under Protocol, choose https. Under Domain, type the hostname, for example app.yourdomain.com.
  4. Add each hostname separately. To keep one as primary, use the www redirect option (Redirect to www or Redirect to non-www).
  5. Redeploy so the proxy applies the configuration.

With https:// and ports 80 and 443 open, the Coolify proxy requests and renews the certificate (Coolify, Domains).

Then go to your app’s auth settings and add the new URL to the allowed redirect URLs. Without it, sign-in breaks on the new domain.

Step 7: deploy on every push

Applications created through a GitHub App come with Auto deploy set to Deploy on push (webhooks) (Coolify, Auto deploy). If you see Manual deployments only, change it under Advanced → Deployment. Then push to the branch and confirm a deployment appears.

Lovable’s Git sync writes to the connected branch. So every change you make in the Lovable chat also goes live. If you want to review first, deploy manually, or point Coolify to another branch and merge changes through pull requests.

Step 8: test the SPA fallback

Open an internal route directly, for example /dashboard, and refresh. A 404 means the index.html fallback is missing.

With Nixpacks, go to General → Build pipeline → Custom Nginx configuration, add try_files $uri $uri/ /index.html; to the location / block and redeploy. A restart will not apply it, because the configuration is copied into the image during the build.

Run the other checks from Lovable’s docs too: sign in and out, then read, write and upload a file.

What becomes yours

Outside Lovable, you handle certificates, backups, access control, monitoring and security audits (Lovable, Deployment, hosting and ownership). Three Coolify points:

  • Instance backup. Keep /data/coolify/source/.env off the server. The docs ask for a backup before every upgrade.
  • Updates. Under Settings → Updates, Automatic updates keeps Coolify current. It does not update the apps, databases or servers Coolify manages (Coolify, Upgrade).
  • The old address. Your lovable.app URL keeps serving the last version published there, and Publish only targets Lovable.

To weigh what this costs each month, read How much does it cost to keep a Lovable app online and our self-hosted deployment page.

Do it yourself or hire help?

If you already use SSH and DNS, the setup is the easy part. What weighs more is what you take on afterwards.

Situation Path
React + Vite project with no secrets in the front end, and someone on the team uses SSH and DNS Do it yourself with this guide
Real users signing in with Google or another provider Worth bringing in a team: the domain, HTTPS and redirect URLs have to switch together
Payment, email or AI secrets, or TanStack Start with server functions Worth bringing in a team like ours: one mistake separating build and runtime variables puts the key in the browser
Nobody technical to maintain the server, backups and updates Request a Heartscale diagnostic before you rent the VPS: it shows what your app uses from Lovable and what needs changes to run elsewhere

Request a Heartscale diagnostic

Our team checks your app’s stack, sets up the build in Coolify, separates build variables from secrets and gets HTTPS, the domain and deploy on push working. Before that, the diagnostic shows what your app uses from Lovable and what needs changes to run elsewhere.

The launch-price diagnostic costs US$ 19 (was US$ 79) and is credited toward the deployment if you go ahead. We only work on apps whose owners can prove they own them.

Request the diagnostic

Frequently asked questions

Frequently asked questions

What VPS do I need to run Coolify with a Lovable app?

Coolify's documentation asks for at least 2 CPU cores, 2 GB of RAM and 10 GB of disk, on Linux with root SSH access. On Ubuntu, use an LTS release (20.04, 22.04 or 24.04) and a fresh server.

Can Coolify build a React + Vite project exported from Lovable?

Yes. With the Nixpacks build pack, Coolify runs npm run build and serves the /dist folder through Nginx when you pick Static site and set Publish Directory to /dist. You can also use the two-stage Dockerfile Lovable suggests.

Why are my VITE_ variables missing in the app hosted on Coolify?

VITE_ variables are embedded at build time, not at runtime. In Coolify, keep Build time set to Available during build and run a new deployment after changing a value. A Restart is not enough.

How does Coolify handle HTTPS for my domain?

Point the domain's DNS to the VPS IP, open ports 80 and 443 and add the address with https:// under Domains. After a redeploy, the Coolify proxy requests and renews the certificate for you.

Will every change I make in Lovable go live on Coolify?

If Lovable's Git sync writes to the same branch Coolify tracks and Auto deploy is set to Deploy on push (webhooks), yes. Every push to the configured branch triggers a new deployment.

My Lovable app returns 404 when I refresh a page on Coolify. How do I fix it?

The SPA fallback is missing: the server has to return index.html for routes that are not files. In Coolify, edit General → Build pipeline → Custom Nginx configuration with try_files and redeploy.

Is it worth hiring someone to host a Lovable app with Coolify?

It is when the app has real users, payments or personal data, or when nobody on the team will look after the server, backups and updates. Heartscale runs a launch-price diagnostic for US$ 19 (was US$ 79), credited toward the deployment if you go ahead within 15 days.

Start with the diagnostic.

The diagnostic costs US$ 19, paid by payment link. We deliver the report in 2 business days and walk you through the findings in a meeting. The fee is credited if you hire the service within 15 days. Everything we set up stays in your name.

Reduces the risk, does not eliminate it. We only work with the app’s owner, with proof of ownership.