Skip to content

VPS Deployment (Production Layout)

Reference for deploying LaunchKit Pro to a single VPS with Nginx, systemd, and release symlinks. Paths below match the LaunchKit Labs production layout; adjust BASE_DIR for your own domain.

No secrets in docs

Use placeholder values in documentation. Store real credentials only in /var/www/launchkitlabs/shared/backend/.env (or your secrets manager). Never source .env in shell — values may contain spaces. Use systemd EnvironmentFile= in production.

Domains

HostPurpose
launchkitlabs.comMarketing site
app.launchkitlabs.comNext.js frontend (dashboard + admin)
api.launchkitlabs.comNestJS API
docs.launchkitlabs.comVitePress buyer documentation (static)

Directory layout

text
/var/www/launchkitlabs/
├── apps/
│   ├── api/
│   │   ├── current          → symlink to active release
│   │   └── releases/
│   │       └── backend-YYYYMMDDhhmmss/   (or timestamp folders)
│   ├── frontend/
│   │   ├── current
│   │   └── releases/
│   └── docs/
│       ├── current
│       └── releases/
├── shared/
│   ├── backend/.env         # shared API secrets (not in git)
│   └── frontend/.env.production
├── logs/
│   ├── api-out.log
│   └── api-error.log
├── backups/                 # local backup archives
├── uploads/                 # optional shared uploads root
├── infra/scripts/           # backup, restore samples
└── deploy-backend.sh        # production backend deploy entrypoint

systemd — API service

Example unit launchkit-api.service:

ini
[Unit]
Description=LaunchKit Pro API
After=network.target postgresql.service

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/launchkitlabs/apps/api/current
EnvironmentFile=/var/www/launchkitlabs/shared/backend/.env
ExecStart=/usr/bin/node /var/www/launchkitlabs/apps/api/current/dist/main.js
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
  • WorkingDirectory must point at apps/api/current
  • ExecStart runs dist/main.js from the same release folder
  • Load env via EnvironmentFile, not shell source

Backend deploy (robust flow)

Production script path:

bash
/var/www/launchkitlabs/deploy-backend.sh

Source template: launchkit-pro-infra/scripts/deploy-backend.sh

Steps performed

  1. Clone new release into apps/api/releases/<timestamp>/
  2. Symlink shared env → .env (contents never printed)
  3. npm ci --include=dev — devDependencies required for nest build
  4. npx prisma generate
  5. npx prisma migrate deploy
  6. npm run build
  7. npm prune --omit=dev — only after successful build
  8. Preflight — boot new release on port 4100–4499 (default 4001), health check before promote
  9. Switch current symlink to new release
  10. systemctl restart launchkit-api
  11. Production health — retry up to 60 seconds (30 × 2s)
  12. Rollback symlink + restart only if health still fails after retries
  13. Prune old releases (keeps last N)

Do not skip preflight

Promoting a broken build without preflight can take production offline. The script aborts before symlink switch if preflight fails.

Health endpoints:

bash
curl -sf http://127.0.0.1:4000/health
curl -sf https://api.launchkitlabs.com/health

Frontend deploy

Typical flow (adjust to your deploy-frontend.sh if present):

  1. Clone/extract release to apps/frontend/releases/<id>/
  2. Link shared/frontend/.env.production
  3. npm ci --include=dev (Next.js build needs devDependencies)
  4. npm run build
  5. npm prune --omit=dev (optional)
  6. Switch apps/frontend/current symlink
  7. Restart launchkit-frontend systemd service (port 3000 behind Nginx)

Required build-time public env:

env
NEXT_PUBLIC_API_URL=https://api.launchkitlabs.com
NEXT_PUBLIC_APP_NAME=LaunchKit Pro
NEXT_PUBLIC_DOCS_URL=https://docs.launchkitlabs.com
NEXT_PUBLIC_SUPPORT_EMAIL=support@launchkitlabs.com

Docs deploy

  1. Build VitePress: cd launchkit-pro-docs && npm ci && npm run build
  2. Upload .vitepress/dist as tarball to server
  3. Extract to apps/docs/releases/<id>/
  4. Switch apps/docs/current symlink
  5. nginx -t && systemctl reload nginx

Nginx

API and app proxy to localhost; docs served as static files. TLS via Let's Encrypt (certbot). See Deployment for sample server blocks.

LaunchKit Pro by LaunchKit Labs — buyer documentation. No secrets in this site.