@stevie_builds
Home

Guide

Build and self-host your own AI app

One small server, Coolify, a private GitHub repo, Replicate, and a coding agent that keeps going until the app is live. Eight checkpoints.

Contents
  1. 1See the whole system
  2. 2Rent the server
  3. 3Install Coolify
  4. 4Connect the accounts
  5. 5Handle secrets
  6. 6Give the build prompt
  7. 7Deploy it
  8. 8Prove it works

1 of 8

See the whole system

You are renting a computer on the internet. Coolify gives it a deployment dashboard. The rest is code, model access and clear instructions.

VPS

A virtual private server. A computer you rent by the month and control over SSH.

Coolify

Builds and runs several apps on that machine. CPU, RAM and disk set the limit, not an app count.

GitHub

Holds the private code, every commit, and the branch Coolify deploys.

Replicate

API access to hosted models, so the server does not need a GPU.

The coding agent does the repetitive part. It builds the app, pushes the code, configures Coolify, deploys, watches the logs and tests the live URL. You own the accounts, approve access and keep the secrets.

2 of 8

Rent a small server

Hetzner is an easy start, but any Ubuntu-compatible VPS works. Start with enough headroom for builds, then resize when real usage says so.

Pick x86 / AMD64

Broadest Docker image support. ARM64 is fine only when every image and native dependency you need supports it. A Hetzner backup cannot switch architectures later.

Small first, resize later

Performance can be rescaled. Storage increases are one-way and changing the OS wipes the disk, so back up before either. See the server creation guide.

Select during creation

  • A location near you or your users.
  • An SSH key. SSH is the encrypted connection your terminal uses to control the server.
  • Ubuntu 24.04 LTS, 64-bit.
  • Hetzner Cloud Firewall and Backups. Daily backups use seven rotating slots. Your app data still needs its own tested backup.
  • A clear name such as apps-01.

3 of 8

Secure the basics, then install Coolify

This is the minimum sensible setup. You are removing easy risks, not becoming a sysadmin.

3.1 Update the fresh server

Connect with the key you added, install updates, reconnect after the reboot.

server-first-login.sh

ssh root@<SERVER_IP>
apt update
apt upgrade -y
reboot

Keep key-based SSH. When you are comfortable, create a named sudo user, verify it in a second terminal, then disable password SSH and root password login. Do not close your working session until the new login works. If an agent makes the change, make it show the effective SSH settings before reloading the service.

3.2 Add firewall rules

Use your provider's firewall. Docker networking can bypass rules made only with UFW. Coolify's firewall page lists the ports and when they can close.

PortUse
22SSH. Restrict to your IP if it is stable.
80HTTP and certificate issuance. Open.
443HTTPS app traffic. Open.
8000Initial Coolify dashboard access.
6001/6002Coolify realtime and terminal during setup.

Once the dashboard has a working HTTPS domain, Coolify says you can close 8000, 6001 and 6002. Keep 22, 80 and 443.

3.3 Run the installer

Use a fresh server. Check the installation page first in case prerequisites change.

install-coolify.sh

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

3.4 Point a domain at it

  • Create an A record such as coolify.example.com pointing to the server's IPv4 address.
  • Set that full https:// URL in Coolify settings.
  • Create another A record for the app domain. Several domains can point at one server.
  • Wait for DNS, then let Coolify request and renew the certificate.

References: DNS configuration and domains and HTTPS.

SQLite needs a real home

Put the database under /app/data, mount a Coolify volume there, run one replica. Containers are replaceable. The volume survives redeploys. Never share one SQLite file between replicas.

Health checks need a boring answer

Add GET /api/health. Return 200 only when the app can reach SQLite, with a small JSON body and no secrets. Set the same path in Coolify's health check.
optional-2gb-swap.sh

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
free -h

Back up both layers. Coolify's own settings and the application volume. An instance backup does not include volume data. For SQLite, use an application-aware backup or pause writes while copying, store a copy off the server, and test a restore. See persistent storage and backup and restore.

4 of 8

Connect GitHub and Replicate

Create the accounts, then grant the narrowest access that lets one app deploy.

GitHub

Create a private repository. Let Coolify read only that repo. GitHub's repository guide covers the private option.

Replicate

Create an account, pick a model from its official page, then make a named token under API tokens. Treat it like a password. One token per app.

Give Coolify access to the private repo

Recommended

Coolify GitHub App

Install it for selected repositories only. It handles selection, webhooks and automatic deploys. See the GitHub integration overview.

One-repo fallback

Read-only deploy key

An SSH key attached to one repository. Leave write access off. Coolify only clones and fetches. See managing deploy keys.

Create a Coolify API token only if the agent will deploy

  • In Coolify, enable API access under Settings, Advanced.
  • Open Security, API Tokens. Give it a short expiry and only the permissions needed.
  • For an agent creating and deploying an app that usually means read, write and deploy. Avoid root and read:sensitive unless an endpoint proves it needs them.
  • Store the token once. The base URL is your Coolify URL followed by /api/v1.

Check current permission names in the API authorization guide. Tokens are scoped to the active team.

5 of 8

Keep secrets out of the conversation

A secret is any value that grants access: API tokens, private keys, passwords, session keys. The safest prompt contains file paths and variable names, never values.

Temporary files, when an agent needs direct access

  1. One file per secret with a clear name, such as ~/Desktop/replicate-api-token.txt. Only the value goes in.
  2. Restrict it with chmod 600 ~/Desktop/replicate-api-token.txt.
  3. Give the path and the rule. “Read this file only when needed. Never print, echo, log, screenshot, commit or paste its contents.”
  4. Make the agent put values in the right place. Local values in an ignored .env.local. Production values in Coolify's encrypted variables. Server-side only.
  5. Verify, then delete the files and empty the Trash. Deletion reduces exposure. It does not make a leaked token safe. Rotate anything exposed.

The two-file environment pattern

.env.example is safe to commit because it holds names and fake placeholders. .env.local holds real values and stays ignored. Never prefix a server secret with NEXT_PUBLIC_. Next.js ships those to the browser.

environment-file-pattern.txt

# Commit this file with names and fake placeholders only
REPLICATE_API_TOKEN=
REPLICATE_MODEL=owner/model-name
AUTH_SECRET=
APP_PASSWORD_HASH=
DATABASE_PATH=/app/data/app.db

# Keep real local values here (never commit)
# .env.local

# .gitignore must include
.env*
!.env.example

6 of 8

Customise one prompt, then let the agent work

This one builds a private, mobile-first AI calorie tracker. Change the product if you like. Keep the infrastructure and safety sections.

build-private-ai-app.txt

Build and deploy a private, mobile-first AI calorie tracker. Continue through implementation, deployment and live verification. Do not stop after planning, scaffolding or a local build.

PROJECT VALUES
- App name: APP_NAME
- Local working folder: LOCAL_PATH
- GitHub owner/repository: GITHUB_OWNER/REPO_NAME
- Production domain: DOMAIN
- Coolify URL: COOLIFY_URL
- Coolify API token file: COOLIFY_TOKEN_FILE_PATH
- Replicate token file: REPLICATE_TOKEN_FILE_PATH
- Single-user login secret or password-hash file: AUTH_SECRET_FILE_PATH
- Preferred Replicate model: REPLICATE_MODEL (confirm its current official model page and API schema before coding)

NON-NEGOTIABLE SAFETY
1. Treat every token and password as secret. Read the named files only when required. Never print, echo, log, screenshot, paste into chat, include in command output, or commit their contents.
2. Use obvious fake placeholders in .env.example. Put real local values in .env.local, confirm it is ignored, and put production values in Coolify's encrypted environment variables.
3. Keep every Replicate call server-side. Never use NEXT_PUBLIC_ for a secret and never send the Replicate token to the browser.
4. Use official current documentation for Next.js, Coolify and Replicate APIs. Do not rely on remembered endpoints or stale examples.
5. Before pushing, inspect the staged diff and repository history for secret-shaped values. If a secret is exposed, stop, tell me which credential needs rotation without repeating it, rotate it, then continue.

BUILD THE APP
1. Inspect LOCAL_PATH first. Reuse any existing app, repository, branch, components and deployment configuration. Do not create a duplicate repository or second app resource.
2. Use the current stable Next.js App Router with TypeScript. Keep the dependency list small and use the repository's existing package manager.
3. Build a fast, installable PWA with a web app manifest, app icons and a clear offline state. It must work at 320px wide, with 44px tap targets, safe-area spacing, strong focus states, reduced-motion support and no horizontal overflow.
4. Add single-user authentication with a secure password hash, an HttpOnly Secure SameSite cookie, session expiry, logout, rate limiting on login and protected app/API routes. Do not store a plaintext password.
5. Store meals, food items, estimated calories, protein/carbs/fat, notes, timestamps and AI-request status in SQLite. Add explicit migrations and a documented migration command.
6. Mount SQLite under one configurable data directory such as /app/data. Run exactly one application replica. SQLite must live on a persistent Coolify volume and survive container replacement.
7. Let the user type or photograph a meal. Send the request from a protected server route to REPLICATE_MODEL, validate the model output, show the estimate as editable before saving, and handle timeouts, invalid output and model errors without losing the user's input.
8. Add daily totals, recent meals, edit/delete, loading and empty states. Make the primary flow comfortable on a phone.
9. Add GET /api/health. It must return a small non-secret JSON response and a non-200 status when the app cannot reach its database. Do not require authentication for this endpoint.
10. Add a production Dockerfile with an efficient multi-stage build, a non-root runtime user where practical, a small runtime image and a startup path that applies safe migrations before starting the app.
11. Add .env.example, .gitignore rules, a concise README and deployment notes covering the exact data volume path, internal port, health path, migration command and required environment-variable names.

VERIFY BEFORE DEPLOYING
1. Add focused tests for authentication boundaries, health response, database persistence logic, model-output validation and the main mobile flow. Do not call the paid Replicate API in tests.
2. Run formatting, lint, TypeScript checking, tests and the production build. Fix every relevant failure.
3. Inspect at 320px, a common iPhone width, tablet and desktop. Fix overflow, contrast, focus order, touch targets and code or error text that breaks the layout.
4. Create or reuse the private GitHub repository GITHUB_OWNER/REPO_NAME. Commit logical changes and push the finished branch. Preserve concurrent work and do not force-push over other changes.

DEPLOY WITH COOLIFY
1. Reuse the existing Coolify project/application when one already matches this repository and domain. Otherwise create one application connected to the private GitHub repository, using the GitHub App or a read-only deploy key.
2. Configure the production branch, Dockerfile build, internal port, DOMAIN, /api/health, and one replica.
3. Create a persistent volume whose container destination exactly matches the SQLite data directory. Confirm the database file is written there, not inside the replaceable container filesystem.
4. Add the required production environment variables from the named secret files without displaying their values. Mark sensitive values as secrets.
5. Make migrations run safely once during startup or as a controlled pre-deploy command. Never run two SQLite replicas against the same file.
6. Trigger the deployment. Watch build and runtime logs without exposing secrets. If the small host runs out of memory during builds, reduce build load, use a more efficient Docker build or add safe headroom/swap, then retry.
7. Wait for DNS and HTTPS, then verify the exact live URL.

LIVE ACCEPTANCE CHECKS
- DOMAIN serves valid HTTPS.
- An unauthenticated visitor cannot see app data or call protected APIs.
- Login and logout work, and the session cookie has secure production settings.
- /api/health returns success without leaking configuration.
- A test meal can be estimated through a server-side Replicate call, edited and saved.
- The saved meal still exists after a redeploy/restart.
- The interface works at 320px and a common iPhone width.
- The GitHub repository is private, one app replica is running, the SQLite volume is mounted, and a backup method is documented.
- No real secret exists in source, git history, screenshots, prompts or logs.

Finish by reporting the live URL, deployed commit, checks run, Coolify resource used, volume destination, health result and any secret files I should now delete. Never include a secret value in the report.

7 of 8

Choose how Coolify gets configured

Both paths end in the same app. Use the dashboard if you want to see every setting. Use the API if you want the agent to keep going without you clicking.

Path A

Coolify UI

  1. One project and a production environment.
  2. Add the private repo via the GitHub App or deploy key.
  3. Select the branch and Dockerfile build. Set the internal port.
  4. Encrypted variables, one replica, the SQLite volume, a safe migration command.
  5. Set the HTTPS domain and /api/health, deploy, read the logs.

Path B

Coolify API

Give the agent the Coolify URL, the token file path, any known server, project and environment IDs, the repo and branch, the domain, variable names and secret file paths, the SQLite volume destination and the health path. If an ID is unknown, tell it to list and reuse matching resources before creating anything.

Safe API handoff

Makes the no-print rule explicit and prevents duplicate resources. Coolify uses a Bearer token and the /api/v1 base URL.

coolify-agent-handoff.txt

Use the existing Coolify instance and deploy the existing private GitHub repository. Do not create duplicate projects, applications or repositories.

- Coolify URL: COOLIFY_URL
- Coolify API token file: COOLIFY_TOKEN_FILE_PATH
- Server/project/environment IDs if known: COOLIFY_IDS_OR_UNKNOWN
- GitHub repository and branch: GITHUB_OWNER/REPO_NAME, BRANCH
- Production domain: DOMAIN
- Required environment variable names: ENV_VAR_NAMES_ONLY
- Secret file paths: SECRET_FILE_PATHS
- SQLite container directory: SQLITE_DATA_DIRECTORY
- Health endpoint: /api/health

Read secrets only from the exact files above. Never print, echo, log, screenshot, commit or paste their contents into chat. Use the narrowest Coolify token permissions that can complete the job. Inspect existing resources first, configure one replica and a persistent volume, set encrypted environment variables, deploy, wait for healthy HTTPS, verify auth and persistence across one redeploy, then report IDs and results without secret values.

For the next update

The shorter prompt, once the app exists. It says that “pushed” is not the finish line.

deploy-update.txt

Deploy the current app update all the way to production.

App folder: LOCAL_PATH
Repository: GITHUB_OWNER/REPO_NAME
Domain: DOMAIN
Coolify URL: COOLIFY_URL
Coolify token file: COOLIFY_TOKEN_FILE_PATH

Inspect the existing branch, GitHub repository and Coolify resource first. Reuse them; do not create duplicates. Preserve concurrent changes. Read the token file only when needed and never print, log, commit or paste its contents.

Use current official docs for any API that may have changed. Run lint, typecheck, tests and the production build. Confirm migrations are safe, SQLite remains on its persistent volume with exactly one replica, and secrets stay server-side. Commit and push the finished update, trigger or wait for the existing Coolify deployment, then verify HTTPS, auth, /api/health, the changed feature and persistence on DOMAIN. Do not stop at a plan, local build or successful push. Report the live commit and verification results without secret values.

If the deploy fails

SymptomCheck
DNSConfirm the A record resolves from a public resolver. Certificates cannot issue until 80 and 443 reach Coolify.
502 / healthCheck the internal port, bind to 0.0.0.0, call /api/health inside the container, read runtime logs.
Empty dataSQLite is inside the container or the mount path is wrong. Mount the exact parent directory and restore from backup.
Host freezesStop parallel builds, free disk, tighten the Docker build, add swap or resize. Do not keep retrying a starved build.
Replicate 401Check the production variable name and the server-side header. If the token may be exposed, disable it and make a new one.
Cannot cloneRefresh the GitHub App's selected repos, or confirm the deploy key and SSH clone URL. Do not make the repo public as a shortcut.

8 of 8

Prove it survives real life

A green badge is one signal. The app is finished when privacy, AI calls, phone UX and persistence all work on the public URL.

  • The repo is private and the deployed commit matches the intended branch.
  • The domain has valid HTTPS with no warning.
  • An unauthenticated visitor cannot see data or call protected APIs. Login and logout work.
  • /api/health returns 200 with no configuration or secret values.
  • A meal goes to Replicate only from a protected server route, can be edited, and saves.
  • The saved meal is still there after a restart or redeploy. One replica, mounted volume.
  • The app works at 320px, iPhone width, tablet and desktop, with visible keyboard focus.
  • Coolify settings and app data have backups, and the restore path has been tested or written down.
  • Temporary files are deleted. Anything shown in chat, logs, screenshots or Git is rotated.

Docs used for this guide

Want the app built with you?

I build small AI products and the deployment behind them, then write down the parts worth reusing.