>_
EngineeringNotes
Module 06

Deploying a Monorepo

From localhost to production: handling multiple apps, databases, and environment variables.

00

Prerequisites

Before you deploy, you need to have a monorepo set up correctly with Turbo Repo. If you haven't done that yet, check out our guide on creating one.

Go to: Creating a Monorepo using Turbo
01

Environment Variables

Managing .env files is critical. In production, your apps won't have the .env file you use locally (since it's gitignored). You need to add it manually to your server.

Note: Manually creating `.env` files on servers is fine for beginners and small projects. However, for larger production systems, you should use Secret Managers (like AWS Secrets Manager, HashiCorp Vault, or GitHub Secrets for CI/CD injection).

How to add .env manually

After cloning your repo on the server, navigate to your project folder and create the file:

Terminal (Server)
bash
# 1. Open editor
vi .env

# 2. Paste your variables
# Press 'i' to insert mode -> Paste content -> Press 'Esc' -> Type ':wq' -> Enter
.env content example
env
DATABASE_URL="postgres://user:password@localhost:5432/mydb"
NEXTAUTH_SECRET="your-super-secret-key"
PORT=3000
02

The High-Level Strategy

Here is the roadmap for a robust deployment:

  • 01.Deploy Monorepo: Handle http-server, websocket-server, Prisma, Postgres, and Next.js frontend.
  • 02.Env Variables: Securely configure secrets.
  • 03.Environments: Separate Prod (stable) vs. Dev (bleeding edge) + Periodic releases.
  • 04.CI Testing: Run tests in pipelines before merging.
  • 05.Cert Management: SSL/TLS for secure HTTPS connections.
  • 06.CD Pipeline (Certs): Refresh certs automatically every month.
  • 07.CD Pipeline (DB): Copy Prod DB to Dev daily (sanitized) for realistic testing.
03

Execution Steps

Step 1: Create Servers

Provision 2 servers (e.g., AWS EC2 instances). One for Production and one for Staging.

Why separate servers? We should maintain different servers for dev/staging and production. You do not want to disturb your stable production environment with continuous testing and updates happening on the dev server. While you can use a single server for both, it is not a good idea for reliability.

Step 2: Server Setup

On both servers, install the necessary runtime and tools.

Node.js: The runtime environment for executing JavaScript.

We recommend using NVM (Node Version Manager) as per our AWS guide:

Terminal
bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash && source ~/.bashrc && nvm install v24.13.0

Nginx: Reverse proxy to handle incoming requests.

Terminal
bash
sudo apt update && sudo apt install nginx -y

Step 3: Clone & Database

Clone your monorepo to both servers. Since we usually use a managed database (RDS/Neon) or a separate container for DB, ensure connectivity.

- If hosting DB on the same server (not recommended for scale): Install Postgres.

Step 4: Start Processes (PM2)

Use PM2 (Process Manager 2) to keep your services alive forever.

First, install PM2 globally:

Terminal
bash
npm install -g pm2

Then start your applications:

Terminal
bash
# Example PM2 commands
pm2 start apps/http-server/dist/index.js --name "http-api"
pm2 start apps/ws-server/dist/index.js --name "ws-server"
pm2 start apps/web/server.js --name "frontend" # If using custom Next.js server

Step 5: Point Domain Names

Configure your DNS provider to point subdomains to your server IPs.

Production

http.yourdomain.com

ws.yourdomain.com

fe.yourdomain.com

Staging

staging.http.yourdomain.com

staging.ws.yourdomain.com

staging.fe.yourdomain.com

Step 6: Refresh Nginx Config

Update your Nginx config (`/etc/nginx/sites-available/default`) to proxy traffic from these subdomains to the correct local ports (e.g., 3000, 3001, 8080).

Step 7: Test Everything

Verify that: