# Namecheap VPS Deployment Checklist

This checklist deploys the Ascend ERP / IDURAR MERN application on a Namecheap VPS with a production database.

The app has two deployable parts:

- **Backend API:** Express + Mongoose, runs on Node.js 20, default port `8888`.
- **Frontend app:** React/Vite build, served as static files.

Recommended production shape:

```mermaid
flowchart LR
  User["User Browser"] --> HTTPS["HTTPS Domain"]
  HTTPS --> Frontend["Static Frontend: app.yourdomain.com"]
  Frontend --> API["Backend API: api.yourdomain.com"]
  API --> Mongo["MongoDB Database"]
  API --> PM2["PM2 Process Manager"]
  API --> Workers["Automation / Agent Workers"]
```

## 1. Decide Your Hosting Layout

Use one of these layouts.

### Option A: Same VPS, Separate Subdomains

Recommended for most first production deployments.

- Frontend: `https://app.yourdomain.com`
- Backend API: `https://api.yourdomain.com`
- Database: MongoDB on the same VPS or MongoDB Atlas

### Option B: Main Domain And API Subdomain

- Frontend: `https://yourdomain.com`
- Backend API: `https://api.yourdomain.com`

### Option C: cPanel Node.js App

Use this only if your cPanel installation supports Node.js app management. For a VPS, PM2 is usually cleaner and more reliable.

## 2. Prepare Namecheap VPS

Checklist:

- [ ] Buy or open your Namecheap VPS.
- [ ] Install AlmaLinux, Rocky Linux, Ubuntu, or another supported Linux OS.
- [ ] If using cPanel/WHM, complete WHM setup.
- [ ] Point your domain DNS to the VPS IP.
- [ ] Create DNS records:
  - [ ] `app.yourdomain.com` -> VPS IP
  - [ ] `api.yourdomain.com` -> VPS IP
- [ ] Enable SSH access.
- [ ] Log in as root or a sudo user.

Example SSH:

```bash
ssh root@YOUR_SERVER_IP
```

## 3. Update Server Packages

For Ubuntu/Debian:

```bash
sudo apt update
sudo apt upgrade -y
```

For AlmaLinux/Rocky/CentOS:

```bash
sudo dnf update -y
```

## 4. Install Required Server Tools

Install basic tools:

Ubuntu/Debian:

```bash
sudo apt install -y git curl wget unzip nano build-essential
```

AlmaLinux/Rocky/CentOS:

```bash
sudo dnf install -y git curl wget unzip nano gcc gcc-c++ make
```

## 5. Install Node.js 20 And npm

This project requires Node.js 20+.

Using NodeSource on Ubuntu/Debian:

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

Using NodeSource on AlmaLinux/Rocky/CentOS:

```bash
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo dnf install -y nodejs
node -v
npm -v
```

Expected:

- Node: `20.x`
- npm: `10.x` or newer

## 6. Install PM2

PM2 keeps the backend running after SSH disconnects and restarts it after reboot.

```bash
sudo npm install -g pm2
pm2 -v
```

Enable PM2 startup:

```bash
pm2 startup
```

Run the command PM2 prints after `pm2 startup`.

## 7. Choose Database Option

You can use local MongoDB on the VPS or MongoDB Atlas.

### Option A: MongoDB Atlas

Recommended if you want managed backups and easier maintenance.

Checklist:

- [ ] Create MongoDB Atlas cluster.
- [ ] Create database user.
- [ ] Whitelist VPS IP address.
- [ ] Copy connection string.
- [ ] Use it as `DATABASE` in backend `.env`.

Example:

```env
DATABASE=mongodb+srv://USERNAME:PASSWORD@cluster0.xxxxx.mongodb.net/ascend_erp?retryWrites=true&w=majority
```

### Option B: Local MongoDB On VPS

Use this if you want the database on the same server.

Install MongoDB according to your Linux distribution, then enable it:

```bash
sudo systemctl enable mongod
sudo systemctl start mongod
sudo systemctl status mongod
```

Create a database user:

```bash
mongosh
```

Inside Mongo shell:

```javascript
use ascend_erp
db.createUser({
  user: "ascend_user",
  pwd: "CHANGE_THIS_STRONG_PASSWORD",
  roles: [{ role: "readWrite", db: "ascend_erp" }]
})
exit
```

Use this connection string:

```env
DATABASE=mongodb://ascend_user:CHANGE_THIS_STRONG_PASSWORD@127.0.0.1:27017/ascend_erp
```

Security checklist for local MongoDB:

- [ ] Bind MongoDB to `127.0.0.1` unless external access is required.
- [ ] Enable MongoDB authentication.
- [ ] Block public access to port `27017`.
- [ ] Configure daily backups.

## 8. Upload Or Clone The App

Recommended deployment directory:

```bash
sudo mkdir -p /var/www/ascend-erp
sudo chown -R $USER:$USER /var/www/ascend-erp
cd /var/www/ascend-erp
```

Clone your repository:

```bash
git clone YOUR_REPOSITORY_URL .
```

If you upload a zip instead:

```bash
unzip idurar-erp-crm-master.zip -d /var/www/ascend-erp
```

Confirm folders exist:

```bash
ls
```

Expected folders:

- `backend`
- `frontend`
- `docs`

## 9. Configure Backend Environment

Go to backend:

```bash
cd /var/www/ascend-erp/backend
cp .env.example .env
nano .env
```

Production backend `.env` example:

```env
NODE_ENV=production
PORT=8888
DATABASE=mongodb://ascend_user:CHANGE_THIS_STRONG_PASSWORD@127.0.0.1:27017/ascend_erp
JWT_SECRET=CHANGE_THIS_TO_A_LONG_RANDOM_SECRET_AT_LEAST_24_CHARS
INTEGRATION_ENCRYPTION_KEY=CHANGE_THIS_TO_ANOTHER_LONG_RANDOM_SECRET_AT_LEAST_24_CHARS
CORS_ALLOWED_ORIGINS=https://app.yourdomain.com,https://yourdomain.com
TRUST_PROXY=true
JSON_BODY_LIMIT=1mb
URLENCODED_BODY_LIMIT=1mb
AUTH_RATE_LIMIT_WINDOW_MS=900000
AUTH_RATE_LIMIT_MAX=20
API_RATE_LIMIT_WINDOW_MS=60000
API_RATE_LIMIT_MAX=600
AUTOMATION_WORKER_ENABLED=true
AUTOMATION_WORKER_INTERVAL_MS=30000
AUTOMATION_WORKER_LIMIT=10
AGENT_WORKER_ENABLED=true
AGENT_WORKER_INTERVAL_MS=15000
AGENT_WORKER_LIMIT=5
AI_USD_NGN_RATE=1600
```

Optional provider keys:

```env
OPENAI_API_KEY=
KIMI_API_KEY=
HERMES_API_KEY=
HERMES_API_URL=
RESEND_API=
META_ACCESS_TOKEN=
META_WHATSAPP_PHONE_NUMBER_ID=
FAL_KEY=
```

Generate strong secrets:

```bash
openssl rand -base64 48
openssl rand -base64 48
```

Checklist:

- [ ] `NODE_ENV=production`
- [ ] `DATABASE` points to MongoDB.
- [ ] `JWT_SECRET` is strong.
- [ ] `INTEGRATION_ENCRYPTION_KEY` is strong.
- [ ] `CORS_ALLOWED_ORIGINS` includes the frontend domain.
- [ ] `TRUST_PROXY=true` when behind Apache/Nginx/cPanel proxy.
- [ ] Worker flags are enabled if automations/agents should process automatically.

## 10. Install Backend Dependencies

```bash
cd /var/www/ascend-erp/backend
npm install
```

Run a startup syntax/env check:

```bash
node src/server.js
```

If it starts successfully, stop it with:

```bash
CTRL+C
```

Common errors:

- Missing `DATABASE`
- Weak `JWT_SECRET`
- Missing `CORS_ALLOWED_ORIGINS` in production
- Missing `INTEGRATION_ENCRYPTION_KEY` in production
- MongoDB connection refused

## 11. Run Backend Setup

Run the setup script once:

```bash
cd /var/www/ascend-erp/backend
npm run setup
```

This creates the initial admin user from the existing setup script.

Production setup credentials must come from environment variables:

```text
SETUP_ADMIN_EMAIL=owner@yourdomain.com
SETUP_ADMIN_PASSWORD=use-a-strong-temporary-password
```

Important production checklist:

- [ ] Set `SETUP_ADMIN_EMAIL` and `SETUP_ADMIN_PASSWORD` before running setup.
- [ ] Log in immediately after deployment.
- [ ] Change the temporary setup password.
- [ ] Create any additional real admin users.
- [ ] Confirm demo mode is disabled on the frontend.
- [ ] Set up roles and permissions.

## 12. Start Backend With PM2

```bash
cd /var/www/ascend-erp/backend
pm2 start src/server.js --name ascend-erp-api
pm2 save
```

Check status:

```bash
pm2 status
pm2 logs ascend-erp-api
```

Test backend locally:

```bash
curl http://127.0.0.1:8888/healthz
```

Expected response:

```json
{
  "success": true
}
```

## 13. Configure Backend Domain Proxy

The backend should be reachable at:

```text
https://api.yourdomain.com
```

### If Using cPanel/WHM With Apache Reverse Proxy

Checklist:

- [ ] Create the subdomain `api.yourdomain.com` in cPanel/WHM.
- [ ] Enable SSL for the subdomain.
- [ ] Configure Apache/Nginx reverse proxy to forward to `127.0.0.1:8888`.
- [ ] Restart web server.

Proxy target:

```text
http://127.0.0.1:8888
```

### If Using Nginx Manually

Create config:

```bash
sudo nano /etc/nginx/sites-available/api.yourdomain.com
```

Example:

```nginx
server {
    listen 80;
    server_name api.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8888;
        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;
    }
}
```

Enable:

```bash
sudo ln -s /etc/nginx/sites-available/api.yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```

Add SSL with Certbot if not using cPanel SSL:

```bash
sudo certbot --nginx -d api.yourdomain.com
```

Test:

```bash
curl https://api.yourdomain.com/healthz
```

## 14. Configure Frontend Environment

Go to frontend:

```bash
cd /var/www/ascend-erp/frontend
cp .env.example .env
nano .env
```

Production frontend `.env`:

```env
VITE_BACKEND_SERVER=https://api.yourdomain.com/
VITE_DEMO_MODE=false
```

Checklist:

- [ ] `VITE_BACKEND_SERVER` ends with `/`.
- [ ] It points to the public backend domain.
- [ ] Demo mode is false.

## 15. Build Frontend

```bash
cd /var/www/ascend-erp/frontend
npm install
npm run build
```

Build output:

```text
frontend/dist
```

## 16. Serve Frontend With cPanel Or Nginx

### Option A: cPanel Static Hosting

Checklist:

- [ ] Create `app.yourdomain.com` in cPanel.
- [ ] Enable SSL.
- [ ] Upload contents of `frontend/dist` into the document root for `app.yourdomain.com`.
- [ ] Confirm `index.html` is at the document root.
- [ ] Add SPA fallback so React routes work.

For Apache, create `.htaccess` in the frontend document root:

```apache
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>
```

### Option B: Nginx Static Hosting

Copy build:

```bash
sudo mkdir -p /var/www/app.yourdomain.com
sudo cp -r /var/www/ascend-erp/frontend/dist/* /var/www/app.yourdomain.com/
```

Create config:

```bash
sudo nano /etc/nginx/sites-available/app.yourdomain.com
```

Example:

```nginx
server {
    listen 80;
    server_name app.yourdomain.com;
    root /var/www/app.yourdomain.com;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, max-age=2592000";
    }
}
```

Enable:

```bash
sudo ln -s /etc/nginx/sites-available/app.yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d app.yourdomain.com
```

## 17. Update Backend CORS After Frontend Domain Is Final

Edit backend `.env`:

```bash
cd /var/www/ascend-erp/backend
nano .env
```

Set:

```env
CORS_ALLOWED_ORIGINS=https://app.yourdomain.com,https://yourdomain.com
```

Restart backend:

```bash
pm2 restart ascend-erp-api
```

## 18. Configure Firewall

Recommended open ports:

- `22` SSH
- `80` HTTP
- `443` HTTPS
- cPanel/WHM ports if using cPanel

Do not expose:

- `8888` backend port publicly
- `27017` MongoDB publicly

Ubuntu UFW example:

```bash
sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
sudo ufw status
```

If using cPanel/WHM, configure firewall through CSF/WHM as appropriate.

## 19. First Login And App Setup

Open:

```text
https://app.yourdomain.com
```

Checklist:

- [ ] Log in with setup admin.
- [ ] Change default password.
- [ ] Create real admin users.
- [ ] Assign roles and branch access.
- [ ] Revoke default sessions if needed.
- [ ] Configure company workspace.
- [ ] Confirm default currency is NGN.
- [ ] Configure tax, payment modes, PDF settings, branches, and users.
- [ ] Add provider API keys in AI Studio / Provider Accounts if needed.
- [ ] Create or import products, customers, and opening stock.

## 20. Test Core Production Flows

Authentication:

- [ ] Login works.
- [ ] Logout works.
- [ ] Password reset/setup link works.
- [ ] User sessions can be viewed and revoked.

Dashboard:

- [ ] Dashboard loads.
- [ ] Money values show NGN.

CRM:

- [ ] Create contact.
- [ ] Create lead.
- [ ] Submit public load calculator.
- [ ] Lead appears in CRM.

Sales/Finance:

- [ ] Create quote.
- [ ] Create invoice.
- [ ] Record payment.
- [ ] Reconcile payment.

Inventory/POS:

- [ ] Create product.
- [ ] Create branch stock.
- [ ] Open POS session.
- [ ] Complete checkout.
- [ ] Stock decreases.
- [ ] Receipt/reprint works.

Marketing/AI/Automation:

- [ ] Open AI Studio.
- [ ] Configure provider account or confirm mock mode.
- [ ] Generate content.
- [ ] Open Automations.
- [ ] Run due jobs.
- [ ] Check notification drawer.

Reports/Exports:

- [ ] Reports overview loads.
- [ ] POS export works.
- [ ] Invoice/payment export works.

## 21. Database Backup Checklist

For MongoDB Atlas:

- [ ] Enable automated backups.
- [ ] Confirm restore process.
- [ ] Restrict network access.

For local MongoDB:

Create backup folder:

```bash
sudo mkdir -p /backups/mongodb
sudo chown -R $USER:$USER /backups/mongodb
```

Manual backup:

```bash
mongodump --uri="mongodb://ascend_user:CHANGE_THIS_STRONG_PASSWORD@127.0.0.1:27017/ascend_erp" --out=/backups/mongodb/$(date +%F)
```

Add cron backup:

```bash
crontab -e
```

Example daily backup at 2 AM:

```cron
0 2 * * * mongodump --uri="mongodb://ascend_user:CHANGE_THIS_STRONG_PASSWORD@127.0.0.1:27017/ascend_erp" --archive=/backups/mongodb/ascend_erp_$(date +\%F).archive --gzip
```

Retention example:

```cron
30 2 * * * find /backups/mongodb -type f -mtime +14 -delete
```

## 22. Update Deployment Checklist

When deploying new code:

```bash
cd /var/www/ascend-erp
git pull
```

Backend update:

```bash
cd /var/www/ascend-erp/backend
npm install
pm2 restart ascend-erp-api
pm2 logs ascend-erp-api
```

Frontend update:

```bash
cd /var/www/ascend-erp/frontend
npm install
npm run build
sudo rm -rf /var/www/app.yourdomain.com/*
sudo cp -r dist/* /var/www/app.yourdomain.com/
```

Smoke test:

- [ ] `https://api.yourdomain.com/healthz`
- [ ] `https://app.yourdomain.com`
- [ ] Login
- [ ] Dashboard
- [ ] One CRM list
- [ ] One finance action
- [ ] One POS/report page

## 23. Troubleshooting

### Backend Does Not Start

Check:

```bash
pm2 logs ascend-erp-api
```

Likely causes:

- Missing `.env`
- Invalid MongoDB URL
- Weak `JWT_SECRET`
- Missing `INTEGRATION_ENCRYPTION_KEY`
- Missing production `CORS_ALLOWED_ORIGINS`
- Wrong Node.js version

### Frontend Cannot Reach Backend

Check:

- [ ] `VITE_BACKEND_SERVER` is correct.
- [ ] Backend domain has SSL.
- [ ] Backend `/healthz` returns success.
- [ ] CORS includes frontend domain.
- [ ] Browser console does not show mixed-content errors.

### Login Fails

Check:

- [ ] Backend is running.
- [ ] MongoDB is connected.
- [ ] Setup script was run.
- [ ] User is enabled.
- [ ] Password is correct.
- [ ] Session was not revoked.

### React Routes Show 404 On Refresh

Fix SPA fallback:

- Apache/cPanel: add `.htaccess`.
- Nginx: use `try_files $uri $uri/ /index.html;`.

### MongoDB Connection Refused

Check:

```bash
sudo systemctl status mongod
```

Check database URL:

```bash
cd /var/www/ascend-erp/backend
cat .env
```

Make sure MongoDB is running and authentication details are correct.

## 24. Final Go-Live Checklist

- [ ] DNS points correctly.
- [ ] SSL works for frontend and backend.
- [ ] Backend health check works.
- [ ] Frontend loads.
- [ ] Demo mode is disabled.
- [ ] Default admin password changed.
- [ ] Real admin users created.
- [ ] CORS locked to production domains.
- [ ] MongoDB is backed up.
- [ ] Firewall blocks backend and database public ports.
- [ ] PM2 startup is saved.
- [ ] Provider keys configured or intentionally left in mock/disabled mode.
- [ ] POS, CRM, finance, AI, automation, reports, and settings smoke-tested.
