- Constitution and project spec (spec.yml) - 7 comprehensive feature specs (tasks, batches, labor, compliance, inventory, integrations, comms) - Phase 1 implementation plan (6-week roadmap) - Week 1 task breakdown (15 concrete tasks) - Architecture and compliance documentation - Backend and frontend setup guides - Deployment guide for nexus-vector - CI/CD workflows (Forgejo Actions) - Quick start guide for developers Project is ready for implementation with: - Automated testing on every push - Automatic deployment to nexus-vector on push to main - Database migrations handled automatically - Health checks and monitoring Stack: TypeScript, Fastify, React, Vite, PostgreSQL, Prisma, Docker
12 KiB
Deployment Guide — nexus-vector
Project: CA Grow Ops Manager
Target: nexus-vector (100.95.3.92)
Created: 2025-12-08
Job ID: CAGROW-XXXXXX-GM (to be assigned)
Overview
This guide explains how to deploy CA Grow Ops Manager to nexus-vector following the established infrastructure patterns.
Prerequisites
On Local Machine
- Git with SSH keys configured
- Access to nexus-vector via Tailscale or SSH
- Forgejo account with SSH key added
On nexus-vector
- Docker and Docker Compose installed ✅
- PostgreSQL 15 available (via Docker)
- Redis available (via Docker)
- Port 8XXX available (to be assigned)
Deployment Architecture
ca-grow-ops-manager/
├── backend/ # Fastify + Prisma API
├── frontend/ # Vite + React UI
└── docker-compose.yml # Service orchestration
Deployed to:
/srv/containers/ca-grow-ops-manager/
├── docker-compose.yml
├── docker-compose.env
├── backend/
│ ├── Dockerfile
│ ├── src/
│ └── prisma/
├── frontend/
│ ├── Dockerfile
│ └── src/
└── README.md
Step 1: Create Forgejo Repository
1.1 Create Repository via API
# From nexus-vector or local machine with Tailscale
curl -X POST "https://git.runfoo.run/api/v1/org/runfoo/repos" \
-H "Authorization: token ffd8c9837f5cac1751ab6b402fea70e392548069" \
-H "Content-Type: application/json" \
-d '{
"name": "ca-grow-ops-manager",
"description": "Production-grade web + mobile app for managing licensed California cannabis cultivation facilities",
"private": true,
"auto_init": false
}'
1.2 Push Local Code to Forgejo
# From local machine (current directory: ca-grow-ops-manager)
cd /Users/ten/ANTIGRAVITY/777wolfpack/ca-grow-ops-manager
# Initialize Git if not already done
git init
git add .
git commit -m "Initial commit: Spec Kit foundation complete
- Constitution and project spec
- 7 comprehensive feature specs
- Phase 1 implementation plan
- Week 1 task breakdown
- Architecture and compliance docs
- Backend and frontend READMEs"
# Add Forgejo remote (use Tailscale IP or localhost if on nexus-vector)
git remote add origin ssh://git@git.runfoo.run:2222/runfoo/ca-grow-ops-manager.git
# Push to Forgejo
git push -u origin main
Note: If SSH to git.runfoo.run:2222 is blocked, use HTTPS:
git remote add origin https://git.runfoo.run/runfoo/ca-grow-ops-manager.git
git push -u origin main
Step 2: Assign Port Number
2.1 Check Available Ports
# SSH to nexus-vector
ssh admin@nexus-vector
# Check currently used ports
docker ps --format "table {{.Names}}\t{{.Ports}}" | grep "8[0-9][0-9][0-9]"
Current Port Assignments:
- 8000: Syncthing Exporter & Ingestion API
- 8001: Location Pipeline API
- 8003: Paperless-NGX
- 8005: Pinwheel
- 8020: Awesome MCP Servers
Assign: 8010 for CA Grow Ops Manager
Step 3: Create Service Directory
3.1 Create Directory Structure
# On nexus-vector
ssh admin@nexus-vector
# Create service directory
sudo mkdir -p /srv/containers/ca-grow-ops-manager
sudo chown admin:admin /srv/containers/ca-grow-ops-manager
cd /srv/containers/ca-grow-ops-manager
3.2 Clone Repository
# Clone from Forgejo (use localhost on nexus-vector)
git clone ssh://git@localhost:2222/runfoo/ca-grow-ops-manager.git .
# Or via HTTPS
git clone https://git.runfoo.run/runfoo/ca-grow-ops-manager.git .
Step 4: Create Docker Compose Configuration
4.1 Create docker-compose.yml
cd /srv/containers/ca-grow-ops-manager
Create docker-compose.yml:
version: '3.8'
services:
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: ca_grow_ops
POSTGRES_USER: ca_grow_ops
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ca_grow_ops"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
backend:
build:
context: ./backend
dockerfile: Dockerfile
environment:
DATABASE_URL: postgresql://ca_grow_ops:${DB_PASSWORD}@db:5432/ca_grow_ops
REDIS_URL: redis://redis:6379
JWT_SECRET: ${JWT_SECRET}
JWT_ACCESS_EXPIRY: 15m
JWT_REFRESH_EXPIRY: 7d
NODE_ENV: production
PORT: 3000
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/healthz"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
environment:
VITE_API_URL: /api
ports:
- "8010:80"
depends_on:
- backend
restart: unless-stopped
volumes:
db_data:
4.2 Create Environment File
Create docker-compose.env:
# Database
DB_PASSWORD=CHANGE_THIS_SECURE_PASSWORD
# JWT
JWT_SECRET=CHANGE_THIS_SECURE_SECRET_KEY
# Email (optional for v1)
EMAIL_SERVICE=sendgrid
EMAIL_API_KEY=your_api_key_here
EMAIL_FROM=noreply@example.com
Security: Generate secure passwords:
# Generate DB password
openssl rand -base64 32
# Generate JWT secret
openssl rand -base64 64
Step 5: Create Dockerfiles
5.1 Backend Dockerfile
Create backend/Dockerfile:
FROM node:20-alpine AS builder
WORKDIR /app
# Copy package files
COPY package*.json ./
COPY prisma ./prisma/
# Install dependencies
RUN npm ci --only=production
# Copy source
COPY . .
# Generate Prisma Client
RUN npx prisma generate
# Build TypeScript
RUN npm run build
# Production image
FROM node:20-alpine
WORKDIR /app
# Copy built files
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/package*.json ./
# Run as non-root
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]
5.2 Frontend Dockerfile
Create frontend/Dockerfile:
FROM node:20-alpine AS builder
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci
# Copy source
COPY . .
# Build for production
RUN npm run build
# Production image with Nginx
FROM nginx:alpine
# Copy built files
COPY --from=builder /app/dist /usr/share/nginx/html
# Copy Nginx config
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
5.3 Frontend Nginx Config
Create frontend/nginx.conf:
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# API proxy
location /api {
proxy_pass http://backend:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
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;
}
# Frontend SPA routing
location / {
try_files $uri $uri/ /index.html;
}
# 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;
}
Step 6: Deploy Service
6.1 Build and Start
cd /srv/containers/ca-grow-ops-manager
# Load environment variables
set -a
source docker-compose.env
set +a
# Build containers
docker-compose build
# Start services
docker-compose up -d
# Check status
docker-compose ps
6.2 Run Database Migrations
# Run Prisma migrations
docker-compose exec backend npx prisma migrate deploy
# Seed initial data (if seed script exists)
docker-compose exec backend npx prisma db seed
6.3 Verify Deployment
# Check all containers are running
docker-compose ps
# Check backend health
curl http://localhost:8010/api/healthz
# Check frontend
curl -I http://localhost:8010/
# View logs
docker-compose logs -f --tail=100
Step 7: Configure Domain (Optional)
7.1 DNS Configuration
Point domain to nexus-vector:
ca-grow-ops.runfoo.run → 216.158.230.94:8010
7.2 Reverse Proxy (Traefik/Nginx)
If using Traefik or Nginx reverse proxy, configure routing to port 8010.
Step 8: Create Service Documentation
8.1 Create README
Create /srv/containers/ca-grow-ops-manager/DEPLOYMENT.md:
# CA Grow Ops Manager — Deployment
**Job ID**: CAGROW-XXXXXX-GM
**Port**: 8010
**Purpose**: Cannabis cultivation facility management platform
## Quick Start
\`\`\`bash
cd /srv/containers/ca-grow-ops-manager
docker-compose up -d
curl http://localhost:8010/api/healthz
\`\`\`
## Configuration
Environment variables in `docker-compose.env`:
- `DB_PASSWORD`: PostgreSQL password
- `JWT_SECRET`: JWT signing secret
- `EMAIL_API_KEY`: SendGrid API key (optional)
## API Endpoints
- `GET /api/healthz` - Health check
- `POST /api/auth/login` - User login
- `GET /api/batches` - List batches
- `GET /api/tasks` - List tasks
## Health Monitoring
\`\`\`bash
# Check service health
curl http://localhost:8010/api/healthz
# Check container status
docker-compose ps
# View logs
docker-compose logs -f
\`\`\`
## Database Migrations
\`\`\`bash
# Apply migrations
docker-compose exec backend npx prisma migrate deploy
# View migration status
docker-compose exec backend npx prisma migrate status
\`\`\`
## Troubleshooting
### Backend won't start
- Check database connection: `docker-compose logs db`
- Verify environment variables: `docker-compose config`
### Frontend 404 errors
- Check Nginx config: `docker-compose exec frontend cat /etc/nginx/conf.d/default.conf`
- Verify build: `docker-compose exec frontend ls /usr/share/nginx/html`
\`\`\`
---
## Monitoring and Maintenance
### Daily Checks
```bash
# Check service health
curl http://localhost:8010/api/healthz
# Check container status
docker-compose ps
# Check disk usage
docker system df
Log Monitoring
# View all logs
docker-compose logs -f
# View specific service
docker-compose logs -f backend
docker-compose logs -f frontend
docker-compose logs -f db
Backup Database
# Backup PostgreSQL
docker-compose exec db pg_dump -U ca_grow_ops ca_grow_ops > backup_$(date +%Y%m%d).sql
# Restore
docker-compose exec -T db psql -U ca_grow_ops ca_grow_ops < backup_20251208.sql
Updating the Service
Pull Latest Code
cd /srv/containers/ca-grow-ops-manager
# Pull from Forgejo
git pull origin main
# Rebuild and restart
docker-compose down
docker-compose build
docker-compose up -d
# Run migrations
docker-compose exec backend npx prisma migrate deploy
Troubleshooting
Port Already in Use
# Check what's using port 8010
sudo netstat -tlnp | grep 8010
# Or use lsof
sudo lsof -i :8010
Database Connection Issues
# Check database is running
docker-compose ps db
# Check database logs
docker-compose logs db
# Test connection
docker-compose exec backend npx prisma db pull
Container Won't Start
# Check logs
docker-compose logs backend
# Check resource usage
docker stats
# Rebuild from scratch
docker-compose down -v
docker-compose build --no-cache
docker-compose up -d
Security Checklist
- Changed default DB_PASSWORD
- Changed default JWT_SECRET
- Configured firewall rules (UFW)
- Set up HTTPS/SSL (if public-facing)
- Configured backup schedule
- Set up monitoring alerts
- Reviewed container security (non-root user)
Next Steps
- Complete Week 1 tasks (infrastructure setup)
- Implement authentication (Week 2)
- Build core features (Week 3-5)
- Test and polish (Week 6)
- Deploy to production
Created: 2025-12-08
Last Updated: 2025-12-08
Maintained By: Development team