mirror of
https://git.meshkee.com/Meshkee/backend.git
synced 2026-08-11 22:30:59 +04:30
Initial commit: Meshkee CMS API
NestJS backend with Prisma, Docker Compose for Postgres/Redis, and deploy docs for the production VM.
This commit is contained in:
+178
@@ -0,0 +1,178 @@
|
||||
# Deploy Meshkee CMS API (Debian VM)
|
||||
|
||||
Stack: Docker (Postgres + Redis) → Node build on server → PM2 → Nginx + Let's Encrypt.
|
||||
|
||||
App path on server: `/opt/meshkee/app`
|
||||
|
||||
API domain: `api.meshkee.com` → `https://api.meshkee.com/api/v1`
|
||||
|
||||
> **Note:** Until the Git remote is accessible from the VM (deploy key / credentials), updates can be synced with `rsync` from your laptop. Pin `sharp@0.33.5` — this VM CPU lacks x64-v2 required by sharp 0.35+.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Debian VM with SSH access
|
||||
- Domain `A` record pointing at the VM (for HTTPS)
|
||||
- Git remote with this codebase (private repo → deploy key)
|
||||
- Production secrets (JWT, Postgres password, S3 keys)
|
||||
|
||||
## 1. Server packages
|
||||
|
||||
```bash
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
sudo apt install -y ca-certificates curl gnupg git nginx ufw
|
||||
|
||||
# Docker
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
sudo apt update
|
||||
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||||
sudo usermod -aG docker "$USER"
|
||||
# log out/in (or newgrp docker) so docker works without sudo
|
||||
|
||||
# Node.js 20 LTS
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
||||
sudo apt install -y nodejs
|
||||
sudo npm install -g pm2
|
||||
|
||||
# Certbot (after Nginx is installed)
|
||||
sudo apt install -y certbot python3-certbot-nginx
|
||||
```
|
||||
|
||||
Firewall:
|
||||
|
||||
```bash
|
||||
sudo ufw allow OpenSSH
|
||||
sudo ufw allow 'Nginx Full'
|
||||
sudo ufw --force enable
|
||||
```
|
||||
|
||||
## 2. Clone the app
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/meshkee
|
||||
sudo chown "$USER:$USER" /opt/meshkee
|
||||
cd /opt/meshkee
|
||||
git clone <YOUR_GIT_REMOTE_URL> app
|
||||
cd app
|
||||
```
|
||||
|
||||
Private repo: create an SSH deploy key on the VM (`ssh-keygen -t ed25519 -C "meshkee-deploy"`), add the public key as a read-only deploy key on GitHub/GitLab, clone via SSH URL.
|
||||
|
||||
## 3. Production env
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env # set strong secrets — never commit this file
|
||||
```
|
||||
|
||||
Required production values:
|
||||
|
||||
- Strong `POSTGRES_PASSWORD` and matching `DATABASE_URL`
|
||||
- Long random `JWT_ACCESS_SECRET` / `JWT_REFRESH_SECRET`
|
||||
- Real `S3_ACCESS_KEY_ID` / `S3_SECRET_ACCESS_KEY`
|
||||
- `PORT=3000`
|
||||
- `SMS_ENABLED` as needed
|
||||
|
||||
## 4. Database + Redis
|
||||
|
||||
```bash
|
||||
cd /opt/meshkee/app
|
||||
docker compose up -d
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
First Postgres volume init runs SQL under `database/migrations/` automatically.
|
||||
|
||||
Later schema updates:
|
||||
|
||||
```bash
|
||||
./database/migrate.sh
|
||||
```
|
||||
|
||||
## 5. Build and run (on the server)
|
||||
|
||||
```bash
|
||||
cd /opt/meshkee/app
|
||||
npm ci
|
||||
npm run prisma:generate
|
||||
npm run build
|
||||
```
|
||||
|
||||
Production seed (super admin only — skip sample data):
|
||||
|
||||
```bash
|
||||
./database/seed.sh database/seeds/002_super_admin_user.sql
|
||||
# optional reference data:
|
||||
# ./database/seed.sh database/seeds/004_iran_cities.sql
|
||||
# ./database/seed.sh database/seeds/005_business_categories.sql
|
||||
```
|
||||
|
||||
Start with PM2:
|
||||
|
||||
```bash
|
||||
pm2 start ecosystem.config.js
|
||||
pm2 save
|
||||
pm2 startup # run the command it prints (usually with sudo)
|
||||
```
|
||||
|
||||
Health check locally on the VM:
|
||||
|
||||
```bash
|
||||
curl -s http://127.0.0.1:3000/api/v1/ | head
|
||||
# or hit a known public route such as tenant resolve
|
||||
```
|
||||
|
||||
## 6. Nginx + HTTPS
|
||||
|
||||
Create `/etc/nginx/sites-available/meshkee-api`:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name api.example.com; # replace with your domain
|
||||
|
||||
client_max_body_size 15M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
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 and get a certificate:
|
||||
|
||||
```bash
|
||||
sudo ln -sf /etc/nginx/sites-available/meshkee-api /etc/nginx/sites-enabled/
|
||||
sudo rm -f /etc/nginx/sites-enabled/default
|
||||
sudo nginx -t && sudo systemctl reload nginx
|
||||
sudo certbot --nginx -d api.example.com
|
||||
```
|
||||
|
||||
API base URL: `https://api.example.com/api/v1`
|
||||
|
||||
## Ongoing updates
|
||||
|
||||
```bash
|
||||
cd /opt/meshkee/app
|
||||
git pull
|
||||
./database/migrate.sh # if there are new SQL migrations
|
||||
npm ci
|
||||
npm run prisma:generate
|
||||
npm run build
|
||||
pm2 restart meshkee-api
|
||||
```
|
||||
|
||||
## Useful commands
|
||||
|
||||
```bash
|
||||
pm2 status
|
||||
pm2 logs meshkee-api
|
||||
docker compose logs -f postgres
|
||||
```
|
||||
Reference in New Issue
Block a user