placebo.mk/DEPLOYMENT.md
2026-02-22 05:30:47 +01:00

16 KiB

Placebo.mk Deployment Guide (Coolify)

Complete deployment guide for the Placebo.mk satirical news platform on a VPS using Coolify.

Table of Contents

  1. Architecture Overview
  2. Prerequisites
  3. Coolify Setup
  4. Database Configuration
  5. Service Deployments
  6. Environment Variables Reference
  7. Domain & SSL Configuration
  8. Push Notifications Setup
  9. Post-Deployment Checklist
  10. Troubleshooting

Architecture Overview

                         ┌──────────────────────────────────────┐
                         │         Coolify Reverse Proxy        │
                         │           (Traefik/Caddy)            │
                         └────────────────┬─────────────────────┘
                                          │
         ┌────────────────────────────────┼────────────────────────────────┐
         │                                │                                │
         ▼                                ▼                                ▼
┌─────────────────┐              ┌─────────────────┐              ┌─────────────────┐
│    Frontend     │              │       PWA       │              │       CMS       │
│  (React+Vite)   │              │ (React+Vite+SW) │              │    (Strapi)     │
│    nginx:80     │              │    nginx:80     │              │   Node.js:1337  │
│ placebo.mk      │              │ app.placebo.mk  │              │ cms.placebo.mk  │
└────────┬────────┘              └────────┬────────┘              └────────┬────────┘
         │                                │                                │
         │                                │                                │
         │                                │                                │
         └────────────────────────────────┼────────────────────────────────┘
                                          │
                                          ▼
                                ┌─────────────────┐
                                │     Backend     │
                                │    (NestJS)     │
                                │   Node.js:3000  │
                                │ api.placebo.mk  │
                                └────────┬────────┘
                                         │
                                         ▼
                                ┌─────────────────┐
                                │   PostgreSQL    │
                                │     :5432       │
                                └─────────────────┘

Tech Stack

Service Technology Port Purpose
Frontend React 19 + Vite + Tailwind 80 Main website (SSG)
PWA React 19 + Vite + Workbox 80 Progressive Web App with push
Backend NestJS + TypeORM 3000 REST API
CMS Strapi 5 1337 Content management
Database PostgreSQL 16 5432 Primary data store

Prerequisites

Server Requirements

Resource Minimum Recommended
RAM 4GB 8GB
CPU 2 vCPU 4 vCPU
Storage 40GB SSD 80GB SSD
OS Ubuntu 22.04 Ubuntu 24.04

Domain Setup

Configure these DNS A records pointing to your VPS IP:

Type Name Purpose
A @ Main website (frontend)
A www WWW redirect
A api Backend API
A app PWA
A cms Strapi admin

Required Before Deployment

  • Coolify installed and accessible
  • Domain DNS configured
  • GitHub repository connected to Coolify
  • SMTP server (optional, for emails)

Coolify Setup

1. Create Project

  1. Login to Coolify dashboard
  2. Navigate to Projects
  3. Click + New Project
  4. Name: placebo
  5. Click Create

2. Create Environment

  1. Inside placebo project
  2. Click + New Environment
  3. Name: production
  4. Click Create

3. Connect Repository

  1. Go to ConfigurationSource
  2. Click Connect GitHub
  3. Authorize Coolify to access your repositories
  4. Select repository: your-org/placeboMk

Database Configuration

Create PostgreSQL Service

  1. In production environment, click + New Resource
  2. Select DatabasePostgreSQL
  3. Configure:
Setting Value
Name placebo-db
Version 16-alpine
PostgreSQL User placebo_user
PostgreSQL Password <generate-secure-password>
PostgreSQL Database placebo_db
Persistent Volume Enabled
  1. Click Deploy

Note Connection Details

After deployment, note the internal hostname:

Host: placebo-db
Port: 5432
Database: placebo_db
Username: placebo_user
Password: <your-password>

Service Deployments

1. Backend (NestJS API)

Create Service

  1. Click + New ResourceService
  2. Select Dockerfile (not Docker Compose)
  3. Name: placebo-backend
  4. Repository: Select your connected repo

Configuration

Setting Value
Dockerfile Location backend/Dockerfile
Build Context backend
Port 3000

Environment Variables

NODE_ENV=production
PORT=3000

# Database
DATABASE_TYPE=postgres
DATABASE_HOST=placebo-db
DATABASE_PORT=5432
DATABASE_USERNAME=placebo_user
DATABASE_PASSWORD=<your-db-password>
DATABASE_NAME=placebo_db
DATABASE_SYNCHRONIZE=false
DATABASE_LOGGING=false

# JWT Authentication
JWT_SECRET=<generate-64-char-secret>
JWT_EXPIRATION=86400

# CORS
CORS_ORIGIN=https://placebo.mk,https://www.placebo.mk,https://app.placebo.mk

# Strapi CMS
STRAPI_URL=https://cms.placebo.mk
STRAPI_API_TOKEN=<your-strapi-api-token>

# Push Notifications
VAPID_SUBJECT=mailto:contact@placebo.mk
VAPID_PUBLIC_KEY=<generated-public-key>
VAPID_PRIVATE_KEY=<generated-private-key>

Generate Secrets

JWT Secret:

openssl rand -base64 64 | tr -d '\n'

VAPID Keys (run locally):

cd backend
npm install
npm run generate-vapid

Health Check

Setting Value
Path /health
Interval 30s
Timeout 10s
Retries 3

Domain

  1. Go to Domains tab
  2. Add: api.placebo.mk
  3. Enable HTTPS (Let's Encrypt)

2. Frontend (Main Website)

Create Service

  1. Click + New ResourceServiceDockerfile
  2. Name: placebo-frontend

Configuration

Setting Value
Dockerfile Location frontend/Dockerfile
Build Context frontend
Port 80

Build Arguments

Vite requires environment variables at build time. Add these as Build Args:

VITE_API_URL=https://api.placebo.mk/api/v1
VITE_CMS_URL=https://cms.placebo.mk

Domain

  1. Add: placebo.mk
  2. Add: www.placebo.mk
  3. Enable HTTPS

3. PWA (Progressive Web App)

Create Service

  1. Click + New ResourceServiceDockerfile
  2. Name: placebo-pwa

Configuration

Setting Value
Dockerfile Location pwa/Dockerfile
Build Context pwa
Port 80

Build Arguments

VITE_API_URL=https://api.placebo.mk/api/v1
VITE_CMS_URL=https://cms.placebo.mk

Persistent Volume (Optional)

For service worker and cache:

  • Container Path: /usr/share/nginx/html
  • Host Path: pwa-dist

Domain

  1. Add: app.placebo.mk
  2. Enable HTTPS

4. CMS (Strapi)

Create Service

  1. Click + New ResourceServiceDockerfile
  2. Name: placebo-cms

Configuration

Setting Value
Dockerfile Location cms/cms/Dockerfile
Build Context cms/cms
Port 1337

Environment Variables

NODE_ENV=production
HOST=0.0.0.0
PORT=1337

# Database
DATABASE_CLIENT=postgres
DATABASE_HOST=placebo-db
DATABASE_PORT=5432
DATABASE_NAME=placebo_db
DATABASE_USERNAME=placebo_user
DATABASE_PASSWORD=<your-db-password>
DATABASE_SSL=false

# Security Keys (generate unique values for each)
APP_KEYS=<generate-4-keys>
API_TOKEN_SALT=<32-char-secret>
ADMIN_JWT_SECRET=<32-char-secret>
TRANSFER_TOKEN_SALT=<32-char-secret>
JWT_SECRET=<32-char-secret>

# CORS
CORS_ORIGIN=https://placebo.mk,https://app.placebo.mk,https://api.placebo.mk

Generate Strapi Keys

For APP_KEYS (4 comma-separated keys):

node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
# Run 4 times, join with commas

For other secrets:

openssl rand -base64 32

Persistent Volumes

Add these volumes for data persistence:

Container Path Purpose
/app/public/uploads Media uploads
/app/.tmp Temporary files

Domain

  1. Add: cms.placebo.mk
  2. Enable HTTPS

Environment Variables Reference

Backend

Variable Required Description
NODE_ENV Yes Set to production
DATABASE_HOST Yes PostgreSQL hostname
DATABASE_PORT Yes PostgreSQL port (5432)
DATABASE_USERNAME Yes Database username
DATABASE_PASSWORD Yes Database password
DATABASE_NAME Yes Database name
DATABASE_SYNCHRONIZE Yes Set to false in production
JWT_SECRET Yes 64+ character secret
CORS_ORIGIN Yes Comma-separated allowed origins
VAPID_PUBLIC_KEY Yes For push notifications
VAPID_PRIVATE_KEY Yes For push notifications
STRAPI_URL Yes CMS URL
STRAPI_API_TOKEN Yes API token from Strapi

Frontend/PWA (Build Args)

Variable Required Description
VITE_API_URL Yes Backend API URL
VITE_CMS_URL Yes CMS URL

CMS (Strapi)

Variable Required Description
APP_KEYS Yes 4 comma-separated 32-byte keys
API_TOKEN_SALT Yes Random 32-byte string
ADMIN_JWT_SECRET Yes Random 32-byte string
JWT_SECRET Yes Random 32-byte string
TRANSFER_TOKEN_SALT Yes Random 32-byte string

Domain & SSL Configuration

Configure Each Service

For each deployed service:

  1. Go to service → ConfigurationDomains
  2. Click Add Domain
  3. Enter domain (e.g., api.placebo.mk)
  4. Enable HTTPS
  5. Select Let's Encrypt
  6. Click Request Certificate

SSL Certificate Generation

Coolify automatically handles SSL via Let's Encrypt. Ensure:

  • DNS is properly configured
  • Port 80 and 443 are open
  • Domain is accessible from internet

Push Notifications Setup

1. Generate VAPID Keys

Run locally in the backend directory:

cd backend
npm install
npm run generate-vapid

Output:

Generating VAPID keys...
VAPID keys generated and added to .env file:
  Public Key: BIAna-ulT88Ek5ZdiAiXJikks3T5JEuZjBstuO7bEbUJ6RAoSmXAbum1Pf7JIbo-YQfwXM1Yi-rGTttOuNJUpUE
  Private Key: DGtRu68SmAxng-xx3BiTCa9NrztQbsSoECRuzry9VD4

2. Configure Backend

Add to backend environment variables:

VAPID_SUBJECT=mailto:contact@placebo.mk
VAPID_PUBLIC_KEY=<your-public-key>
VAPID_PRIVATE_KEY=<your-private-key>

3. Verify Setup

  1. Deploy backend with VAPID keys
  2. Visit: https://api.placebo.mk/api/v1/push/vapid-public-key
  3. Should return JSON with your public key

4. Test in PWA

  1. Open https://app.placebo.mk
  2. Wait for notification banner
  3. Click "Вклучи" (Enable)
  4. Accept browser permission
  5. Verify subscription in admin dashboard

Post-Deployment Checklist

Backend

  • Health check passing: https://api.placebo.mk/health
  • API docs accessible: https://api.placebo.mk/api/v1
  • Database connected (check logs)
  • JWT authentication working
  • CORS accepting frontend origins
  • Push notification endpoint working

Frontend

  • Site loads: https://placebo.mk
  • No console errors
  • API calls successful (check Network tab)
  • Images and assets loading
  • Navigation working correctly
  • Admin dashboard accessible

PWA

  • Site loads: https://app.placebo.mk
  • Service worker registered (DevTools → Application)
  • Install prompt appears
  • Notification banner shows
  • Push subscription successful
  • Works offline (cached resources)

CMS

  • Admin panel: https://cms.placebo.mk/admin
  • First admin user created
  • API token generated for backend
  • Media uploads working
  • Content types created

Troubleshooting

Backend Won't Start

Symptoms: Container keeps restarting

Solutions:

  1. Check logs: Coolify → Service → Logs
  2. Verify database connection:
    • DATABASE_HOST should be service name (e.g., placebo-db)
    • Check password matches database password
  3. Verify all required env vars are set
  4. Check JWT_SECRET is at least 32 characters

Frontend Shows Blank Page

Symptoms: Page loads but nothing displays

Solutions:

  1. Check browser console for errors
  2. Verify build args were set:
    • VITE_API_URL must be set at build time
  3. Check Network tab for failed API calls
  4. Rebuild with correct environment variables

CORS Errors

Symptoms: Browser blocks API requests

Solutions:

  1. Add all frontend domains to CORS_ORIGIN:
    CORS_ORIGIN=https://placebo.mk,https://www.placebo.mk,https://app.placebo.mk
    
  2. Restart backend after changing
  3. Clear browser cache

Push Notifications Not Working

Symptoms: Subscription fails or notifications don't arrive

Solutions:

  1. Verify HTTPS is enabled (required for push)
  2. Check VAPID keys are set in backend
  3. Test endpoint: /api/v1/push/vapid-public-key
  4. Check service worker is registered
  5. Verify browser notification permission is granted

Database Connection Issues

Symptoms: Backend can't connect to database

Solutions:

  1. Verify database service is running
  2. Check hostname matches database service name
  3. Verify credentials are correct
  4. Ensure both services are on the same network
  5. Check database logs for errors

CMS Admin Not Accessible

Symptoms: 404 or redirect loop on /admin

Solutions:

  1. Verify all Strapi secrets are set
  2. Check HOST=0.0.0.0 is set
  3. Clear browser cache and cookies
  4. Check CMS logs for startup errors

Maintenance

Updating Deployments

  1. Push changes to GitHub main branch
  2. Coolify → Service → Redeploy
  3. Or enable automatic deployments on push

Database Backups

  1. Coolify → Database → Backups
  2. Enable scheduled backups
  3. Recommended retention: 7-30 days
  4. Store backups off-server periodically

Log Management

  • View logs: Coolify → Service → Logs
  • Download logs: Available in service settings
  • Log rotation: Configured automatically

Monitoring

  1. Set up Coolify notifications for:
    • Service down
    • High resource usage
    • Deployment failures
  2. Monitor disk usage (uploads, logs)
  3. Check SSL certificate expiration

Security Checklist

  • All secrets are 32+ characters
  • HTTPS enabled on all services
  • Database not exposed to internet
  • CORS restricted to your domains only
  • CMS admin protected (consider IP whitelist)
  • Regular security updates applied
  • Backups configured and tested
  • Monitoring and alerts enabled

Support

For issues specific to: