# VerifyPack — Single EC2 (Ubuntu) Deployment Everything on **one Ubuntu EC2 instance**: MongoDB + FastAPI backend + Next.js frontend, with Nginx as the public reverse proxy. Because MongoDB runs on the same box, it binds to `127.0.0.1` and is **never exposed to the internet** — no DB port in the security group. ``` Internet ──443──> Nginx ──┬── / → Next.js (localhost:3000) └── /api/* , etc → FastAPI (localhost:8000) FastAPI ──> MongoDB (localhost:27017) ``` --- ## 0. Provision the instance - **AMI:** Ubuntu Server 22.04 LTS - **Type:** t3.small minimum (t3.medium recommended — Mongo + Node build need RAM) - **Storage:** 30 GB gp3 - **Security Group inbound:** - `22` (SSH) — your IP only - `80` (HTTP) — anywhere - `443` (HTTPS) — anywhere - **Do NOT open 27017, 8000, or 3000.** They stay local. - Allocate an **Elastic IP** and point your domain's A records at it: - `app.yourdomain.com` → EIP - `api.yourdomain.com` → EIP (or serve API under `app.../api` — see Nginx below) SSH in: ```bash ssh -i your-key.pem ubuntu@ ``` --- ## 1. Base packages ```bash sudo apt update && sudo apt upgrade -y sudo apt install -y git nginx python3-venv python3-pip build-essential curl ufw ``` ### Firewall (defense in depth) ```bash sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' sudo ufw enable ``` --- ## 2. Install MongoDB 7.0 ```bash curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \ sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | \ sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list sudo apt update sudo apt install -y mongodb-org sudo systemctl enable --now mongod sudo systemctl status mongod # should be active (running) ``` Mongo listens on `127.0.0.1:27017` by default — leave it that way. ### (Recommended) enable auth on MongoDB ```bash mongosh ``` ```javascript use admin db.createUser({ user: "vpadmin", pwd: "", roles: [ { role: "root", db: "admin" } ] }) exit ``` Turn on auth: ```bash sudo sed -i 's/#security:/security:\n authorization: enabled/' /etc/mongod.conf sudo systemctl restart mongod ``` Your connection string becomes: `mongodb://vpadmin:@127.0.0.1:27017/?authSource=admin` --- ## 3. Install Node 20 (for the frontend) ```bash curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt install -y nodejs node --version # v20.x ``` --- ## 4. Get the code onto the box ```bash sudo mkdir -p /opt/verifypack && sudo chown ubuntu:ubuntu /opt/verifypack cd /opt/verifypack # either git clone your repo, or scp the "verify pack" folder up: # scp -i key.pem -r "verify pack" ubuntu@:/opt/verifypack/ ``` Assume the result is `/opt/verifypack/backend` and `/opt/verifypack/frontend`. --- ## 5. Backend (FastAPI) ```bash cd /opt/verifypack/backend python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt gunicorn cp .env.example .env nano .env ``` Set in `backend/.env`: ```env ENVIRONMENT=production SECRET_KEY=<32+ random chars — run: openssl rand -hex 32> FRONTEND_URL=https://app.yourdomain.com MONGODB_URL=mongodb://vpadmin:@127.0.0.1:27017/?authSource=admin MONGODB_DB=verifypack MOCK_DB=0 MOCK_EMAIL=0 MOCK_STORAGE=0 AWS_REGION=ap-south-1 AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... SES_FROM_EMAIL=no-reply@yourdomain.com S3_BUCKET=verifypack-uploads GOOGLE_CLIENT_ID=... GOOGLE_CLIENT_SECRET=... GOOGLE_REDIRECT_URI=https://api.yourdomain.com/auth/google/callback RAZORPAY_KEY_ID=... RAZORPAY_KEY_SECRET=... RAZORPAY_WEBHOOK_SECRET=... GST_RATE=0.18 ``` > To run fully offline first (DB only, no AWS/Razorpay), set `MOCK_EMAIL=1 MOCK_STORAGE=1` > and leave the cloud keys blank — the app still boots. Seed once: ```bash python -m app.db.seed ``` Install the systemd service (file provided in `deploy/verifypack-backend.service`): ```bash sudo cp /opt/verifypack/deploy/verifypack-backend.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now verifypack-backend sudo systemctl status verifypack-backend curl localhost:8000/health # {"status":"ok",...,"mock_db":false} ``` --- ## 6. Frontend (Next.js) ```bash cd /opt/verifypack/frontend npm ci cp .env.local.example .env.local nano .env.local ``` Set: ```env NEXT_PUBLIC_API_URL=https://api.yourdomain.com NEXT_PUBLIC_APP_URL=https://app.yourdomain.com ``` Build & install service: ```bash npm run build sudo cp /opt/verifypack/deploy/verifypack-frontend.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now verifypack-frontend sudo systemctl status verifypack-frontend curl localhost:3000 # HTML returned ``` --- ## 7. Nginx reverse proxy ```bash sudo cp /opt/verifypack/deploy/nginx-verifypack.conf /etc/nginx/sites-available/verifypack sudo ln -s /etc/nginx/sites-available/verifypack /etc/nginx/sites-enabled/ sudo rm -f /etc/nginx/sites-enabled/default sudo nginx -t && sudo systemctl reload nginx ``` ### HTTPS with Let's Encrypt ```bash sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d app.yourdomain.com -d api.yourdomain.com # auto-renew is installed as a systemd timer ``` --- ## 8. Updating after a code change ```bash cd /opt/verifypack && git pull # or re-scp # backend cd backend && source .venv/bin/activate && pip install -r requirements.txt sudo systemctl restart verifypack-backend # frontend cd ../frontend && npm ci && npm run build sudo systemctl restart verifypack-frontend ``` --- ## 9. Logs & ops ```bash sudo journalctl -u verifypack-backend -f # backend logs sudo journalctl -u verifypack-frontend -f # frontend logs sudo systemctl status mongod ``` Mongo backup (cron nightly): ```bash mongodump --uri="mongodb://vpadmin:@127.0.0.1:27017/verifypack?authSource=admin" \ --out /opt/backups/$(date +\%F) ``` --- ## 10. Single-instance security recap - 27017 / 8000 / 3000 are **localhost only** — never in the security group. - MongoDB auth enabled; strong `SECRET_KEY`; seeded admin password changed. - TLS via certbot; HTTP redirects to HTTPS. - `ufw` allows only SSH + Nginx. - Consider snapshots/EBS backups + the nightly `mongodump`.