Skip to content

Deploying Sellf to Coolify

Coolify is a PaaS for managing applications on your own servers. It comes in two flavors:

Coolify Self-HostedCoolify Cloud
Where the Coolify dashboard runsOn your own VPSOn Coolify’s servers
Where your Sellf store runsOn your own VPS (same machine as Coolify, or a separate one)On your own VPS (you connect it to the Cloud dashboard)
CostFree forever$5/mo for 2 servers + $3/mo per extra server
You manageCoolify itself + your apps + your serversJust your apps + your servers (Coolify auto-updates itself)
Backups, alerts, auto-updateDIYIncluded
Best forDIY tinkerers, complete control, zero recurring costPeople who want managed Coolify but still own their data and hardware

Key point common to both: your Sellf store always runs on a VPS that you rent (Hetzner, DigitalOcean, Contabo, etc.). Coolify Cloud doesn’t host your apps — it only hosts the control panel. So both options require you to have a server with enough RAM (see Requirements below).

This guide covers both modes. Pick one and follow only the steps for that mode where they differ.

Pick Coolify if:

  • You have (or are willing to rent) a VPS with 8 GB+ RAM. The Sellf build itself needs ~3 GB free for bun run build on Next.js 16 with Turbopack; on a 4 GB VPS Coolify + Postgres + Redis already eat ~1 GB, leaving the build to OOM. Verified 2026-05-27: 4 GB Hetzner CX22 OOM-kills the build; 8 GB Hetzner CX32 builds in ~8 minutes and serves successfully.
  • You want everything on your own infrastructure (no Supabase Cloud, no Vercel)
  • You’re OK with self-hosting Postgres (and your own backups, on self-hosted Coolify)
  • You want “deploy and forget” — Coolify handles auto-renew TLS, automatic redeploys on git push, container restarts

Pick Coolify Cloud if you want all that AND you’d rather not run the Coolify dashboard yourself (auto-updates, backups, email alerts handled for you, ~$5/mo).

Pick Coolify Self-Hosted if you want zero recurring software bills (you still pay your VPS provider) AND you’re comfortable maintaining the Coolify management UI yourself (docker compose pull && restart once a month).

Don’t pick Coolify if any of these fit you better:

  • You want free-tier hosting: Coolify still needs your own VPS, ~$5–10/mo minimum. See DEPLOYMENT-VERCEL-NETLIFY.md — Vercel + Supabase Cloud both have free tiers.
  • You want the smallest possible footprint: see DEPLOYMENT-MIKRUS.md — Sellf alone runs on a $9/year mikr.us VPS without Docker.

Shortest path — use the StackPilot installer

Section titled “Shortest path — use the StackPilot installer”

StackPilot’s install-coolify.sh automates this entire guide. Two invocation styles depending on which Coolify flavor you use:

Self-hosted Coolify (default):

Terminal window
./apps/sellf/install-coolify.sh \
--ssh-host <vps-alias> \
--repo-path /path/to/sellf

The script installs Coolify on the target (if absent), registers an admin user, generates an API token, creates the application, sets all the env vars, applies database migrations, and creates the Stripe webhook. Total time: ~12 minutes on a fresh VPS, ~7 minutes if Coolify is already running.

Coolify Cloud:

Terminal window
./apps/sellf/install-coolify.sh \
--coolify-cloud \
--coolify-token <your-api-token> \
--server-uuid <uuid-of-server-already-added-to-cloud> \
--repo-path /path/to/sellf

For Cloud, you’ve already done the one-time setup in Coolify Cloud (sign in, add your server, generate an API token). The script then just creates the project + app + env vars + Stripe webhook against https://app.coolify.io/api/v1/.... Total time: ~7 minutes.

Verified on a Hetzner CX32 (8 GB RAM) 2026-05-27.

If you prefer the manual flow (or are deploying without root SSH access on the VPS), follow the steps below.

Mode A: Self-hosted (install Coolify on your VPS)

Section titled “Mode A: Self-hosted (install Coolify on your VPS)”

If you don’t already have Coolify on a VPS, install it on Debian/Ubuntu:

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

After install, open http://<your-vps-ip>:8000 and complete the first-run wizard (admin email + password). The wizard already adds the host VPS as your first “server” automatically.

Full Coolify install docs: https://coolify.io/docs/installation

Mode B: Coolify Cloud (sign up + connect a server)

Section titled “Mode B: Coolify Cloud (sign up + connect a server)”
  1. Sign up at https://app.coolify.io
  2. Pick a plan ($5/mo for 2 servers is enough for one Sellf instance + room to grow)
  3. In the Cloud dashboard, click Servers → New Server
  4. Coolify will give you an SSH public key. Add it to your VPS’s ~/.ssh/authorized_keys (Coolify Cloud needs to SSH into your VPS to deploy apps there)
  5. Enter your VPS’s IP address in the form and click Validate
  6. Once validation passes, your server is ready for deployments

For the rest of this guide, the Coolify dashboard URL is https://app.coolify.io (Cloud) instead of http://<your-vps-ip>:8000 (Self-Hosted). All other steps work identically — same UI, same API.

In Coolify dashboard:

  1. Projects → New Project → name it sellf
  2. Inside the project, New Resource → Public Repository
  3. Paste:
    • Git Repository: https://github.com/jurczykpawel/sellf
    • Branch: main
    • Build Pack: Docker Compose
    • Compose File Location: docker-compose.fullstack.yml
  4. Click Continue

Coolify will read the compose file and ask for env vars referenced in it. You’ll need to fill in:

Generated locally (run in your terminal first)

Section titled “Generated locally (run in your terminal first)”
Terminal window
echo "POSTGRES_PASSWORD=$(openssl rand -base64 24 | tr -d '=+/' | cut -c1-24)"
echo "JWT_SECRET=$(openssl rand -base64 32)"
echo "ANON_KEY=<generate via supabase JWT signing tool, see Step 3.1>"
echo "SERVICE_ROLE_KEY=<same>"
echo "CHECKOUT_BINDING_SECRET=$(openssl rand -base64 32)"
echo "APP_ENCRYPTION_KEY=$(openssl rand -base64 32)"
echo "LOGINWALL_SECRET=$(openssl rand -hex 32)"

Self-hosted Supabase needs an ANON_KEY and SERVICE_ROLE_KEY signed with your JWT_SECRET. Use Supabase’s online tool: https://supabase.com/docs/guides/self-hosting#api-keys (the page has a built-in generator). Or run locally:

Terminal window
JWT_SECRET="<your value from above>"
# anon key:
docker run --rm -i node:20-alpine sh -c "npm i -g jsonwebtoken-cli && jwt encode --secret '$JWT_SECRET' '{\"role\": \"anon\", \"iss\": \"supabase\"}'"
# service_role key:
docker run --rm -i node:20-alpine sh -c "npm i -g jsonwebtoken-cli && jwt encode --secret '$JWT_SECRET' '{\"role\": \"service_role\", \"iss\": \"supabase\"}'"
POSTGRES_PASSWORD=<from step 3>
JWT_SECRET=<from step 3>
ANON_KEY=<from step 3.1>
SERVICE_ROLE_KEY=<from step 3.1>
SUPABASE_URL=http://kong:8000 # internal Docker network
SUPABASE_ANON_KEY=<same as ANON_KEY>
SUPABASE_SERVICE_ROLE_KEY=<same as SERVICE_ROLE_KEY>
SITE_URL=https://<your-coolify-app-domain>
STRIPE_SECRET_KEY=sk_test_… # or sk_live_… for production
STRIPE_PUBLISHABLE_KEY=pk_test_…
# STRIPE_WEBHOOK_SECRET — leave unset; you'll register the webhook from
# the Sellf admin in Step 5 and the signing secret will land in the DB.
CHECKOUT_BINDING_SECRET=<from step 3>
APP_ENCRYPTION_KEY=<from step 3>
LOGINWALL_SECRET=<from step 3>
TRUSTED_PROXY=true

Click Deploy in Coolify. First deploy takes 5–10 minutes (it builds Sellf’s Next.js bundle and pulls Supabase images). Coolify shows live build logs.

No separate migration stepdocker-compose.fullstack.yml mounts ./supabase/migrations into the Postgres container’s /docker-entrypoint-initdb.d, so migrations run automatically on first boot. This is the main reason Coolify is closer to true one-click than Vercel/Netlify.

Step 5 — Sign up + register Stripe webhook (1 min, 1 click)

Section titled “Step 5 — Sign up + register Stripe webhook (1 min, 1 click)”

After deploy, your app is at https://<your-coolify-app-domain>.

  1. Open the URL → sign up with your email → click the magic link from your inbox. The first registered user automatically becomes admin.
  2. In the admin, go to Settings → Payments (or /dashboard/settings).
  3. API keys card: paste your Stripe Publishable Key and Secret Key. Saved encrypted to your Supabase DB.
  4. Stripe Webhook card: click Register webhook. Sellf calls Stripe for you — creates the endpoint pointing at https://<your-domain>/api/webhooks/stripe, subscribes to all the events it needs, and stores the signing secret encrypted in stripe_configurations. No Stripe Dashboard hopping, no env var dance.

Env-config alt: If you’d rather keep secrets in Coolify env vars (e.g. for CI-driven redeploys), use the legacy flow — create the webhook manually at https://dashboard.stripe.com/test/webhooks, paste the whsec_… into Coolify’s STRIPE_WEBHOOK_SECRET, restart. Same outcome.

In Coolify dashboard:

  1. Open your Sellf application
  2. Domains → Add Domain → enter your custom domain (e.g. shop.example.com)
  3. Point your DNS A record at the Coolify VPS IP
  4. Coolify auto-provisions a Let’s Encrypt cert in ~30 seconds

Update SITE_URL env var to match the new domain, restart.

Coolify can’t see inside the Sellf Supabase. Set up your own backups:

Terminal window
# In Coolify dashboard → your project → Backups
# OR via cron on the VPS:
0 3 * * * docker exec sellf-db pg_dumpall -U postgres > /backups/sellf-$(date +%F).sql

For S3-compatible offsite backups, see vault/brands/_shared/infra/INDEX.md for the backup-host-restic.sh pattern.

In Coolify dashboard:

  1. Open your Sellf app
  2. Deployments → Redeploy — pulls latest main from GitHub, rebuilds
  3. Migrations in newer Sellf versions run automatically on container restart (idempotent)

If you want auto-deploy on every git push to main, enable Webhooks → GitHub in Coolify project settings.

Symptom: sellf-db container keeps restarting, logs say FATAL: password authentication failed.

Cause: POSTGRES_PASSWORD env var was changed after the first boot. Postgres data dir was initialized with the old password; the new password can’t authenticate.

Fix: stop the stack, docker volume rm sellf_postgres_data, redeploy. Destroys all data — make sure you have a backup if you’re past first-deploy.

Kong API gateway returns 404 on every request

Section titled “Kong API gateway returns 404 on every request”

Cause: missing or invalid supabase/kong.yml file in the repo. The compose mounts it read-only.

Fix: check the file exists at the path docker-compose.fullstack.yml expects (./supabase/kong.yml).

Coolify free tier allows N resources per server. Check the Coolify pricing page — if you’re over, either delete unused resources or upgrade.

Symptom: Coolify shows the deploy as “in progress” but the build container disappears with no error in the UI logs. dmesg on the host shows:

Out of memory: Killed process <pid> (bun) total-vm:76GB ...

Cause: Next.js 16 + Turbopack + bun run build peaks around 3 GB resident, and Coolify’s own services + Postgres + Redis already use ~1 GB. A 4 GB VPS doesn’t fit.

Fix: upgrade to 8 GB+ (Hetzner CX32, Contabo VPS 200, Linode g6-standard-2, etc.) and redeploy. Or build the image elsewhere and let Coolify just pull it (see “Build server” in Coolify settings).

Stripe webhooks return 400 “Missing signature”

Section titled “Stripe webhooks return 400 “Missing signature””

Same issue as the Vercel/Netlify guide — STRIPE_WEBHOOK_SECRET env var doesn’t match the Stripe Dashboard’s signing secret. Re-copy and restart the container.


Why this isn’t published as a “Coolify Template” yet

Section titled “Why this isn’t published as a “Coolify Template” yet”

Coolify supports one-click templates from a marketplace. Sellf doesn’t have one yet because:

  • The fullstack compose file uses Supabase images that need JWT-signed keys (Step 3.1) — Coolify’s template format doesn’t have native support for “generate this JWT, sign with that other generated value.” You’d still need the manual JWT step.
  • Supabase Self-Hosted is a moving target (auth/realtime/storage versions change). The fullstack compose pins to known-good versions; a template would need maintenance.

If someone wants to contribute a Coolify template that bundles a JWT-signing init container, it would be welcome — open an issue.