Skip to main content

Hosting Infrastructure

Related docs: SDLC/DEPLOYMENT · CI/CD Pipeline · Microservices


1. Environment Topology

The Pakashop infrastructure is split into two identical stacks (Staging and Production) to ensure safe testing before going live.

ComponentStaging Environment (main)Production Environment (production)
FrontendVercel (Staging)Vercel (Production)
Backend APIAWS EC2 (Staging)AWS EC2 (Production)
DatabaseRDS PostgreSQL (Staging)RDS PostgreSQL (Production)
RedisEC2 Redis (Staging)EC2 Redis (Production)
SearchMeilisearch (Staging EC2)Meilisearch (Production EC2)
CDN/DNS/WAFCloudflareCloudflare

2. EC2 Infrastructure

Both Staging and Production EC2 instances run Ubuntu 22.04 LTS with Nginx as a reverse proxy.

2.1 Process Management (systemd)

All 19 services are managed by systemd unit files located in /etc/systemd/system/.

ServiceUnit NamePortLanguage
API Gatewaypakashop-gateway.service8000Node.js
Backend APIpakashop-backend.service3080Node.js
Configpakashop-config.service3085Node.js
Notificationspakashop-notifications.service3090Node.js
Trackingpakashop-tracking.service3120Node.js
Schedulerpakashop-scheduler.service3004Node.js
Fraudpakashop-fraud.service3006Node.js
Couponpakashop-coupon.service3008Node.js
Loyaltypakashop-loyalty.service3010Node.js
WhatsApppakashop-whatsapp.service3009Node.js
Reportspakashop-reports.service3011Node.js
Reconciliationpakashop-reconciliation.service3012Node.js
Invoicingpakashop-invoicing.service3013Node.js
Pricingpakashop-pricing.service3014Node.js
Settlementpakashop-settlement.service3016Node.js
Searchpakashop-search.service3005Go
Analyticspakashop-analytics.service3007Go
Moderationpakashop-moderation.service3110Python
Recommendationspakashop-recommendations.service3100Python

2.2 Example systemd Unit File

# /etc/systemd/system/pakashop-backend.service
[Unit]
Description=Pakashop Backend API
After=network.target postgresql.service redis.service
Wants=postgresql.service redis.service

[Service]
Type=simple
User=deploy
Group=deploy
WorkingDirectory=/opt/pakashop/services/backend
Environment=NODE_ENV=production
EnvironmentFile=/opt/pakashop/.env.production
ExecStart=/usr/bin/node src/index.js
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=pakashop-backend

# Resource limits
LimitNOFILE=65536

# Security hardening (commented out until tested)
# NoNewPrivileges=true
# ProtectSystem=strict
# ProtectHome=true
# ReadWritePaths=/opt/pakashop/services/backend/tmp

[Install]
WantedBy=multi-user.target

2.3 Nginx Configuration

# /etc/nginx/sites-available/pakashop
upstream gateway {
server 127.0.0.1:8000;
}

server {
listen 443 ssl http2;
server_name pakashop.store www.pakashop.store;

ssl_certificate /etc/ssl/certs/pakashop.crt;
ssl_certificate_key /etc/ssl/private/pakashop.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;

# WebSocket support for tracking
location /api/v1/tracking/ws {
proxy_pass http://gateway;
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_read_timeout 86400;
}

# SSE support for notifications
location /api/v1/notifications/stream {
proxy_pass http://gateway;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 86400;
}

# All other API requests
location /api/ {
proxy_pass http://gateway;
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;
proxy_set_header X-Internal-Key $http_x_internal_key;

# Rate limiting
limit_req zone=api burst=100 nodelay;
limit_req_status 429;
}

# Static assets (if served from EC2)
location /static/ {
alias /opt/pakashop/frontend/public/;
expires 1y;
add_header Cache-Control "public, immutable";
}

# Health check endpoint (bypass auth)
location /health {
proxy_pass http://gateway;
access_log off;
}
}

# Redirect HTTP to HTTPS
server {
listen 80;
server_name pakashop.store www.pakashop.store;
return 301 https://$server_name$request_uri;
}

3. Deployment and Branch Mapping

  • Staging: Deployed automatically when code is pushed to the main branch.
  • Production: Deployed automatically when code is pushed to the production branch.

All deployments use the centralized scripts/deploy.sh script, which is branch-aware and pulls the latest code from the branch currently checked out on the host.


4. Environment Files

4.1 Production Environment (/opt/pakashop/.env.production)

# Database
DATABASE_URL=postgresql://user:pass@pakashop-prod.cluster-xxx.us-east-1.rds.amazonaws.com:5432/pakashop
DIRECT_DATABASE_URL=postgresql://user:pass@localhost:5432/pakashop

# Redis
REDIS_URL=redis://localhost:6379

# Meilisearch
MEILISEARCH_URL=http://localhost:7700
MEILISEARCH_API_KEY=master_key

# JWT
JWT_SECRET=xxx
TOTP_ENCRYPTION_KEY=xxx

# Gateway keys
PAKASHOP_CLIENT_KEY=xxx
INTERNAL_API_KEY=xxx

# Payment providers
PAYMENT_PROVIDER=AUTO
PAWAPAY_API_KEY=xxx
PAWAPAY_BASE_URL=https://api.pawapay.io
PAWAPAY_WEBHOOK_SECRET=xxx
FLUTTERWAVE_SECRET_KEY=FLWSECK-xxx
FLUTTERWAVE_SECRET_HASH=xxx
FLUTTERWAVE_BASE_URL=https://api.flutterwave.com/v3
FLUTTERWAVE_REDIRECT_URL=https://pakashop.store/payment/callback

# Email
RESEND_API_KEY=xxx
ZOHO_MAIL_PASSWORD=xxx

# Cloudinary
CLOUDINARY_CLOUD_NAME=xxx
CLOUDINARY_API_KEY=xxx
CLOUDINARY_API_SECRET=xxx

# Content moderation
SIGHTENGINE_API_USER=xxx
SIGHTENGINE_API_SECRET=xxx

# WhatsApp
WHATSAPP_BUSINESS_ID=xxx
TWILIO_ACCOUNT_SID=xxx
TWILIO_AUTH_TOKEN=xxx

# ZRA
ZRA_VSDC_API_KEY=xxx
ZRA_MOCK_MODE=false

# Observability
MIDDLEWARE_API_KEY=xxx
ENABLE_OBSERVABILITY=true

# Feature flags
FEATURE_FLAGS_REDIS_KEY=pakashop:feature_flags

4.2 Deployment User

The deploy user on EC2 has limited privileges:

# /etc/sudoers.d/deploy
deploy ALL=(ALL) NOPASSWD: /bin/systemctl restart pakashop-*
deploy ALL=(ALL) NOPASSWD: /bin/systemctl reload nginx
deploy ALL=(ALL) NOPASSWD: /opt/pakashop/scripts/deploy.sh

5. Security Hardening

5.1 EC2 Security Groups

PortProtocolSourcePurpose
22TCPOffice IP onlySSH access
80TCP0.0.0.0/0HTTP redirect
443TCP0.0.0.0/0HTTPS traffic
6379TCPVPC onlyRedis (no external access)
5432TCPVPC onlyPostgreSQL (no external access)
7700TCPVPC onlyMeilisearch (no external access)

5.2 Cloudflare Configuration

  • SSL/TLS: Full (strict) — encrypts traffic between Cloudflare and origin
  • WAF: OWASP Top 10 rules enabled
  • DDoS Protection: Always on
  • Bot Management: Challenge suspicious traffic
  • Page Rules: Cache static assets, bypass cache for API

5.3 systemd Sandboxing (Optional)

For enhanced security, uncomment the following in each systemd unit file:

NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/pakashop/services/<service>/tmp
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictRealtime=true
RestrictSUIDSGID=true

Note: Test thoroughly before enabling in production. Some services may require additional ReadWritePaths for temporary file storage.


6. Maintenance and Monitoring

  • Logs: All environments ship logs to journald. Live logs can be viewed with journalctl -u <unit> -f.
  • Health Checks: Middleware.io monitors both Staging and Production stacks with separate environment tags.
  • Status Dashboard: Use ./scripts/pakashop-status.sh on either host to see a color-coded status of all local services.
  • Backups: Nightly automated database backups to S3 via GitHub Actions (db-backup.yml).

For internal use only. Do not distribute outside Pakashop engineering.