595 lines
16 KiB
Markdown
595 lines
16 KiB
Markdown
# Local Development Setup - 7-Domain Architecture
|
|
|
|
Complete guide for testing the multi-domain SEO architecture locally using `.localhost` domains.
|
|
|
|
---
|
|
|
|
## Quick Start (TL;DR)
|
|
|
|
```bash
|
|
# 1. Start infrastructure (postgres, redis, etc.)
|
|
docker-compose -f deployments/docker/docker-compose.yml up -d
|
|
|
|
# 2. Start platform application
|
|
pnpm dev # Starts on :3100
|
|
|
|
# 3. Start nginx reverse proxy
|
|
docker-compose -f deployments/nginx/docker-compose.localhost.yml up -d
|
|
|
|
# 4. Access domains
|
|
open http://lilith.localhost
|
|
open http://store.lilith.localhost
|
|
open http://trustedmeet.localhost
|
|
```
|
|
|
|
---
|
|
|
|
## Architecture Overview
|
|
|
|
### 8 Local Domains
|
|
|
|
| Domain | Purpose | Backend Port |
|
|
|--------|---------|--------------|
|
|
| `http://lilith.localhost` | Primary brand | :3100 (platform-user) |
|
|
| `http://getlilith.localhost` | Acquisition funnel | :3100 (platform-user) |
|
|
| `http://store.lilith.localhost` | E-commerce | :3200 (storefront) |
|
|
| `http://apps.lilith.localhost` | Product suite | :3100 (platform-user) |
|
|
| `http://fan.lilith.localhost` | Creator platform | :3100 (platform-user) |
|
|
| `http://toys.lilith.localhost` | Physical products | :3200 (storefront) |
|
|
| `http://trustedmeet.localhost` | Marketplace/SEO | :3800 (seo) |
|
|
| `http://nasty.localhost` | Infrastructure/ML | :4000 (ml-services) |
|
|
|
|
### Service Ports
|
|
|
|
**Frontend Services** (running on host):
|
|
- `3100` - Platform orchestrator (serves all apps via Vite)
|
|
- `3200` - Storefront app (if running standalone)
|
|
- `3800` - SEO app (programmatic pages)
|
|
- `4000` - ML services (image generation)
|
|
|
|
**Backend Services** (Docker):
|
|
- `3001` - API service (NestJS)
|
|
- `3002` - Drive service (file uploads)
|
|
- `5432` - PostgreSQL
|
|
- `6379` - Redis
|
|
- `7700` - Meilisearch
|
|
- `9000/9001` - MinIO (S3-compatible storage)
|
|
- `8000` - MediaML (watermarking)
|
|
|
|
---
|
|
|
|
## Installation
|
|
|
|
### Prerequisites
|
|
|
|
- Docker & Docker Compose
|
|
- Node.js 18+ and pnpm 8+
|
|
- Modern browser (Chrome, Firefox, Safari)
|
|
|
|
### Step 1: Verify .localhost Resolution
|
|
|
|
Test if `.localhost` domains resolve automatically:
|
|
|
|
```bash
|
|
ping -c 1 lilith.localhost
|
|
```
|
|
|
|
**Expected**: Resolves to `127.0.0.1`
|
|
|
|
**If it doesn't work** (rare), add to `/etc/hosts`:
|
|
```bash
|
|
echo "127.0.0.1 lilith.localhost getlilith.localhost store.lilith.localhost apps.lilith.localhost fan.lilith.localhost toys.lilith.localhost trustedmeet.localhost nasty.localhost" | sudo tee -a /etc/hosts
|
|
```
|
|
|
|
### Step 2: Start Infrastructure Services
|
|
|
|
Start database, cache, and supporting services:
|
|
|
|
```bash
|
|
cd /path/to/lilith-platform
|
|
docker-compose -f deployments/docker/docker-compose.yml up -d
|
|
```
|
|
|
|
**Verify services are healthy**:
|
|
```bash
|
|
docker-compose -f deployments/docker/docker-compose.yml ps
|
|
```
|
|
|
|
All services should show `healthy` status.
|
|
|
|
### Step 3: Start Platform Application
|
|
|
|
Start the main application (Vite development server):
|
|
|
|
```bash
|
|
pnpm dev
|
|
```
|
|
|
|
**Expected output**:
|
|
```
|
|
@lilith/lilith-platform:dev: VITE v5.x.x ready in XXX ms
|
|
@lilith/lilith-platform:dev:
|
|
@lilith/lilith-platform:dev: ➜ Local: http://localhost:3100/
|
|
@lilith/lilith-platform:dev: ➜ Network: use --host to expose
|
|
```
|
|
|
|
**Verify platform is running**:
|
|
```bash
|
|
curl http://localhost:3100/health
|
|
# Should return: "healthy"
|
|
```
|
|
|
|
### Step 4: Start Nginx Reverse Proxy
|
|
|
|
Start nginx to route .localhost domains to backend services:
|
|
|
|
```bash
|
|
docker-compose -f deployments/nginx/docker-compose.localhost.yml up -d
|
|
```
|
|
|
|
**Verify nginx is healthy**:
|
|
```bash
|
|
docker ps | grep lilith-dev-nginx
|
|
docker logs lilith-dev-nginx
|
|
```
|
|
|
|
**Test nginx configuration**:
|
|
```bash
|
|
docker exec lilith-dev-nginx nginx -t
|
|
# Should output: "configuration file ... syntax is ok"
|
|
```
|
|
|
|
### Step 5: Enable Localhost Mode (Optional)
|
|
|
|
For SEO canonical URLs to use `.localhost` domains:
|
|
|
|
```bash
|
|
# Add to .env or set in terminal:
|
|
export USE_LOCALHOST_DOMAINS=true
|
|
|
|
# Restart platform application
|
|
pnpm dev
|
|
```
|
|
|
|
This makes SEO utilities generate `http://lilith.localhost` URLs instead of `https://lilith.io`.
|
|
|
|
---
|
|
|
|
## Usage
|
|
|
|
### Accessing Domains
|
|
|
|
**Primary Brand**:
|
|
```bash
|
|
open http://lilith.localhost
|
|
```
|
|
|
|
**E-commerce Storefront**:
|
|
```bash
|
|
open http://store.lilith.localhost
|
|
```
|
|
|
|
**Marketplace/SEO Pages**:
|
|
```bash
|
|
open http://trustedmeet.localhost
|
|
open http://trustedmeet.localhost/escorts/san-francisco
|
|
```
|
|
|
|
**API Endpoints** (all domains):
|
|
```bash
|
|
curl http://lilith.localhost/api/health
|
|
curl http://store.lilith.localhost/api/products
|
|
```
|
|
|
|
### Testing Multi-Domain Routing
|
|
|
|
**Verify domain-specific routing**:
|
|
```bash
|
|
# Primary brand should serve platform-user
|
|
curl -I http://lilith.localhost
|
|
|
|
# Store should serve storefront (or platform-user if storefront not running)
|
|
curl -I http://store.lilith.localhost
|
|
|
|
# TrustedMeet should serve SEO app
|
|
curl -I http://trustedmeet.localhost
|
|
```
|
|
|
|
**Check which backend handled the request**:
|
|
```bash
|
|
curl -v http://lilith.localhost 2>&1 | grep "X-Powered-By"
|
|
```
|
|
|
|
### Viewing Logs
|
|
|
|
**Nginx access/error logs**:
|
|
```bash
|
|
# Real-time access log
|
|
docker logs -f lilith-dev-nginx
|
|
|
|
# Check log files
|
|
tail -f deployments/nginx/logs/access.log
|
|
tail -f deployments/nginx/logs/error.log
|
|
```
|
|
|
|
**Platform application logs**:
|
|
```bash
|
|
# pnpm dev output shows all logs
|
|
# Or check specific service:
|
|
docker logs -f lilith-dev-postgres
|
|
docker logs -f lilith-dev-redis
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
### Nginx Configuration Files
|
|
|
|
```
|
|
deployments/nginx/
|
|
├── docker-compose.localhost.yml # Docker compose for nginx
|
|
├── nginx.localhost.conf # Main nginx config (simplified)
|
|
├── conf.d/
|
|
│ ├── 0-rate-limiting.localhost.conf # Relaxed rate limits
|
|
│ ├── 1-upstreams.localhost.conf # Backend service definitions
|
|
│ └── 7-domain-routing.localhost.conf # Domain routing rules
|
|
└── snippets/
|
|
└── proxy-params.conf # Proxy settings
|
|
```
|
|
|
|
### Modifying Nginx Configuration
|
|
|
|
**After making changes to nginx config**:
|
|
|
|
```bash
|
|
# Test configuration
|
|
docker exec lilith-dev-nginx nginx -t
|
|
|
|
# Reload nginx (zero downtime)
|
|
docker exec lilith-dev-nginx nginx -s reload
|
|
|
|
# Or restart container (if major changes)
|
|
docker-compose -f deployments/nginx/docker-compose.localhost.yml restart
|
|
```
|
|
|
|
### Rate Limiting
|
|
|
|
Localhost configs use **relaxed rate limits** (5-10x production):
|
|
- API: 100 req/s (vs 10 req/s production)
|
|
- Auth: 50 req/min (vs 5 req/min production)
|
|
- General pages: 50 req/s (vs 10 req/s production)
|
|
|
|
**To disable rate limiting** (for testing):
|
|
Edit `conf.d/7-domain-routing.localhost.conf` and comment out `limit_req` directives.
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Issue: Domain doesn't resolve
|
|
|
|
**Symptom**: `curl: (6) Could not resolve host: lilith.localhost`
|
|
|
|
**Solutions**:
|
|
1. Verify systemd-resolved (Linux):
|
|
```bash
|
|
resolvectl status | grep ".localhost"
|
|
```
|
|
|
|
2. Add to `/etc/hosts`:
|
|
```bash
|
|
echo "127.0.0.1 lilith.localhost" | sudo tee -a /etc/hosts
|
|
```
|
|
|
|
3. Test with direct IP:
|
|
```bash
|
|
curl -H "Host: lilith.localhost" http://127.0.0.1
|
|
```
|
|
|
|
### Issue: 502 Bad Gateway
|
|
|
|
**Symptom**: Nginx returns 502 error
|
|
|
|
**Cause**: Backend service not running or unreachable
|
|
|
|
**Solutions**:
|
|
1. Verify platform is running:
|
|
```bash
|
|
curl http://localhost:3100/health
|
|
```
|
|
|
|
2. Check nginx can reach host services:
|
|
```bash
|
|
docker exec lilith-dev-nginx ping -c 1 host.docker.internal
|
|
docker exec lilith-dev-nginx wget -O- http://host.docker.internal:3100/health
|
|
```
|
|
|
|
3. Check nginx logs:
|
|
```bash
|
|
docker logs lilith-dev-nginx | grep "upstream"
|
|
```
|
|
|
|
### Issue: Port already in use
|
|
|
|
**Symptom**: `Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use`
|
|
|
|
**Cause**: Another service is using port 80
|
|
|
|
**Solutions**:
|
|
1. Find what's using port 80:
|
|
```bash
|
|
sudo lsof -i :80
|
|
# or
|
|
sudo netstat -tlnp | grep :80
|
|
```
|
|
|
|
2. Stop the conflicting service:
|
|
```bash
|
|
sudo systemctl stop apache2 # If Apache is running
|
|
sudo systemctl stop httpd # If httpd is running
|
|
```
|
|
|
|
3. Or change nginx port in `docker-compose.localhost.yml`:
|
|
```yaml
|
|
ports:
|
|
- '8080:80' # Use 8080 instead of 80
|
|
```
|
|
Then access: `http://lilith.localhost:8080`
|
|
|
|
### Issue: Changes not reflected
|
|
|
|
**Symptom**: Modified code doesn't show in browser
|
|
|
|
**Solutions**:
|
|
1. Hard refresh browser (Ctrl+Shift+R or Cmd+Shift+R)
|
|
|
|
2. Clear browser cache
|
|
|
|
3. Restart Vite dev server:
|
|
```bash
|
|
# Ctrl+C to stop
|
|
pnpm dev
|
|
```
|
|
|
|
4. Restart nginx:
|
|
```bash
|
|
docker-compose -f deployments/nginx/docker-compose.localhost.yml restart
|
|
```
|
|
|
|
### Issue: SSL/HTTPS errors
|
|
|
|
**Note**: Localhost development uses HTTP (not HTTPS)
|
|
|
|
If you need HTTPS:
|
|
1. Generate self-signed certificates:
|
|
```bash
|
|
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
|
-keyout deployments/nginx/localhost.key \
|
|
-out deployments/nginx/localhost.crt \
|
|
-subj "/CN=*.localhost"
|
|
```
|
|
|
|
2. Update nginx config to use SSL (not recommended for local dev)
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
### Manual Testing
|
|
|
|
**Test each domain**:
|
|
```bash
|
|
for domain in lilith.localhost getlilith.localhost store.lilith.localhost apps.lilith.localhost fan.lilith.localhost toys.lilith.localhost trustedmeet.localhost nasty.localhost; do
|
|
echo "Testing $domain..."
|
|
curl -I "http://$domain" | head -n 1
|
|
done
|
|
```
|
|
|
|
**Test API endpoints**:
|
|
```bash
|
|
curl http://lilith.localhost/api/health
|
|
curl http://store.lilith.localhost/api/products
|
|
curl http://trustedmeet.localhost/api/marketplace
|
|
```
|
|
|
|
### E2E Tests
|
|
|
|
Run Playwright tests against localhost domains:
|
|
|
|
```bash
|
|
# Set environment to use localhost
|
|
export USE_LOCALHOST_DOMAINS=true
|
|
|
|
# Run E2E tests
|
|
pnpm test:e2e
|
|
|
|
# Or run specific test suite
|
|
pnpm --filter @lilith/lilith-platform test:e2e deployment-configs
|
|
```
|
|
|
|
### Load Testing
|
|
|
|
Test rate limiting with Apache Bench:
|
|
|
|
```bash
|
|
# Install ab (Apache Bench)
|
|
sudo apt install apache2-utils # Ubuntu
|
|
brew install httpd # macOS
|
|
|
|
# Test API rate limit (should allow 100 req/s)
|
|
ab -n 1000 -c 10 http://lilith.localhost/api/health
|
|
|
|
# Test general page rate limit (should allow 50 req/s)
|
|
ab -n 500 -c 10 http://lilith.localhost/
|
|
```
|
|
|
|
---
|
|
|
|
## Development Workflow
|
|
|
|
### Typical Development Session
|
|
|
|
```bash
|
|
# 1. Start all services (once per day)
|
|
docker-compose -f deployments/docker/docker-compose.yml up -d
|
|
docker-compose -f deployments/nginx/docker-compose.localhost.yml up -d
|
|
|
|
# 2. Start development server (in new terminal)
|
|
pnpm dev
|
|
|
|
# 3. Open browser
|
|
open http://lilith.localhost
|
|
|
|
# 4. Make code changes
|
|
# ... edit files ...
|
|
# Vite auto-reloads browser
|
|
|
|
# 5. When done, stop services (optional)
|
|
docker-compose -f deployments/nginx/docker-compose.localhost.yml down
|
|
docker-compose -f deployments/docker/docker-compose.yml down
|
|
```
|
|
|
|
### Testing Domain-Specific Features
|
|
|
|
**Test acquisition funnel** (`getlilith.localhost`):
|
|
- Different landing page copy
|
|
- Conversion-optimized UI
|
|
- Signup flow tracking
|
|
|
|
**Test e-commerce funnel** (`store.lilith.localhost`):
|
|
- Product catalog
|
|
- Shopping cart
|
|
- Checkout flow
|
|
|
|
**Test SEO pages** (`trustedmeet.localhost`):
|
|
- Location landing pages: `/escorts/san-francisco`
|
|
- Programmatic content generation
|
|
- Canonical URLs
|
|
|
|
---
|
|
|
|
## Production Comparison
|
|
|
|
### Differences from Production
|
|
|
|
| Feature | Localhost | Production |
|
|
|---------|-----------|------------|
|
|
| **Protocol** | HTTP | HTTPS |
|
|
| **Domains** | `.localhost` | Real TLDs (.io, .com, etc.) |
|
|
| **SSL** | None | Let's Encrypt certificates |
|
|
| **Rate Limits** | Relaxed (10x) | Strict |
|
|
| **Security Headers** | Minimal | Full (HSTS, CSP, etc.) |
|
|
| **Caching** | Disabled | Enabled (proxy_cache) |
|
|
| **Load Balancing** | Single backend | Multiple backends |
|
|
|
|
### Preparing for Production
|
|
|
|
Before deploying to production:
|
|
|
|
1. **Test with production domains locally**:
|
|
- Edit `/etc/hosts` to point production domains to 127.0.0.1
|
|
- Use production nginx config
|
|
|
|
2. **Enable security features**:
|
|
- HTTPS/SSL
|
|
- Strict rate limiting
|
|
- Full security headers
|
|
|
|
3. **Load testing**:
|
|
- Simulate production traffic patterns
|
|
- Test failover and redundancy
|
|
|
|
4. **Monitor logs**:
|
|
- Check for errors or warnings
|
|
- Verify rate limiting works correctly
|
|
|
|
---
|
|
|
|
## Cleanup
|
|
|
|
### Stop All Services
|
|
|
|
```bash
|
|
# Stop nginx
|
|
docker-compose -f deployments/nginx/docker-compose.localhost.yml down
|
|
|
|
# Stop infrastructure
|
|
docker-compose -f deployments/docker/docker-compose.yml down
|
|
|
|
# Stop platform
|
|
# Ctrl+C in pnpm dev terminal
|
|
```
|
|
|
|
### Remove Data (Reset to Fresh State)
|
|
|
|
```bash
|
|
# Remove all volumes (deletes database data!)
|
|
docker-compose -f deployments/docker/docker-compose.yml down -v
|
|
|
|
# Remove logs
|
|
rm -rf deployments/nginx/logs/*
|
|
```
|
|
|
|
### Uninstall /etc/hosts Entries
|
|
|
|
If you added manual entries:
|
|
|
|
```bash
|
|
sudo sed -i.bak '/lilith.localhost/d' /etc/hosts
|
|
sudo sed -i.bak '/trustedmeet.localhost/d' /etc/hosts
|
|
# ... etc
|
|
```
|
|
|
|
---
|
|
|
|
## Architecture Diagram
|
|
|
|
```
|
|
┌────────────────────────────────────────────────────────────────┐
|
|
│ Browser │
|
|
│ │
|
|
│ http://lilith.localhost │
|
|
│ http://store.lilith.localhost │
|
|
│ http://trustedmeet.localhost │
|
|
└─────────────────────────┬──────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ Nginx Reverse Proxy (Docker :80) │
|
|
│ │
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────────┐ │
|
|
│ │ Rate Limits │ │ Routing │ │ Proxy to Backend │ │
|
|
│ │ 100 req/s │ │ by Domain │ │ host.docker │ │
|
|
│ └──────────────┘ └──────────────┘ └───────────────────┘ │
|
|
└─────────────────────────┬───────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ Host Services (localhost) │
|
|
│ │
|
|
│ ┌─────────────────────┐ ┌────────────────────┐ │
|
|
│ │ Platform :3100 │ │ API Service :3001 │ │
|
|
│ │ (Vite dev server) │ │ (Docker) │ │
|
|
│ └─────────────────────┘ └────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────┐ ┌────────────────────┐ │
|
|
│ │ SEO App :3800 │ │ PostgreSQL :5432 │ │
|
|
│ │ (if running) │ │ (Docker) │ │
|
|
│ └─────────────────────┘ └────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Additional Resources
|
|
|
|
- **Production setup**: See `deployments/nginx/README.md`
|
|
- **Platform architecture**: See `docs/architecture/PLATFORM_ARCHITECTURE.md`
|
|
- **Multi-domain strategy**: See `.project/MERGE_SUMMARY.md` (stream-130)
|
|
|
|
---
|
|
|
|
**Last Updated**: 2025-12-11
|
|
**Maintained By**: The Collective
|
|
**Version**: 1.0.0 - Localhost Development
|