agmission/Documents/DEPLOYMENT.md

9.8 KiB

AgMission Deployment Guide

Last updated: April 2026


Table of Contents


1 Prerequisites

Developer machine (deploying from):

  • SSH access to the production server on port 22222
  • rsync installed
  • SVN working copy at ~/work/AgMission
  • AGN private libraries at ~/work/@agn
  • Angular CLI for frontend builds (npm install -g @angular/cli)

Production server:

  • Node.js 16.20.2 LTS
  • PM2 (global): npm install -g pm2
  • MongoDB 4.4.x replica set (rs0)
  • RabbitMQ 3.10.7+
  • Redis
  • Nginx 1.10.x+

2 Repository and Directory Layout

Local developer machine

~/work/AgMission/
├── trunk/Development/      ← main line source
├── branches/<branch-name>/ ← feature branches
└── tags/release-x.y.z/    ← release snapshots

~/work/@agn/                ← private AGN Node.js libraries

Remote production server

/home/agm/apps/
├── agmission/              ← API server (server/)
├── client/dist/            ← Angular build output
├── gps-server/
├── track-server/
├── satloc/
├── maintainer/
├── pm2-apps/               ← PM2 JSON configs
└── @agn/                   ← private libs (rsync'd from ~/work/@agn)

3 Deployment Script Reference

Script: trunk/Others/scripts/deploy/agm-deploy.sh

Usage

./agm-deploy.sh [run_mode] [branch_name] [fe_mode]
Argument Values Default Description
run_mode 0, 1, 2 0 Deployment scope (see table below)
branch_name trunk, main, or branch name subscription-invoicing Source to deploy from
fe_mode run, dry-run run Frontend deploy behaviour (mode 2 only)
run_mode Backend Frontend Use case
0 (or empty) Dry run Dry run Verify what would be synced
1 Deploy Skipped Backend-only update
2 Deploy Deploy Full production deployment
# 1. Copy template
cp trunk/Others/scripts/deploy/agm-deploy.conf.template ~/.agm-deploy.conf

# 2. Edit values
nano ~/.agm-deploy.conf

# 3. Use it
source ~/.agm-deploy.conf && ./agm-deploy.sh 1 trunk

Environment variable overrides

Variable Default Description
AGM_BASE_DIR ~/work/AgMission Local AgMission SVN root
AGN_LIBS_DIR ~/work/@agn Local AGN private libraries
AGM_DEST_HOST agm@agmission-1.agnav.com SSH target (user@host)
AGM_DEST_PORT 22222 SSH port
AGM_DEST_PATH /home/agm/apps Remote base directory

4 Configuration

Excluded files

trunk/Others/scripts/deploy/excludes.txt lists paths excluded from rsync. These typically include:

  • node_modules/
  • .env / environment*.env (never overwrite production secrets)
  • .tmp/, job-unzip/, job-uploads/
  • Log files and rlog crash reports

Production environment files

Environment files are not deployed by the script. They must be maintained manually on the production server. See 9 Environment Variables Reference for key variables.


5 Deployment Modes

Dry run mode 0

./agm-deploy.sh 0 trunk

Shows all files that would be synced without touching the server. Always run this first when deploying after a significant code change.

Backend only mode 1

./agm-deploy.sh 1 trunk

Deploys:

  • server//home/agm/apps/agmission/
  • gps-server//home/agm/apps/gps-server/
  • track-server//home/agm/apps/track-server/
  • shared//home/agm/apps/shared/
  • @agn libraries → /home/agm/apps/@agn/

After sync, run pm2 reload on the server (see 7 PM2 Process Management).

Full deployment mode 2

./agm-deploy.sh 2 trunk

Deploys everything in mode 1, plus the Angular frontend client/dist/ to the Nginx webroot.

Before running mode 2, build the frontend locally:

cd trunk/Development/client
npm install
npm run build-prod     # builds all locales: en, pt, es

6 Step-by-Step Production Deployment

graph TD
    A["1. Update SVN working copy<br/>svn update trunk/"] --> B["2. Run tests<br/>cd server && npm test"]
    B --> C["3. Build frontend<br/>cd client && npm run build-prod"]
    C --> D["4. Dry run<br/>./agm-deploy.sh 0 trunk"]
    D --> E{"Review OK?"}
    E -- No --> F["Fix issues"]
    F --> D
    E -- Yes --> G["5. Deploy backend<br/>./agm-deploy.sh 1 trunk"]
    G --> H["6. SSH to server<br/>ssh agm@agmission-1.agnav.com -p 22222"]
    H --> I["7. Install dependencies<br/>cd /home/agm/apps/agmission && npm install --production"]
    I --> J["8. Reload PM2<br/>pm2 reload agmission-prod"]
    J --> K["9. Check logs<br/>pm2 logs agmission-prod --lines 50"]
    K --> L{"Errors?"}
    L -- Yes --> M["Rollback: pm2 reload with previous snapshot"]
    L -- No --> N["10. Deploy frontend (if needed)<br/>./agm-deploy.sh 2 trunk"]

Post-deployment checklist

  • pm2 status — all processes show online
  • pm2 logs agmission-prod --lines 20 — no crash errors
  • Health check endpoint: curl https://agmission-1.agnav.com/api/health
  • Login to the web UI and confirm dashboard loads
  • If partner workers were updated: pm2 reload partner_sync_worker partner_data_polling_worker
  • If worker code changed: check pm2 logs job_worker --lines 20

7 PM2 Process Management

Start all services first time

# SSH into server
ssh agm@agmission-1.agnav.com -p 22222

# Start all configured apps
/home/agm/apps/pm2-apps/start_pm2_apps.sh

Reload after deployment

# Reload individual app (zero-downtime)
pm2 reload agmission-prod

# Reload all at once
pm2 reload all

# Check status
pm2 status
pm2 logs agmission-prod --lines 30

Process list

pm2 list

Expected processes:

Name Status
agmission-prod online
track_server online
gps_server-agnav online
gps_server-rap online
job_worker online
invoice_worker online
cleanup_worker online
partner_sync_worker online
partner_data_polling_worker online

Restart a single worker

pm2 restart job_worker
pm2 restart partner_sync_worker
pm2 restart invoice_worker

Save current PM2 process list

pm2 save

8 Backup and Recovery

Automated backup

trunk/Others/scripts/backup_agm.sh runs via cron. It:

  1. Dumps MongoDB to a gzip archive (mongodump --gzip)
  2. Retains 11 days of database archives
  3. Syncs archives to NAS via rsync (rsync://rsync@data.agnav.com/agm/)
  4. Syncs uploaded job files separately
  5. Syncs rsync log files

Manual MongoDB backup

mongodump \
  --archive=/home/agm/backups/manual_$(date +%Y%m%d).gz \
  --gzip \
  --db agmission \
  --username agm \
  --authenticationDatabase agmission

Restore from backup

mongorestore \
  --archive=/home/agm/backups/agmdb_YYYYMMDD.gz \
  --gzip \
  --db agmission \
  --username agm \
  --authenticationDatabase agmission \
  --drop

9 Environment Variables Reference

Environment files live on the production server at /home/agm/apps/agmission/environment.env and are not managed by the deployment script.

Core server

Variable Description
AGM_PORT HTTP port the API server listens on (e.g., 7000)
PRODUCTION true in production
DB_USR / DB_PWD / DB_NAME MongoDB credentials
DB_HOSTS MongoDB host list (replica set)
DB_REPLSET Replica set name (rs0)
REDIS_PWD Redis password
JWT_SECRET JWT signing secret
MAX_SESSION_SECS Session token lifetime (default: 28800)

Stripe billing

Variable Description
STRIPE_SECRET_KEY Stripe secret key
STRIPE_PUBLISHABLE_KEY Stripe publishable key
STRIPE_API_VERSION Stripe API version
STRIPE_WH_SEC Stripe webhook signing secret
ESS_1ESS_5 Stripe price IDs for Essential plans
ENT_1ENT_4 Stripe price IDs for Enterprise plans
ADDON_1 Stripe price ID for add-on

File storage

Variable Description
UPLOAD_DIR Job upload directory
UNZIP_DIR Temp extraction directory
INV_UPLOAD_DIR Invoice image upload directory
INV_IMG_VIR_DIR Virtual URL path for invoice images
SATLOC_STORAGE_PATH Local storage for downloaded SatLoc log files

RabbitMQ

Variable Description
QUEUE_HOST RabbitMQ host
QUEUE_PORT RabbitMQ port (default: 5672)
QUEUE_USR / QUEUE_PWD RabbitMQ credentials
QUEUE_VHOST Virtual host
QUEUE_NAME_JOBS Job processing queue name
QUEUE_NAME_GDATA GPS data queue name
QUEUE_NAME_PARTNER Partner tasks queue name

Partner integration

Variable Description
SATLOC_API_ENDPOINT SatLoc Cloud base URL
SATLOC_API_TIMEOUT HTTP request timeout (ms)
PARTNER_SYNC_INTERVAL Partner sync interval (ms)
PARTNER_HEALTH_CHECK_INTERVAL Health check interval (ms)
PARTNER_MAX_RETRIES Max retry attempts before DLQ
DLQ_CHECK_INTERVAL DLQ monitoring interval (ms)

See ARCHITECTURE.md for full system design documentation.