GoGrab Infrastructure - Complete Guide
Complete guide to the GoGrab infrastructure
GoGrab Infrastructure - Complete Guide
Last Updated: February 19, 2026 Author: Infrastructure audit performed during Railway consolidation (Sessions 110+) Purpose: Single source of truth for understanding the entire GoGrab project infrastructure
Overview
GoGrab is a full-stack Angular 20 + NestJS platform running as an NX monorepo. The infrastructure is distributed across several cloud providers, each handling a specific responsibility:
| Layer | Provider | What It Does |
|---|---|---|
| DNS & CDN | Cloudflare | Domain routing, caching, SSL, DDoS protection |
| Frontend Hosting | Cloudflare Pages | Static site deployment for all Angular apps |
| Backend Hosting | Railway | Docker containers for all NestJS API services |
| Database | MongoDB Atlas | 3 clusters for app data, docs, and Vitto |
| File/Media Storage | Cloudflare R2 | Object storage (S3-compatible) for files, images, audio |
| Cache | Railway Redis | In-memory caching shared across backend services |
| Google Workspace | Gmail for gograb.space domain | |
| Error Tracking | Sentry | Frontend and backend error monitoring |
| Messaging | Twilio | WhatsApp/SMS for channel management |
| AI Providers | OpenAI, Anthropic, Google | LLM APIs for AI features |
| MCP Intelligence | mcp-gograb-ai | Development decision tracking and agent collaboration |
1. Domain & DNS (Cloudflare)
Dashboard: https://dash.cloudflare.com/5723867b831b303313524ffda92b71ea
Account ID: 5723867b831b303313524ffda92b71ea
Domain: gograb.space
Nameservers: colin.ns.cloudflare.com / kara.ns.cloudflare.com
Cloudflare is the authoritative DNS for gograb.space. All traffic flows through Cloudflare first. This means:
- All DNS records are managed in Cloudflare (not cPanel, not the registrar)
- HTTPS/SSL certificates are automatically provisioned by Cloudflare
- CDN caching is applied to all proxied requests
- DDoS protection is always active
Key DNS Records
| Record | Type | Target | Purpose |
|---|---|---|---|
gograb.space |
A/CNAME | Cloudflare Pages | Main website |
api.gograb.space |
CNAME | euesp4um.up.railway.app |
Backend API |
ai-api.gograb.space |
CNAME | z11ouvom.up.railway.app |
AI Backend API |
vitto-api.gograb.space |
CNAME | Railway | Vitto Backend API |
docs-api.gograb.space |
CNAME | Railway | Docs Backend API |
pulse.gograb.space |
CNAME | Cloudflare Pages | Pulse music player |
@ (MX) |
MX | ASPMX.L.GOOGLE.COM |
Gmail/Google Workspace |
Email (Google Workspace / Gmail)
Email for gograb.space is handled by Google Workspace. This is configured entirely through MX records in Cloudflare:
Priority 1: ASPMX.L.GOOGLE.COM
Priority 5: ALT1.ASPMX.L.GOOGLE.COM
Priority 5: ALT2.ASPMX.L.GOOGLE.COM
Priority 10: ALT3.ASPMX.L.GOOGLE.COM
Priority 10: ALT4.ASPMX.L.GOOGLE.COM
Gmail depends ONLY on these Cloudflare MX records. It does NOT depend on cPanel or any hosting provider.
2. Frontend Hosting (Cloudflare Pages)
All Angular frontend applications are deployed as static sites to Cloudflare Pages. Each app has its own Pages project with a custom domain.
Frontend Applications
| App | Pages Project | Custom Domain | Deploy Script |
|---|---|---|---|
| GoGrab Space | gograb-space | gograb.space | deployment/cloudflare/deploy-space-admin.sh |
| Admin Panel | gograb-admin | admin.gograb.space | deployment/cloudflare/deploy-admin.sh |
| Dev Tools | gograb-dev | dev.gograb.space | deployment/cloudflare/deploy-dev.sh |
| AI Dashboard | gograb-ai | ai.gograb.space | deployment/cloudflare/deploy-ai.sh |
| Docs | gograb-docs | docs.gograb.space | deployment/cloudflare/deploy-docs.sh |
| Pulse Player | gograb-pulse | pulse.gograb.space | deployment/cloudflare/deploy-pulse.sh |
| Landing Page | gograb-landing | (varies) | deployment/cloudflare/deploy-gograb-landing.sh |
Deployment method: Direct upload via Cloudflare API (deployment/cloudflare/deploy-to-cloudflare.js)
GitHub Actions: .github/workflows/deploy-*.yml for CI/CD
3. Backend Hosting (Railway)
All NestJS backend services run as Docker containers on Railway, now consolidated into a single project.
Railway Project (Consolidated)
Project Name: GoGrab
Project ID: 3990549d-4313-47e4-9682-d17b382bdba2
Environment ID: 1d438b60-52d5-4c89-ba8f-45fff0df308f
Dashboard: https://railway.com/project/3990549d-4313-47e4-9682-d17b382bdba2
Services
| Service | Service ID | Domain | Port | Health Check |
|---|---|---|---|---|
| backend-api | 1ad0b79a-b722-4c69-920c-5dcb35978f0d |
api.gograb.space | 3000 | /api/health |
| backend-ai-api | fa00811a-db8e-4232-a23f-2becd96615c7 |
ai-api.gograb.space | 3001 | /ai-api/health |
| backend-docs-api | 0f7af191-d7a4-4366-82b6-312c4ab8fa7e |
docs-api.gograb.space | 3002 | /docs-api/health |
| backend-vitto-api | 072352ed-2e34-468e-bec9-03f6d299f867 |
vitto-api.gograb.space | 3003 | /vitto-api/health |
| Redis | (managed service) | Internal only | 6379 | N/A |
Deployment Flow
Each service has a dedicated deploy branch and directory:
deployment/
├── backend-api/
│ ├── railway.toml # Canonical Railway config
│ ├── Dockerfile.railway # Docker build instructions
│ ├── deploy.sh # Manual deploy script
│ └── README.md
├── backend-ai-api/ # Same structure
├── backend-docs-api/ # Same structure
├── backend-vitto-api/ # Same structure
├── cli/ # Smart deploy CLI tool
│ └── lib/deployment-config.js # All service configurations
├── cloudflare/ # Frontend deploy scripts
├── docs/ # Deployment documentation
└── history/ # Deployment logs
Deploy branches: deploy/api, deploy/ai-api, deploy/docs-api, deploy/vitto-api
Deploy CLI: node deployment/cli/deploy.js <service-name>
Port Configuration
Source of truth: .env.local — NEVER hardcode localhost ports.
| Context | Space | Admin | Dev | Docs | AI |
|---|---|---|---|---|---|
| editor2 (dev) | 5200 | 5100 | 5300 | 5010 | 5400 |
| gspace1 (dev) | 6200 | 6100 | 6300 | 6010 | 6400 |
| Production | 3000 | 3001 | 3002 | 3003 | N/A |
Import ports from @libs-foundational/api-config, never hardcode.
4. Database (MongoDB Atlas)
Three separate MongoDB Atlas clusters handle different data domains:
| Cluster | Connection String Env Var | Purpose |
|---|---|---|
| gograb-api | MONGODB_URI |
Main app data (users, spaces, auth, pulse songs) |
| gograb-docs | MONGODB_URI_DOCS |
Documentation system data |
| vitto-mind | MONGODB_URI_VITTO |
Vitto AI agent memory and tools |
All connection strings are stored in .env.local and injected as Railway environment variables in production.
5. File & Media Storage (Cloudflare R2)
Dashboard: https://dash.cloudflare.com/5723867b831b303313524ffda92b71ea/r2/overview
S3 API Endpoint: https://5723867b831b303313524ffda92b71ea.r2.cloudflarestorage.com
Current Buckets
| Bucket | Objects | Size | Purpose |
|---|---|---|---|
pulse-music |
22 | 95.82 MB | MP3 audio files for Pulse player |
Why R2?
- Zero egress fees — no bandwidth charges for downloads (unlike AWS S3)
- S3-compatible API — use standard
@aws-sdk/client-s3SDK - Global CDN — files served from Cloudflare's edge network
- Custom domains — can serve from
cdn.gograb.spaceor similar - Already integrated — Pulse player already uses R2 successfully
R2 Integration Pattern (from Pulse)
The existing Pulse implementation provides a proven pattern:
- Upload:
sync-pulse-music.sh --source <path> --r2uploads files to R2 - Metadata: Song metadata stored in MongoDB via
/api/pulse/songsendpoint - Serving: Files served directly from R2 public URLs (r2.dev domain)
- CORS Note: Do NOT use
crossorigin="anonymous"on audio/media elements from R2 — use no-cors mode
Recommended: General-Purpose File Storage
For general file uploads (images, documents, user content), create a new bucket:
Bucket name: gograb-assets (or gograb-uploads)
Custom domain: cdn.gograb.space or files.gograb.space
Access pattern: NestJS backend uploads via S3 SDK → files served via custom domain with CDN
User uploads file → NestJS backend receives it
→ Backend stores in R2 via @aws-sdk/client-s3
→ Backend saves file URL/key in MongoDB (metadata)
→ Files served from cdn.gograb.space (R2 + Cloudflare CDN)
Required Environment Variables for R2
# Cloudflare R2 Configuration
CLOUDFLARE_ACCOUNT_ID=5723867b831b303313524ffda92b71ea
CLOUDFLARE_R2_ACCESS_KEY_ID=<from Cloudflare R2 API tokens>
CLOUDFLARE_R2_SECRET_ACCESS_KEY=<from Cloudflare R2 API tokens>
CLOUDFLARE_R2_BUCKET_NAME=gograb-assets
CLOUDFLARE_R2_ENDPOINT=https://5723867b831b303313524ffda92b71ea.r2.cloudflarestorage.com
6. Cache (Railway Redis)
A managed Redis instance (redis:8.6.0) runs inside the Railway project, connected to all backend services via Railway's internal networking.
- Purpose: Rate limiting, distributed locks, BullMQ job queues, Socket.IO adapter
- Storage: Persistent via
redis-volume - Access: Internal Railway networking via
redis.railway.internal:6379 - Public proxy:
nozomi.proxy.rlwy.net:14089(for external tooling only)
Railway Reference Variables
| Variable | Resolves To | Use For |
|---|---|---|
${{Redis.REDIS_URL}} |
redis://default:***@redis.railway.internal:6379 |
Backend services (USE THIS) |
${{Redis.REDIS_PRIVATE_URL}} |
redis://default:***@127.0.0.1:6379 |
DO NOT USE — resolves to localhost |
${{Redis.REDIS_PUBLIC_URL}} |
redis://default:***@nozomi.proxy.rlwy.net:14089 |
External access only |
CRITICAL: Always use ${{Redis.REDIS_URL}} for backend service env vars. REDIS_PRIVATE_URL resolves to 127.0.0.1 which is only valid inside the Redis container itself. This was the root cause of Redis connection failures across all backends (Session 128).
Database Allocation
| Backend | Railway Env Var | Reference Value |
|---|---|---|
| backend-vitto-api | REDIS_URL |
${{Redis.REDIS_URL}}/0 |
| backend-api | REDIS_URL |
${{Redis.REDIS_URL}}/1 |
| backend-ai-api | REDIS_URL |
${{Redis.REDIS_URL}}/2 |
| backend-docs-api | REDIS_URL |
${{Redis.REDIS_URL}}/3 |
7. Error Tracking (Sentry)
Dashboard: https://gograb-tl.sentry.io/ Alerts: Configured for frontend error spikes (>10 errors/min)
8. Messaging (Twilio)
Console: https://console.twilio.com/
Purpose: WhatsApp and SMS integration for channel management
Config: Credentials stored in .env.local as TWILIO_* variables
9. AI Providers
| Provider | Env Variable | Used By |
|---|---|---|
| OpenAI | OPENAI_API_KEY |
backend-ai-api |
| Anthropic | ANTHROPIC_API_KEY |
backend-ai-api |
GOOGLE_AI_API_KEY |
backend-ai-api |
10. Environment Variables
Local development: .env.local at project root (git-ignored)
Template: deployment/docs/ENV_LOCAL_TEMPLATE.md
Loader utility: tools/scripts/database/env-loader.js
import { getEnvVar, requireEnvVar, getMongoDBConnectionString } from './env-loader.js';
const uri = getMongoDBConnectionString(); // Required (throws if missing)
const key = getEnvVar('MY_VAR', 'default'); // Optional with fallback
Railway production: Environment variables set per-service in Railway dashboard.
11. Legacy Infrastructure (cPanel / NixiHost) — DEPRECATED
Status: Can be cancelled. Not actively used.
| Detail | Value |
|---|---|
| Provider | NixiHost "Mini-Shared" plan |
| Server | iah-s02, IP 23.187.248.18 |
| cPanel URL | cpanel.gograb.space:2083 |
| Resource Usage | ~0% (CPU, memory, databases) |
| Websites Hosted | None |
| Databases | None |
| DNS Zone | Stale/irrelevant (Cloudflare overrides) |
| [email protected] mailbox exists (0 bytes, unused) | |
| FTP | Was used for legacy deployments, now replaced by Railway + Cloudflare |
Why it can be cancelled:
- Cloudflare is the DNS authority (nameservers point to Cloudflare, not NixiHost)
- Gmail depends on MX records in Cloudflare, not on cPanel
- No websites, databases, or active services run on cPanel
- FTP deployment has been replaced by Railway (backends) and Cloudflare Pages (frontends)
- File uploads will be handled by Cloudflare R2 (replaces FTP for file hosting)
12. Architecture Diagram
CLOUDFLARE (DNS + CDN + SSL)
┌─────────────────────────────────────────┐
│ gograb.space (nameservers) │
│ │
USER ──── HTTPS ────────►│ DNS Routing: │
│ *.gograb.space → Cloudflare Pages │
│ api.gograb.space → Railway │
│ ai-api.gograb.space → Railway │
│ vitto-api.gograb.space → Railway │
│ docs-api.gograb.space → Railway │
│ MX → Google Workspace (Gmail) │
│ │
│ R2 Object Storage: │
│ pulse-music bucket (audio files) │
│ gograb-assets bucket (general files) │
└──────────┬───────────────┬──────────────┘
│ │
┌────────────────┘ └────────────────┐
▼ ▼
CLOUDFLARE PAGES RAILWAY
┌──────────────────┐ ┌──────────────────────────┐
│ gograb-space │ │ GoGrab Project │
│ gograb-admin │ │ (3990549d-...) │
│ gograb-dev │ │ │
│ gograb-ai │ │ ┌──────────────────────┐ │
│ gograb-docs │ │ │ backend-api :3000 │ │
│ gograb-pulse │ │ │ backend-ai-api :3001 │ │
│ gograb-landing │ │ │ backend-docs :3002 │ │
└──────────────────┘ │ │ backend-vitto :3003 │ │
│ │ Redis :6379 │ │
│ └──────────┬───────────┘ │
└────────────┼─────────────┘
│
▼
MONGODB ATLAS
┌──────────────────────┐
│ gograb-api (main) │
│ gograb-docs │
│ vitto-mind │
└──────────────────────┘
13. Quick Reference — All IDs & URLs
Railway (Consolidated Project)
- Project ID:
3990549d-4313-47e4-9682-d17b382bdba2 - Environment ID:
1d438b60-52d5-4c89-ba8f-45fff0df308f
Cloudflare
- Account ID:
5723867b831b303313524ffda92b71ea - S3 API:
https://5723867b831b303313524ffda92b71ea.r2.cloudflarestorage.com - R2 Bucket (Pulse):
pulse-music
Service Dashboard URLs
- Backend API: https://railway.com/project/3990549d-4313-47e4-9682-d17b382bdba2/service/1ad0b79a-b722-4c69-920c-5dcb35978f0d
- Backend AI API: https://railway.com/project/3990549d-4313-47e4-9682-d17b382bdba2/service/fa00811a-db8e-4232-a23f-2becd96615c7
- Backend Docs API: https://railway.com/project/3990549d-4313-47e4-9682-d17b382bdba2/service/0f7af191-d7a4-4366-82b6-312c4ab8fa7e
- Backend Vitto API: https://railway.com/project/3990549d-4313-47e4-9682-d17b382bdba2/service/072352ed-2e34-468e-bec9-03f6d299f867
Health Check Endpoints
https://api.gograb.space/api/health
https://ai-api.gograb.space/ai-api/health
https://docs-api.gograb.space/docs-api/health
https://vitto-api.gograb.space/vitto-api/health
Key Config Files
| File | Purpose |
|---|---|
.env.local |
All environment variables (git-ignored) |
.railway/projects.json |
Railway project registry |
deployment/cli/lib/deployment-config.js |
Deployment target definitions |
deployment/docs/ENV_LOCAL_TEMPLATE.md |
Env var template/documentation |
tools/scripts/database/env-loader.js |
Env var loading utility |
This document should be updated whenever infrastructure changes are made (new services, domain changes, provider migrations, etc.)