Overview
This guide covers everything needed to deploy the MaqAgr API to production, from environment configuration to database setup and containerization.
Environment Variables
The API requires several environment variables to be configured. Create a .env file in the project root:
Required Variables
Port number where the Express server will listen
NODE_ENV
string
default: "development"
Environment mode: development, production, or test Affects:
Error detail exposure (hidden in production)
Log verbosity (debug in dev, info in prod)
CORS settings
DB_HOST
string
default: "localhost"
PostgreSQL database host address
PostgreSQL database password (REQUIRED)
Secret key for signing JWT tokens (min 32 characters recommended) Generate a strong secret:
JWT token expiration time Examples: 1h, 24h, 7d, 30d
TEST_DB_NAME
string
default: "maqagr_test"
Separate database for integration tests (optional)
Example .env File
# Server Configuration
PORT = 4000
NODE_ENV = production
# Database Configuration
DB_HOST = localhost
DB_PORT = 5432
DB_NAME = MaqAgr
DB_USER = postgres
DB_PASS = your_secure_password_here
# JWT Configuration
JWT_SECRET = your_super_secure_jwt_secret_min_32_chars_recommended
JWT_EXPIRES_IN = 24h
# Redis Configuration (optional)
REDIS_HOST = localhost
REDIS_PORT = 6379
Security:
Never commit .env files to version control
Use strong, randomly generated passwords and secrets
Rotate JWT secrets periodically in production
Use environment-specific values (separate dev/staging/prod)
Database Setup
Prerequisites
Install PostgreSQL
Install PostgreSQL 12 or higher: Ubuntu/Debian
macOS
Windows
sudo apt update
sudo apt install postgresql postgresql-contrib
Create Database
Create the production database: # Connect to PostgreSQL
sudo -u postgres psql
# Create database
CREATE DATABASE MaqAgr ;
# Create user (optional)
CREATE USER maqagr_user WITH PASSWORD 'secure_password' ;
GRANT ALL PRIVILEGES ON DATABASE MaqAgr TO maqagr_user ;
# Exit
\q
Import Schema
Import the database schema and initial data: # From project root
psql -d MaqAgr -f docs/dbSetting/users_202601311817.sql
psql -d MaqAgr -f docs/dbSetting/tractor_202601311817.sql
psql -d MaqAgr -f docs/dbSetting/implement_202601311817.sql
psql -d MaqAgr -f docs/dbSetting/terrain_202601311817.sql
psql -d MaqAgr -f database/indexes.sql
If you created a custom user, add the -U flag: psql -U maqagr_user -d MaqAgr -f docs/dbSetting/users_202601311817.sql
Verify Tables
Verify that tables were created: psql -d MaqAgr
# List all tables
\dt
# Should show:
# - users
# - roles
# - tractors
# - implements
# - terrains
# - calculations
# - recommendations
Database Indexes
Ensure performance indexes are created:
-- User authentication
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_role_id ON users(role_id);
-- Tractors
CREATE INDEX idx_tractors_brand ON tractors(brand);
CREATE INDEX idx_tractors_power ON tractors(power);
-- Terrains
CREATE INDEX idx_terrains_user_id ON terrains(user_id);
CREATE INDEX idx_terrains_soil_type ON terrains(soil_type);
-- Calculations
CREATE INDEX idx_calculations_user_id ON calculations(user_id);
CREATE INDEX idx_calculations_created_at ON calculations(created_at DESC );
Redis Setup (Optional)
Redis is used for caching and rate limiting:
Use the provided docker-compose.yml: version : '3.8'
services :
redis :
image : redis:alpine
container_name : redis_cache
restart : always
ports :
- "6379:6379"
volumes :
- redis_data:/data
volumes :
redis_data :
Start Redis: Ubuntu/Debian
macOS
Windows
sudo apt install redis-server
sudo systemctl start redis
sudo systemctl enable redis
Installation
Clone Repository
git clone https://github.com/David9604/BackMaqagr.git
cd BackMaqagr
Configure Environment
cp .env.example .env
# Edit .env with your production values
nano .env
Setup Database
# Create database and import schema (see Database Setup above)
createdb MaqAgr
psql -d MaqAgr -f docs/dbSetting/users_202601311817.sql
# ... import remaining SQL files
Production Deployment
Using PM2 (Recommended)
PM2 is a production process manager for Node.js:
Start Application
pm2 start src/app.js --name maqagr-api
Configure Auto-Restart
# Save PM2 process list
pm2 save
# Generate startup script
pm2 startup
Monitor
# View logs
pm2 logs maqagr-api
# Monitor resources
pm2 monit
# View process list
pm2 list
PM2 Ecosystem File
Create ecosystem.config.js for advanced configuration:
module . exports = {
apps: [{
name: 'maqagr-api' ,
script: './src/app.js' ,
instances: 2 ,
exec_mode: 'cluster' ,
env: {
NODE_ENV: 'production' ,
PORT: 4000
},
error_file: './logs/pm2-error.log' ,
out_file: './logs/pm2-out.log' ,
log_date_format: 'YYYY-MM-DD HH:mm:ss Z' ,
merge_logs: true ,
max_memory_restart: '500M'
}]
};
Deploy:
pm2 start ecosystem.config.js
Docker Deployment
Create a Dockerfile for containerized deployment:
FROM node:24-alpine
# Create app directory
WORKDIR /usr/src/app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application code
COPY . .
# Expose port
EXPOSE 4000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD node -e "require('http').get('http://localhost:4000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
# Start application
CMD [ "node" , "src/app.js" ]
Full Docker Compose
version : '3.8'
services :
api :
build : .
container_name : maqagr-api
restart : always
ports :
- "4000:4000"
environment :
- NODE_ENV=production
- DB_HOST=postgres
- DB_PORT=5432
- DB_NAME=MaqAgr
- DB_USER=postgres
- DB_PASS=${DB_PASS}
- JWT_SECRET=${JWT_SECRET}
- REDIS_HOST=redis
depends_on :
- postgres
- redis
networks :
- maqagr-network
postgres :
image : postgres:14-alpine
container_name : maqagr-postgres
restart : always
environment :
- POSTGRES_DB=MaqAgr
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=${DB_PASS}
volumes :
- postgres_data:/var/lib/postgresql/data
- ./docs/dbSetting:/docker-entrypoint-initdb.d
networks :
- maqagr-network
redis :
image : redis:alpine
container_name : maqagr-redis
restart : always
volumes :
- redis_data:/data
networks :
- maqagr-network
volumes :
postgres_data :
redis_data :
networks :
maqagr-network :
driver : bridge
Deploy:
# Build and start all services
docker-compose up -d
# View logs
docker-compose logs -f api
# Stop all services
docker-compose down
Reverse Proxy (Nginx)
Configure Nginx as reverse proxy:
/etc/nginx/sites-available/maqagr-api
server {
listen 80 ;
server_name api.maqagr.com;
# Redirect to HTTPS
return 301 https://$ server_name $ request_uri ;
}
server {
listen 443 ssl http2;
server_name api.maqagr.com;
# SSL certificates (use Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/api.maqagr.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.maqagr.com/privkey.pem;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# API proxy
location / {
proxy_pass http://localhost:4000;
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 ;
}
# Rate limiting
limit_req_zone $ binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req zone=api_limit burst=20 nodelay;
}
Enable site:
sudo ln -s /etc/nginx/sites-available/maqagr-api /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Health Checks
The API includes a health check endpoint:
curl http://localhost:4000/health
Response:
{
"status" : "ok" ,
"timestamp" : "2026-03-11T10:30:00.000Z" ,
"uptime" : 3600 ,
"database" : "connected" ,
"redis" : "connected"
}
Monitoring & Logging
Log Files
Logs are stored in the logs/ directory:
logs/
├── combined.log # All logs
├── error.log # Errors only
├── app-2026-03-11.log # Daily rotation
└── app-2026-03-10.log.gz # Compressed archives
Log Rotation
Logs automatically rotate daily and keep 14 days of history.
Monitoring with PM2
# Real-time monitoring
pm2 monit
# CPU and memory usage
pm2 status
# Application logs
pm2 logs maqagr-api --lines 100
Security Checklist
Troubleshooting
Database Connection Fails
Check database credentials and connectivity: # Test PostgreSQL connection
psql -h localhost -U postgres -d MaqAgr
# Check if PostgreSQL is running
sudo systemctl status postgresql
# View API logs
pm2 logs maqagr-api
# Find process using port 4000
lsof -i :4000
# Kill process
kill -9 < PI D >
# Or change PORT in .env
# Check if Redis is running
redis-cli ping
# Should return: PONG
# Start Redis
sudo systemctl start redis
# Or with Docker:
docker-compose up -d redis
Configure PM2 memory limit: pm2 restart maqagr-api --max-memory-restart 500M
Testing Run tests before deployment
Error Handling Monitor errors in production