Files
app/docs/deployment-guide.md
2026-03-24 19:59:14 +01:00

8.9 KiB

Deployment Guide — boha-app-ts (Ubuntu Server)

Migration from PHP boha-app to TypeScript boha-app-ts on the same Ubuntu server. Both apps share the same MySQL database. The PHP app stays running during migration.


Prerequisites

  • Ubuntu server with the PHP boha-app already running
  • nginx with SSL (Let's Encrypt) already configured
  • MySQL database already running with production data
  • NAS storage mounted (e.g., /mnt/nas/02_PROJEKTY)
  • SSH access to the server

Phase 1: Prepare on Dev Machine (Windows)

1.1 Create Prisma migration baseline

cd D:\cortex\boha-app-ts
mkdir -p prisma/migrations/0_init
npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql
npx prisma migrate resolve --applied 0_init
git add prisma/migrations/
git commit -m "chore: create Prisma migration baseline"

1.2 Build the application

npm run build

This creates:

  • dist/ — compiled server (Node.js)
  • dist-client/ — compiled frontend (static files)

1.3 Generate new production secrets

openssl rand -hex 32
# Save this as JWT_SECRET

openssl rand -hex 32
# Save this as TOTP_ENCRYPTION_KEY (only if you want a new key)

1.4 Test the production build locally (optional)

APP_ENV=production JWT_SECRET=<your-dev-key> TOTP_ENCRYPTION_KEY=<your-dev-key> DATABASE_URL=<your-dev-db> node dist/server.js

Verify it starts and responds at http://localhost:3001/api/health.


Phase 2: Prepare Ubuntu Server

2.1 Install Node.js 22

curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
node -v
npm -v

2.2 Install PM2

sudo npm install -g pm2

2.3 Create application directory

sudo mkdir -p /var/www/boha-app-ts
sudo chown $USER:$USER /var/www/boha-app-ts

Phase 3: Transfer Files to Server

3.1 Copy built files

From your Windows machine (Git Bash or PowerShell with SCP):

scp -r dist/ dist-client/ package.json package-lock.json prisma/ scripts/ .env.example user@server:/var/www/boha-app-ts/

Or use rsync if available:

rsync -avz --exclude node_modules --exclude .env dist/ dist-client/ package.json package-lock.json prisma/ scripts/ .env.example user@server:/var/www/boha-app-ts/

3.2 Install production dependencies on server

ssh user@server
cd /var/www/boha-app-ts
npm install --production
npx prisma generate

Phase 4: Configure Environment

4.1 Create production .env

cd /var/www/boha-app-ts
cp .env.example .env
nano .env

Fill in:

# Database — same as the PHP app
DATABASE_URL=mysql://user:password@localhost:3306/your_db_name

# Server
PORT=3001
HOST=127.0.0.1
APP_ENV=production

# Auth — use the NEW secrets generated in step 1.3
JWT_SECRET=<paste-new-jwt-secret>
ACCESS_TOKEN_EXPIRY=900
REFRESH_TOKEN_SESSION_EXPIRY=3600
REFRESH_TOKEN_REMEMBER_EXPIRY=2592000

# TOTP — use SAME key as PHP app (unless you want to re-encrypt)
TOTP_ENCRYPTION_KEY=<same-key-as-php-app>

# NAS — Linux mount point
NAS_PATH=/mnt/nas/02_PROJEKTY
MAX_UPLOAD_SIZE=52428800

# Email
CONTACT_EMAIL_TO=manager@boha-automation.cz
CONTACT_EMAIL_FROM=web@boha-automation.cz
SMTP_FROM=noreply@boha-automation.cz

# CORS — your production domain(s)
CORS_ORIGINS=https://app.boha-automation.cz,https://www.boha-automation.cz

Important decisions:

Setting Recommendation
JWT_SECRET New key. All PHP sessions will be invalid — users re-login. This is expected.
TOTP_ENCRYPTION_KEY Same key as PHP app. Avoids re-encrypting all TOTP secrets.
DATABASE_URL Same database as PHP app. Both apps share it.
NAS_PATH Linux mount point instead of Windows drive letter.

Phase 5: Database Setup

5.1 Mark Prisma baseline as applied

cd /var/www/boha-app-ts
npx prisma migrate resolve --applied 0_init

This tells Prisma the database already has all tables. No SQL is executed.

5.2 Verify database connection

npx prisma db pull --print | head -20

Should show your existing tables.


Phase 6: TOTP Key Rotation (only if using new encryption key)

Skip this section if you're using the same TOTP_ENCRYPTION_KEY as the PHP app.

If you generated a new encryption key:

cd /var/www/boha-app-ts

# Dry run — verify all secrets can be decrypted and re-encrypted
npx tsx scripts/rotate-totp-key.ts <old-key> <new-key> --dry-run

# If all [OK], run for real
npx tsx scripts/rotate-totp-key.ts <old-key> <new-key>

After this, the PHP app's TOTP verification will break (secrets are now encrypted with the new key). Only do this when you're ready to cut over.


Phase 7: Start Application with PM2

7.1 Create PM2 config

cd /var/www/boha-app-ts
cat > ecosystem.config.js << 'EOF'
module.exports = {
  apps: [{
    name: 'boha-app-ts',
    script: 'dist/server.js',
    cwd: '/var/www/boha-app-ts',
    instances: 1,
    env: {
      NODE_ENV: 'production',
    },
  }]
};
EOF

7.2 Start the app

pm2 start ecosystem.config.js
pm2 save
pm2 startup
# Follow the printed command to enable auto-start on boot

7.3 Verify

pm2 status
pm2 logs boha-app-ts --lines 20
curl http://localhost:3001/api/health

Expected: {"status":"ok","timestamp":"..."}


Phase 8: Nginx Configuration

8.1 Create nginx config

sudo nano /etc/nginx/sites-available/boha-app-ts

Paste:

server {
    listen 443 ssl http2;
    server_name app.boha-automation.cz;

    ssl_certificate /etc/letsencrypt/live/app.boha-automation.cz/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.boha-automation.cz/privkey.pem;

    client_max_body_size 55M;

    location / {
        proxy_pass http://127.0.0.1:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

server {
    listen 80;
    server_name app.boha-automation.cz;
    return 301 https://$host$request_uri;
}

Adjust server_name and SSL paths to match your setup.

8.2 Enable and reload

sudo ln -s /etc/nginx/sites-available/boha-app-ts /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Phase 9: Testing

9.1 Verify in browser

Open https://app.boha-automation.cz and test:

  • Login page loads
  • Login works (users will need to re-login due to new JWT_SECRET)
  • TOTP verification works (if using same encryption key)
  • Dashboard loads with data
  • Offers — list, create, edit, PDF export
  • Orders — list, create from offer, status transitions
  • Invoices — list, create, PDF with QR code
  • Projects — list, create, file manager (upload/download)
  • Attendance — clock in/out, admin view, print
  • Trips — list, history
  • Settings — company settings, users, roles

9.2 Check logs for errors

pm2 logs boha-app-ts --lines 50

Phase 10: Cutover Strategy

Both apps run simultaneously on the same database. Recommended approach:

  1. Week 1: Run both apps. Use the TS app for daily work. Fall back to PHP if issues arise.
  2. Week 2: If stable, redirect the main domain to the TS app.
  3. Week 3: Stop the PHP app.

To redirect the PHP domain to the TS app, update the nginx config for the PHP domain to proxy to port 3001 instead.


Future Updates

When you push code changes:

# On dev machine
npm run build
git push

# On server
cd /var/www/boha-app-ts
git pull
npm install --production
npx prisma generate
npx prisma migrate deploy    # runs any new migrations
pm2 restart boha-app-ts

Troubleshooting

Problem Solution
EADDRINUSE: port 3001 pm2 stop boha-app-ts then pm2 start
Prisma connection error Check DATABASE_URL in .env
TOTP verification fails Verify TOTP_ENCRYPTION_KEY matches the key used to encrypt secrets
NAS files not accessible Check mount: ls /mnt/nas/02_PROJEKTY, verify permissions
502 Bad Gateway App not running: pm2 status, check logs: pm2 logs
CSS/JS not loading Verify dist-client/ was copied, check APP_ENV=production
CORS errors Check CORS_ORIGINS in .env matches your domain exactly

Quick Reference

Command Purpose
pm2 start ecosystem.config.js Start the app
pm2 restart boha-app-ts Restart after update
pm2 stop boha-app-ts Stop the app
pm2 logs boha-app-ts View logs
pm2 monit Live monitoring
npx prisma migrate deploy Apply database migrations
npx prisma studio Database GUI (dev only)