Standalone Deployment - nself-org/nchat GitHub Wiki
Version: 0.9.2 Last Updated: February 10, 2026 Status: Production Ready
Standalone deployment means each nself-chat instance runs with its own dedicated nSelf backend infrastructure. This is the simplest deployment model and recommended for:
- Single teams or organizations
- Simple setup requirements
- Full control over infrastructure
- Independent scaling needs
- Testing and development environments
app1.example.com
├── Frontend (Next.js)
│ └── Served at /
├── Backend (nSelf)
│ ├── /api → Hasura GraphQL
│ ├── /auth → Nhost Auth
│ ├── /v1/graphql → GraphQL endpoint
│ └── /storage → MinIO (optional)
└── Database (PostgreSQL)
└── Single database instance
- Domain name with DNS control
- Hosting platform account (Vercel/Netlify/Docker host)
- SSL certificate (Let's Encrypt or platform-provided)
- Node.js 20+ (for local builds)
- pnpm 9.15.4+
- CDN (Cloudflare, Fastly, etc.)
- Monitoring service (Sentry, DataDog)
- Backup solution
- CI/CD pipeline
Option A: Docker Compose (Recommended for VPS)
# Clone repository
git clone https://github.com/yourusername/nself-chat.git
cd nself-chat
# Install nself CLI
npm install -g @nself/cli@latest
# Initialize backend
cd .backend
nself init --demo
# Configure environment
cp .env.example .env
nano .env # Edit configuration
# Start services
nself start
# Verify services
nself status
nself urlsExpected Output:
✓ PostgreSQL http://localhost:5432
✓ Hasura http://localhost:8080
✓ Auth http://localhost:4000
✓ Admin http://localhost:3021
Option B: Kubernetes (Recommended for Production)
# Apply configurations
kubectl apply -f deploy/k8s/namespace.yaml
kubectl apply -f deploy/k8s/postgres.yaml
kubectl apply -f deploy/k8s/hasura.yaml
kubectl apply -f deploy/k8s/auth.yaml
# Verify pods
kubectl get pods -n nself-chat
# Check logs
kubectl logs -f deployment/hasura -n nself-chatCreate .env.local for frontend:
# Backend URLs (adjust for your domain)
NEXT_PUBLIC_GRAPHQL_URL=https://app1.example.com/v1/graphql
NEXT_PUBLIC_AUTH_URL=https://app1.example.com/auth
NEXT_PUBLIC_STORAGE_URL=https://app1.example.com/storage
# Environment
NEXT_PUBLIC_ENV=production
NODE_ENV=production
# Application
NEXT_PUBLIC_APP_NAME=nself-chat
NEXT_PUBLIC_PRIMARY_COLOR=#6366f1
# Optional: Sentry monitoring
NEXT_PUBLIC_SENTRY_DSN=https://[key]@[org].ingest.sentry.io/[project]
SENTRY_ORG=your-org
SENTRY_PROJECT=nself-chatBackend .env (in .backend/ directory):
# Database
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=nself_chat
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your_secure_password
# Hasura
HASURA_GRAPHQL_ADMIN_SECRET=your_admin_secret
HASURA_GRAPHQL_JWT_SECRET={"type":"HS256","key":"your_jwt_secret"}
# Auth
AUTH_SERVER_URL=http://auth:4000
AUTH_CLIENT_URL=https://app1.example.com/auth
# Optional: Storage
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=your_minio_passwordOption A: Vercel (Recommended for Next.js)
# Install Vercel CLI
npm install -g vercel
# Login
vercel login
# Deploy
vercel --prod
# Configure environment variables in Vercel dashboard
# Project Settings → Environment VariablesVercel Configuration (vercel.json):
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@vercel/next"
}
],
"env": {
"NEXT_PUBLIC_GRAPHQL_URL": "https://app1.example.com/v1/graphql",
"NEXT_PUBLIC_AUTH_URL": "https://app1.example.com/auth"
}
}Option B: Netlify
# Install Netlify CLI
npm install -g netlify-cli
# Build
pnpm build
# Deploy
netlify deploy --prod --dir=.nextNetlify Configuration (netlify.toml) (the redirects array below uses TOML array-of-tables syntax — double brackets are TOML, not wiki-links):
[build]
command = "pnpm build"
publish = ".next"
[build.environment]
NODE_VERSION = "20"
NPM_FLAGS = "--version"
[[redirects]]
from = "/api/*"
to = "https://app1.example.com/api/:splat"
status = 200
[[redirects]]
from = "/auth/*"
to = "https://app1.example.com/auth/:splat"
status = 200Option C: Docker (Self-Hosted)
# Build image
docker build -t nself-chat:latest .
# Run container
docker run -d \
--name nself-chat \
-p 3000:3000 \
-e NEXT_PUBLIC_GRAPHQL_URL=https://app1.example.com/v1/graphql \
-e NEXT_PUBLIC_AUTH_URL=https://app1.example.com/auth \
nself-chat:latest
# Verify
docker logs -f nself-chatDockerfile (already included):
FROM node:22-alpine AS base
# Dependencies
FROM base AS deps
RUN corepack enable && corepack prepare [email protected] --activate
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
# Builder
FROM base AS builder
RUN corepack enable && corepack prepare [email protected] --activate
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN pnpm build
# Runner
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
CMD ["node", "server.js"]DNS Configuration:
Type Name Value TTL
A @ your.server.ip.address 3600
CNAME www app1.example.com 3600
Vercel Domain Setup:
- Go to Project Settings → Domains
- Add
app1.example.com - Configure DNS as shown in Vercel dashboard
- Wait for SSL certificate provisioning (~5 minutes)
Nginx Configuration (if self-hosted):
# /etc/nginx/sites-available/nself-chat
server {
listen 80;
server_name app1.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name app1.example.com;
ssl_certificate /etc/letsencrypt/live/app1.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app1.example.com/privkey.pem;
# Frontend
location / {
proxy_pass http://localhost: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;
}
# Backend API
location /api/ {
proxy_pass http://localhost:8080/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Auth
location /auth/ {
proxy_pass http://localhost:4000/v1/auth/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# GraphQL
location /v1/graphql {
proxy_pass http://localhost:8080/v1/graphql;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
}
# Storage (optional)
location /storage/ {
proxy_pass http://localhost:9000/;
proxy_http_version 1.1;
proxy_set_header Host $host;
}
}Enable and restart:
sudo ln -s /etc/nginx/sites-available/nself-chat /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginxOption A: Let's Encrypt (Free)
# Install certbot
sudo apt-get install certbot python3-certbot-nginx
# Obtain certificate
sudo certbot --nginx -d app1.example.com
# Auto-renewal (already configured by certbot)
sudo certbot renew --dry-runOption B: Platform-Managed (Vercel/Netlify)
SSL certificates are automatically provisioned and renewed. No action required.
Option C: Custom Certificate
# Copy certificate files
sudo cp your-cert.crt /etc/ssl/certs/app1.example.com.crt
sudo cp your-cert.key /etc/ssl/private/app1.example.com.key
# Set permissions
sudo chmod 644 /etc/ssl/certs/app1.example.com.crt
sudo chmod 600 /etc/ssl/private/app1.example.com.key
# Update Nginx config (already shown above)Hasura CORS (.backend/.env):
# Allow your frontend domain
HASURA_GRAPHQL_CORS_DOMAIN=https://app1.example.comNhost Auth CORS (.backend/.env):
# Allowed redirect URIs
AUTH_CLIENT_URL=https://app1.example.com
AUTH_REDIRECT_URL=https://app1.example.com/auth/callbackFrontend CORS (next.config.mjs):
const nextConfig = {
async headers() {
return [
{
source: '/api/:path*',
headers: [
{ key: 'Access-Control-Allow-Origin', value: 'https://app1.example.com' },
{ key: 'Access-Control-Allow-Methods', value: 'GET,POST,PUT,DELETE,OPTIONS' },
{ key: 'Access-Control-Allow-Headers', value: 'Content-Type, Authorization' },
],
},
]
},
}Pros:
- Zero configuration
- Automatic SSL
- Global CDN
- Serverless functions
- GitHub integration
Steps:
-
Connect Repository
# Push to GitHub git remote add origin https://github.com/yourusername/nself-chat.git git push -u origin main -
Import to Vercel
- Go to https://vercel.com/new
- Select repository
- Framework preset: Next.js
- Click "Deploy"
-
Configure Environment Variables
- Project Settings → Environment Variables
- Add all
NEXT_PUBLIC_*variables - Redeploy
-
Add Custom Domain
- Project Settings → Domains
- Add
app1.example.com - Configure DNS as instructed
Pros:
- Simple configuration
- Branch previews
- Form handling
- Edge functions
Steps:
-
Build Configuration (
netlify.toml):[build] command = "pnpm build" publish = ".next" [build.environment] NODE_VERSION = "20"
-
Deploy
netlify deploy --prod --dir=.next
-
Configure Domain
- Domain settings → Add domain
- Configure DNS
Pros:
- Full control
- Consistent environments
- Easy scaling
- Multi-platform support
Docker Compose (docker-compose.yml):
version: '3.8'
services:
frontend:
build: .
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_GRAPHQL_URL=https://app1.example.com/v1/graphql
- NEXT_PUBLIC_AUTH_URL=https://app1.example.com/auth
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/ssl
depends_on:
- frontend
restart: unless-stoppedPros:
- Production-grade orchestration
- Auto-scaling
- High availability
- Rolling updates
Deployment (deploy/k8s/frontend.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: nself-chat-frontend
namespace: nself-chat
spec:
replicas: 3
selector:
matchLabels:
app: nself-chat-frontend
template:
metadata:
labels:
app: nself-chat-frontend
spec:
containers:
- name: frontend
image: nself-chat:latest
ports:
- containerPort: 3000
env:
- name: NEXT_PUBLIC_GRAPHQL_URL
value: "https://app1.example.com/v1/graphql"
- name: NEXT_PUBLIC_AUTH_URL
value: "https://app1.example.com/auth"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: nself-chat-frontend
namespace: nself-chat
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 3000
selector:
app: nself-chat-frontendSee Environment-Variables.md for complete list.
Critical Variables:
| Variable | Required | Example | Description |
|---|---|---|---|
NEXT_PUBLIC_GRAPHQL_URL |
Yes | https://app1.example.com/v1/graphql |
GraphQL endpoint |
NEXT_PUBLIC_AUTH_URL |
Yes | https://app1.example.com/auth |
Auth service URL |
NEXT_PUBLIC_ENV |
Yes | production |
Environment |
POSTGRES_PASSWORD |
Yes | secure_password_123 |
Database password |
HASURA_GRAPHQL_ADMIN_SECRET |
Yes | your_admin_secret |
Hasura admin secret |
Symptoms: GraphQL errors, authentication failures
Solutions:
-
Check CORS configuration
curl -I https://app1.example.com/v1/graphql
-
Verify environment variables
# In frontend container env | grep NEXT_PUBLIC
-
Check network connectivity
# From frontend container curl https://app1.example.com/v1/graphql
Symptoms: Browser shows "Not Secure", HTTPS errors
Solutions:
-
Verify certificate installation
sudo certbot certificates
-
Check Nginx configuration
sudo nginx -t
-
Renew certificate
sudo certbot renew
Symptoms: Backend services crash, connection errors
Solutions:
-
Check PostgreSQL status
# Docker docker ps | grep postgres # System service sudo systemctl status postgresql
-
Verify credentials
# Test connection psql -h localhost -U postgres -d nself_chat -
Check firewall
sudo ufw status sudo ufw allow 5432/tcp
Symptoms: Container crashes, build failures
Solutions:
-
Increase Docker memory
# Docker Desktop → Settings → Resources # Set memory to 4GB+
-
Optimize build
# Use multi-stage builds (already in Dockerfile) # Clear build cache docker builder prune
Symptoms: Pages load slowly, timeouts
Solutions:
-
Enable caching
# In Nginx config location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control "public, immutable"; }
-
Use CDN
- Cloudflare (free tier available)
- AWS CloudFront
- Fastly
-
Optimize images
// Use Next.js Image component (already used) import Image from 'next/image'
| Service | Provider | Cost |
|---|---|---|
| Frontend | Vercel Hobby | $0/mo |
| Backend | DigitalOcean Droplet | $12/mo |
| Database | Included | $0/mo |
| Storage | DigitalOcean Spaces | $5/mo |
| Domain | Namecheap | $12/year |
| SSL | Let's Encrypt | $0/mo |
| Total | ~$18/month |
| Service | Provider | Cost |
|---|---|---|
| Frontend | Vercel Pro | $20/mo |
| Backend | DigitalOcean 4GB | $24/mo |
| Database | Managed PostgreSQL | $15/mo |
| Storage | DigitalOcean Spaces | $5/mo |
| CDN | Cloudflare Pro | $20/mo |
| Monitoring | Sentry Team | $26/mo |
| Total | ~$110/month |
| Service | Provider | Cost |
|---|---|---|
| Frontend | Vercel Enterprise | $150/mo |
| Backend | Kubernetes (3 nodes) | $150/mo |
| Database | RDS PostgreSQL | $100/mo |
| Storage | S3 + CloudFront | $50/mo |
| Monitoring | DataDog | $150/mo |
| Total | ~$600/month |
- SSL/TLS enabled (HTTPS only)
- Strong database password
- Hasura admin secret set
- JWT secret configured
- CORS properly configured
- Environment variables secured
- Firewall configured
- Regular backups enabled
- Monitoring and alerting setup
- Security headers configured
- Rate limiting enabled
- DDoS protection (Cloudflare)
- Setup Monitoring: Monitoring.md
- Configure Backups: Backup-Strategy.md
- Performance Tuning: Performance-Optimization.md
- Scaling Guide: Scaling-Guide.md
- nSelf CLI Documentation
- Vercel Documentation
- Netlify Documentation
- Docker Documentation
- Kubernetes Documentation
- Let's Encrypt Documentation
Need Help?
- GitHub Issues: https://github.com/yourusername/nself-chat/issues
- Community Discord: https://discord.gg/nself
- Documentation: https://docs.nself.org