feat: update after deploy
This commit is contained in:
parent
b9c998f33d
commit
970a0f75c6
46
CLAUDE.md
46
CLAUDE.md
|
|
@ -300,6 +300,52 @@ curl -X POST http://localhost:3000/api/upload \
|
|||
- **Rate Limits**: 100 requests per hour per key
|
||||
- **Revocation**: Soft delete via `is_active` flag
|
||||
|
||||
## Production Deployment
|
||||
|
||||
### VPS Infrastructure
|
||||
|
||||
Banatie is deployed as an isolated ecosystem on VPS at `/opt/banatie/`:
|
||||
|
||||
| Service | URL | Container |
|
||||
|---------|-----|-----------|
|
||||
| Landing | https://banatie.app | banatie-landing |
|
||||
| API | https://api.banatie.app | banatie-api |
|
||||
| MinIO Console | https://storage.banatie.app | banatie-minio |
|
||||
| MinIO CDN | https://cdn.banatie.app | banatie-minio |
|
||||
|
||||
### Deploy Scripts
|
||||
|
||||
```bash
|
||||
# From project root
|
||||
./scripts/deploy-landing.sh # Deploy landing
|
||||
./scripts/deploy-landing.sh --no-cache # Force rebuild (when deps change)
|
||||
./scripts/deploy-api.sh # Deploy API
|
||||
./scripts/deploy-api.sh --no-cache # Force rebuild
|
||||
```
|
||||
|
||||
### Production Configuration Files
|
||||
|
||||
```
|
||||
infrastructure/
|
||||
├── docker-compose.production.yml # VPS docker-compose
|
||||
├── .env.example # Environment variables template
|
||||
└── secrets.env.example # Secrets template
|
||||
```
|
||||
|
||||
### Key Production Learnings
|
||||
|
||||
1. **NEXT_PUBLIC_* variables** - Must be set at build time AND runtime for Next.js client-side code
|
||||
2. **pnpm workspaces in Docker** - Symlinks break between stages; use single-stage install with `pnpm --filter`
|
||||
3. **Docker User NS Remapping** - VPS uses UID offset 165536; container UID 1001 → host UID 166537
|
||||
4. **DATABASE_URL encoding** - Special characters like `=` must be URL-encoded (`%3D`)
|
||||
|
||||
### Known Production Issues (Non-Critical)
|
||||
|
||||
1. **Healthcheck showing "unhealthy"** - Alpine images lack curl; services work correctly
|
||||
2. **Next.js cache permission** - `.next/cache` may show EACCES; non-critical for functionality
|
||||
|
||||
See [docs/deployment.md](docs/deployment.md) for full deployment guide.
|
||||
|
||||
## Development Notes
|
||||
|
||||
- Uses pnpm workspaces for monorepo management (required >= 8.0.0)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,215 @@
|
|||
# Banatie Production Deployment Guide
|
||||
|
||||
> Last Updated: December 23, 2025
|
||||
|
||||
This guide covers deploying Banatie to a VPS with Docker. For local development, see [environment.md](./environment.md).
|
||||
|
||||
## Overview
|
||||
|
||||
Banatie is deployed as an isolated ecosystem with:
|
||||
|
||||
- **Landing** (Next.js 15.5.9) → banatie.app
|
||||
- **API** (Express.js) → api.banatie.app
|
||||
- **PostgreSQL** (15-alpine) → Database
|
||||
- **MinIO** (SNMD mode) → Object storage
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- VPS with Docker and Docker Compose
|
||||
- Caddy reverse proxy (or similar) with SSL
|
||||
- DNS records configured
|
||||
- GEMINI_API_KEY from Google AI Studio
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# 1. Create directory structure
|
||||
sudo mkdir -p /opt/banatie/{data,logs,scripts}
|
||||
sudo mkdir -p /opt/banatie/data/{postgres,minio,waitlist-logs,api-results,api-uploads}
|
||||
sudo mkdir -p /opt/banatie/data/minio/{drive1,drive2,drive3,drive4}
|
||||
sudo chown -R $USER:$USER /opt/banatie
|
||||
|
||||
# 2. Clone repository
|
||||
git clone <repo> ~/workspace/projects/banatie-service
|
||||
|
||||
# 3. Copy production configs
|
||||
cp ~/workspace/projects/banatie-service/infrastructure/docker-compose.production.yml /opt/banatie/docker-compose.yml
|
||||
cp ~/workspace/projects/banatie-service/infrastructure/.env.example /opt/banatie/.env
|
||||
cp ~/workspace/projects/banatie-service/infrastructure/secrets.env.example /opt/banatie/secrets.env
|
||||
cp ~/workspace/projects/banatie-service/infrastructure/init-db.sql /opt/banatie/scripts/
|
||||
|
||||
# 4. Configure environment
|
||||
nano /opt/banatie/.env # Edit public variables
|
||||
nano /opt/banatie/secrets.env # Generate and add secrets
|
||||
chmod 600 /opt/banatie/secrets.env
|
||||
|
||||
# 5. Build and start
|
||||
cd /opt/banatie
|
||||
docker compose --env-file .env --env-file secrets.env build
|
||||
docker compose --env-file .env --env-file secrets.env up -d
|
||||
|
||||
# 6. Initialize database schema
|
||||
cd ~/workspace/projects/banatie-service
|
||||
pnpm install
|
||||
pnpm --filter @banatie/database db:push
|
||||
|
||||
# 7. Create master API key
|
||||
curl -X POST https://api.banatie.app/api/bootstrap/initial-key
|
||||
# Or use UI: https://banatie.app/admin/master/
|
||||
```
|
||||
|
||||
## Deploy Scripts
|
||||
|
||||
Located in `scripts/` directory:
|
||||
|
||||
```bash
|
||||
# Deploy landing page
|
||||
./scripts/deploy-landing.sh # Normal deploy
|
||||
./scripts/deploy-landing.sh --no-cache # Fresh build (when deps change)
|
||||
|
||||
# Deploy API
|
||||
./scripts/deploy-api.sh # Normal deploy
|
||||
./scripts/deploy-api.sh --no-cache # Fresh build
|
||||
```
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### Environment Variables (.env)
|
||||
|
||||
```bash
|
||||
NODE_ENV=production
|
||||
PORT=3000
|
||||
POSTGRES_DB=banatie_db
|
||||
POSTGRES_USER=banatie_user
|
||||
DATABASE_URL=postgresql://banatie_user:<password>@banatie-postgres:5432/banatie_db
|
||||
MINIO_ENDPOINT=banatie-minio:9000
|
||||
MINIO_PUBLIC_URL=https://cdn.banatie.app
|
||||
API_PUBLIC_URL=https://api.banatie.app
|
||||
NEXT_PUBLIC_API_URL=https://api.banatie.app
|
||||
CORS_ORIGIN=https://banatie.app,https://api.banatie.app
|
||||
```
|
||||
|
||||
### Secrets (secrets.env)
|
||||
|
||||
```bash
|
||||
POSTGRES_PASSWORD=<generated>
|
||||
MINIO_ROOT_USER=banatie_admin
|
||||
MINIO_ROOT_PASSWORD=<generated>
|
||||
MINIO_ACCESS_KEY=banatie_service
|
||||
MINIO_SECRET_KEY=<generated>
|
||||
GEMINI_API_KEY=<your-key>
|
||||
JWT_SECRET=<generated>
|
||||
SESSION_SECRET=<generated>
|
||||
```
|
||||
|
||||
Generate secrets with:
|
||||
```bash
|
||||
openssl rand -base64 32 | tr -d '\n\r '
|
||||
```
|
||||
|
||||
## DNS Configuration
|
||||
|
||||
| Type | Name | Value |
|
||||
|------|------|-------|
|
||||
| A | @ | VPS_IP |
|
||||
| CNAME | www | banatie.app |
|
||||
| CNAME | api | banatie.app |
|
||||
| CNAME | storage | banatie.app |
|
||||
| CNAME | cdn | banatie.app |
|
||||
|
||||
## Caddy Configuration
|
||||
|
||||
Add to your Caddyfile:
|
||||
|
||||
```caddy
|
||||
www.banatie.app {
|
||||
redir https://banatie.app{uri} permanent
|
||||
}
|
||||
|
||||
banatie.app {
|
||||
reverse_proxy banatie-landing:3000
|
||||
}
|
||||
|
||||
api.banatie.app {
|
||||
reverse_proxy banatie-api:3000
|
||||
}
|
||||
|
||||
storage.banatie.app {
|
||||
reverse_proxy banatie-minio:9001
|
||||
}
|
||||
|
||||
cdn.banatie.app {
|
||||
reverse_proxy banatie-minio:9000
|
||||
header Access-Control-Allow-Origin "*"
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Permission Denied on Volumes
|
||||
|
||||
Docker User Namespace Remapping offsets UIDs by 165536:
|
||||
|
||||
```bash
|
||||
# Fix permissions for Next.js (uid 1001 → 166537)
|
||||
sudo chown -R 166537:166537 /opt/banatie/data/waitlist-logs
|
||||
|
||||
# Fix permissions for API (uid 1001 → 166537)
|
||||
sudo chown -R 166537:166537 /opt/banatie/data/api-results
|
||||
sudo chown -R 166537:166537 /opt/banatie/data/api-uploads
|
||||
```
|
||||
|
||||
### Environment Variables Not Applied
|
||||
|
||||
Use `docker compose up -d` instead of `docker restart`:
|
||||
|
||||
```bash
|
||||
docker compose --env-file .env --env-file secrets.env up -d banatie-api
|
||||
```
|
||||
|
||||
### NEXT_PUBLIC_* Variables
|
||||
|
||||
Must be set at both build time AND runtime. Ensure `NEXT_PUBLIC_API_URL` is in .env before building.
|
||||
|
||||
### pnpm Workspace Symlinks in Docker
|
||||
|
||||
The Dockerfiles use simplified single-stage install to avoid symlink issues:
|
||||
|
||||
```dockerfile
|
||||
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||
COPY apps/landing ./apps/landing
|
||||
COPY packages/database ./packages/database
|
||||
RUN pnpm install --frozen-lockfile
|
||||
RUN pnpm --filter @banatie/landing build
|
||||
```
|
||||
|
||||
### Database Connection Refused
|
||||
|
||||
URL-encode special characters in DATABASE_URL:
|
||||
- `=` → `%3D`
|
||||
- `@` → `%40`
|
||||
- `#` → `%23`
|
||||
|
||||
## Known Issues
|
||||
|
||||
### Healthcheck Showing "Unhealthy"
|
||||
|
||||
Alpine images don't have `curl` by default. The healthcheck uses `wget` but may still show unhealthy in some cases. Services work correctly despite this status.
|
||||
|
||||
### Next.js Cache Permission Warning
|
||||
|
||||
```
|
||||
EACCES: permission denied, mkdir '/app/apps/landing/.next/cache'
|
||||
```
|
||||
|
||||
This is non-critical - images still work, just not cached. To fix:
|
||||
```bash
|
||||
sudo chown -R 166537:166537 /opt/banatie/data/landing-cache
|
||||
# And add volume mount for .next/cache
|
||||
```
|
||||
|
||||
## Full VPS Documentation
|
||||
|
||||
For complete VPS setup and infrastructure details, see:
|
||||
- VPS Repository: `VPS/docs/banatie-deployment.md`
|
||||
- Deployment Manual: `VPS/manuals/banatie-service-deployment.md`
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
# Banatie Production Environment Variables
|
||||
# ==========================================
|
||||
# Copy this file to .env and fill in the values
|
||||
#
|
||||
# Location on VPS: /opt/banatie/.env
|
||||
# Last Updated: December 23, 2025
|
||||
|
||||
# ----------------------------------------
|
||||
# Node.js Configuration
|
||||
# ----------------------------------------
|
||||
NODE_ENV=production
|
||||
PORT=3000
|
||||
|
||||
# ----------------------------------------
|
||||
# PostgreSQL Database
|
||||
# ----------------------------------------
|
||||
POSTGRES_DB=banatie_db
|
||||
POSTGRES_USER=banatie_user
|
||||
# Note: POSTGRES_PASSWORD is in secrets.env
|
||||
|
||||
# DATABASE_URL for application use
|
||||
# IMPORTANT: URL-encode special characters (e.g., = → %3D, @ → %40)
|
||||
# Example: DATABASE_URL=postgresql://banatie_user:MyP%3Dssword@banatie-postgres:5432/banatie_db
|
||||
DATABASE_URL=postgresql://banatie_user:<url-encoded-password>@banatie-postgres:5432/banatie_db
|
||||
|
||||
# ----------------------------------------
|
||||
# MinIO Object Storage
|
||||
# ----------------------------------------
|
||||
MINIO_ENDPOINT=banatie-minio:9000
|
||||
MINIO_BUCKET_NAME=banatie
|
||||
MINIO_USE_SSL=false
|
||||
STORAGE_TYPE=minio
|
||||
|
||||
# Public URL for CDN access (used in API responses)
|
||||
MINIO_PUBLIC_URL=https://cdn.banatie.app
|
||||
|
||||
# ----------------------------------------
|
||||
# API Configuration
|
||||
# ----------------------------------------
|
||||
API_BASE_URL=https://api.banatie.app
|
||||
API_PUBLIC_URL=https://api.banatie.app
|
||||
|
||||
# IMPORTANT: This must be set for Next.js client-side code
|
||||
NEXT_PUBLIC_API_URL=https://api.banatie.app
|
||||
|
||||
# ----------------------------------------
|
||||
# CORS Configuration
|
||||
# ----------------------------------------
|
||||
# Comma-separated list of allowed origins
|
||||
CORS_ORIGIN=https://banatie.app,https://api.banatie.app
|
||||
|
||||
# ----------------------------------------
|
||||
# Multi-tenancy Defaults
|
||||
# ----------------------------------------
|
||||
DEFAULT_ORG_ID=default
|
||||
DEFAULT_PROJECT_ID=main
|
||||
DEFAULT_USER_ID=system
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
# Banatie Infrastructure
|
||||
|
||||
Production deployment configuration files for VPS.
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `docker-compose.production.yml` | Docker Compose for VPS deployment |
|
||||
| `.env.example` | Environment variables template |
|
||||
| `secrets.env.example` | Secrets template (passwords, API keys) |
|
||||
| `init-db.sql` | PostgreSQL initialization (grants permissions) |
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Copy to VPS
|
||||
scp -r infrastructure/* usul-vps:/opt/banatie/
|
||||
|
||||
# On VPS
|
||||
cd /opt/banatie
|
||||
cp docker-compose.production.yml docker-compose.yml
|
||||
cp .env.example .env
|
||||
cp secrets.env.example secrets.env
|
||||
cp init-db.sql scripts/
|
||||
|
||||
# Edit configuration
|
||||
nano .env
|
||||
nano secrets.env
|
||||
chmod 600 secrets.env
|
||||
|
||||
# Deploy
|
||||
docker compose --env-file .env --env-file secrets.env up -d
|
||||
```
|
||||
|
||||
## VPS Directory Structure
|
||||
|
||||
```
|
||||
/opt/banatie/
|
||||
├── docker-compose.yml # Copy from docker-compose.production.yml
|
||||
├── .env # Copy from .env.example and configure
|
||||
├── secrets.env # Copy from secrets.env.example and configure
|
||||
├── scripts/
|
||||
│ └── init-db.sql # Copy from init-db.sql
|
||||
├── data/
|
||||
│ ├── postgres/ # PostgreSQL data (DO NOT CREATE MANUALLY)
|
||||
│ ├── minio/ # MinIO drives (DO NOT CREATE MANUALLY)
|
||||
│ ├── waitlist-logs/
|
||||
│ ├── api-results/
|
||||
│ └── api-uploads/
|
||||
└── logs/
|
||||
└── api/
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
1. **Docker User NS Remapping**: VPS uses UID offset 165536. Let Docker create data directories.
|
||||
2. **Secrets**: Never commit secrets.env to git. Use `chmod 600`.
|
||||
3. **Database**: Tables are created by Drizzle ORM, not init-db.sql.
|
||||
|
||||
## Documentation
|
||||
|
||||
- Full guide: [docs/deployment.md](../docs/deployment.md)
|
||||
- VPS docs: VPS repo `docs/banatie-deployment.md`
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
# Banatie Production - VPS Isolated Deployment
|
||||
# ============================================
|
||||
# This is the production docker-compose file used on VPS at /opt/banatie/
|
||||
# Last Updated: December 23, 2025
|
||||
#
|
||||
# Usage:
|
||||
# docker compose --env-file .env --env-file secrets.env up -d
|
||||
# docker compose --env-file .env --env-file secrets.env build --no-cache
|
||||
#
|
||||
# Key differences from dev:
|
||||
# - Uses external proxy-network for Caddy integration
|
||||
# - All services isolated in banatie-internal network
|
||||
# - MinIO with 4 drives for full S3 compatibility
|
||||
# - Secrets stored in separate secrets.env file
|
||||
|
||||
services:
|
||||
# ----------------------------------------
|
||||
# API Service - Express.js REST API
|
||||
# ----------------------------------------
|
||||
banatie-api:
|
||||
build:
|
||||
context: /home/usul/workspace/projects/banatie-service
|
||||
dockerfile: apps/api-service/Dockerfile
|
||||
target: production
|
||||
container_name: banatie-api
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- banatie-internal
|
||||
- proxy-network
|
||||
depends_on:
|
||||
banatie-postgres:
|
||||
condition: service_healthy
|
||||
banatie-minio:
|
||||
condition: service_healthy
|
||||
env_file:
|
||||
- .env
|
||||
- secrets.env
|
||||
environment:
|
||||
- IS_DOCKER=true
|
||||
- NODE_ENV=production
|
||||
volumes:
|
||||
- ./logs/api:/app/apps/api-service/logs
|
||||
- ./data/api-results:/app/results
|
||||
- ./data/api-uploads:/app/uploads
|
||||
healthcheck:
|
||||
# Note: Alpine images don't have curl by default
|
||||
# Using wget instead, but may still show "unhealthy" - service works correctly
|
||||
test: ["CMD", "wget", "--spider", "-q", "http://localhost:3000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
|
||||
# ----------------------------------------
|
||||
# Landing Page - Next.js 15.5.9
|
||||
# ----------------------------------------
|
||||
banatie-landing:
|
||||
build:
|
||||
context: /home/usul/workspace/projects/banatie-service
|
||||
dockerfile: apps/landing/Dockerfile
|
||||
container_name: banatie-landing
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- banatie-internal
|
||||
- proxy-network
|
||||
depends_on:
|
||||
- banatie-postgres
|
||||
env_file:
|
||||
- .env
|
||||
- secrets.env
|
||||
environment:
|
||||
- IS_DOCKER=true
|
||||
- NODE_ENV=production
|
||||
- HOSTNAME=0.0.0.0
|
||||
- WAITLIST_LOGS_PATH=/app/waitlist-logs
|
||||
volumes:
|
||||
- ./data/waitlist-logs:/app/waitlist-logs
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "-q", "http://localhost:3000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
# ----------------------------------------
|
||||
# PostgreSQL Database
|
||||
# ----------------------------------------
|
||||
banatie-postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: banatie-postgres
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- banatie-internal
|
||||
volumes:
|
||||
- ./data/postgres:/var/lib/postgresql/data
|
||||
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/01-init.sql:ro
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB}
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
# ----------------------------------------
|
||||
# MinIO Object Storage (S3-compatible)
|
||||
# ----------------------------------------
|
||||
banatie-minio:
|
||||
image: quay.io/minio/minio:latest
|
||||
container_name: banatie-minio
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- banatie-internal
|
||||
- proxy-network
|
||||
volumes:
|
||||
# 4 drives for SNMD mode (full S3 compatibility)
|
||||
- ./data/minio/drive1:/data1
|
||||
- ./data/minio/drive2:/data2
|
||||
- ./data/minio/drive3:/data3
|
||||
- ./data/minio/drive4:/data4
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||
MINIO_BROWSER_REDIRECT_URL: https://storage.banatie.app
|
||||
MINIO_SERVER_URL: https://cdn.banatie.app
|
||||
command: server /data{1...4} --console-address ":9001"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
# ----------------------------------------
|
||||
# Storage Initialization (runs once)
|
||||
# ----------------------------------------
|
||||
banatie-storage-init:
|
||||
image: minio/mc:latest
|
||||
container_name: banatie-storage-init
|
||||
networks:
|
||||
- banatie-internal
|
||||
depends_on:
|
||||
banatie-minio:
|
||||
condition: service_healthy
|
||||
env_file:
|
||||
- secrets.env
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
echo '=== MinIO Storage Initialization ==='
|
||||
mc alias set storage http://banatie-minio:9000 $${MINIO_ROOT_USER} $${MINIO_ROOT_PASSWORD}
|
||||
mc mb --ignore-existing storage/banatie
|
||||
mc admin user add storage $${MINIO_ACCESS_KEY} $${MINIO_SECRET_KEY} || echo 'User may already exist'
|
||||
mc admin policy attach storage readwrite --user=$${MINIO_ACCESS_KEY} || echo 'Policy may already be attached'
|
||||
cat > /tmp/lifecycle.json <<'LCEOF'
|
||||
{"Rules":[{"ID":"temp-cleanup","Status":"Enabled","Filter":{"Prefix":"temp/"},"Expiration":{"Days":7}}]}
|
||||
LCEOF
|
||||
mc ilm import storage/banatie < /tmp/lifecycle.json || echo 'Lifecycle policy may already exist'
|
||||
echo '=== Storage Initialization Completed ==='
|
||||
exit 0
|
||||
restart: "no"
|
||||
|
||||
# ----------------------------------------
|
||||
# Networks
|
||||
# ----------------------------------------
|
||||
networks:
|
||||
# Internal network for service communication
|
||||
# internal: true means no outbound access
|
||||
banatie-internal:
|
||||
driver: bridge
|
||||
internal: true
|
||||
|
||||
# External network shared with Caddy reverse proxy
|
||||
# Must be created by Caddy's docker-compose first
|
||||
proxy-network:
|
||||
name: services_proxy-network
|
||||
external: true
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
-- Banatie PostgreSQL 15 Permission Fix
|
||||
-- =====================================
|
||||
-- This script runs only on first PostgreSQL startup.
|
||||
-- It grants necessary permissions for the Drizzle ORM to create tables.
|
||||
--
|
||||
-- Note: Actual tables are created by Drizzle ORM during deployment:
|
||||
-- pnpm --filter @banatie/database db:push
|
||||
--
|
||||
-- PostgreSQL 15+ removed default CREATE privileges on public schema for security.
|
||||
-- This script restores those privileges for the service user.
|
||||
|
||||
-- Grant CREATE permission on public schema
|
||||
GRANT CREATE ON SCHEMA public TO banatie_user;
|
||||
GRANT ALL ON SCHEMA public TO banatie_user;
|
||||
|
||||
-- Log completion
|
||||
DO $$
|
||||
BEGIN
|
||||
RAISE NOTICE 'Banatie database initialized. Run db:push to create tables.';
|
||||
END $$;
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
# Banatie Production Secrets
|
||||
# ==========================
|
||||
# NEVER COMMIT THIS FILE TO GIT!
|
||||
#
|
||||
# Copy this file to secrets.env and generate real values
|
||||
# Location on VPS: /opt/banatie/secrets.env
|
||||
# Permissions: chmod 600 secrets.env
|
||||
#
|
||||
# Last Updated: December 23, 2025
|
||||
|
||||
# ----------------------------------------
|
||||
# PostgreSQL Secrets
|
||||
# ----------------------------------------
|
||||
# Generate: openssl rand -base64 32 | tr -d '\n\r '
|
||||
POSTGRES_PASSWORD=<generate-strong-password>
|
||||
|
||||
# ----------------------------------------
|
||||
# MinIO Root Credentials
|
||||
# ----------------------------------------
|
||||
# Root user for MinIO admin console
|
||||
MINIO_ROOT_USER=banatie_admin
|
||||
# Generate: openssl rand -base64 32 | tr -d '\n\r '
|
||||
MINIO_ROOT_PASSWORD=<generate-strong-password>
|
||||
|
||||
# ----------------------------------------
|
||||
# MinIO Service Account
|
||||
# ----------------------------------------
|
||||
# Service account for API access to MinIO
|
||||
MINIO_ACCESS_KEY=banatie_service
|
||||
# Generate: openssl rand -base64 32 | tr -d '\n\r '
|
||||
MINIO_SECRET_KEY=<generate-strong-password>
|
||||
|
||||
# ----------------------------------------
|
||||
# API Secrets
|
||||
# ----------------------------------------
|
||||
# Google Gemini API key for image generation
|
||||
# Get from: https://aistudio.google.com/app/apikey
|
||||
GEMINI_API_KEY=<your-gemini-api-key>
|
||||
|
||||
# JWT secret for token signing
|
||||
# Generate: openssl rand -base64 64 | tr -d '\n\r '
|
||||
JWT_SECRET=<generate-strong-secret>
|
||||
|
||||
# Session secret for Express sessions
|
||||
# Generate: openssl rand -base64 32 | tr -d '\n\r '
|
||||
SESSION_SECRET=<generate-strong-secret>
|
||||
|
||||
# ----------------------------------------
|
||||
# Quick Generation Script
|
||||
# ----------------------------------------
|
||||
# Run this to generate all secrets:
|
||||
#
|
||||
# echo "POSTGRES_PASSWORD=$(openssl rand -base64 32 | tr -d '\n\r ')"
|
||||
# echo "MINIO_ROOT_USER=banatie_admin"
|
||||
# echo "MINIO_ROOT_PASSWORD=$(openssl rand -base64 32 | tr -d '\n\r ')"
|
||||
# echo "MINIO_ACCESS_KEY=banatie_service"
|
||||
# echo "MINIO_SECRET_KEY=$(openssl rand -base64 32 | tr -d '\n\r ')"
|
||||
# echo "JWT_SECRET=$(openssl rand -base64 64 | tr -d '\n\r ')"
|
||||
# echo "SESSION_SECRET=$(openssl rand -base64 32 | tr -d '\n\r ')"
|
||||
# echo "GEMINI_API_KEY=<add-manually>"
|
||||
|
|
@ -23,7 +23,8 @@
|
|||
"clean": "pnpm -r clean && rm -rf node_modules",
|
||||
"deploy:landing": "./scripts/deploy-landing.sh",
|
||||
"deploy:landing:no-cache": "./scripts/deploy-landing.sh --no-cache",
|
||||
"deploy:api": "./scripts/deploy-landing.sh"
|
||||
"deploy:api": "./scripts/deploy-api.sh",
|
||||
"deploy:api:no-cache": "./scripts/deploy-api.sh --no-cache"
|
||||
},
|
||||
"keywords": [
|
||||
"monorepo",
|
||||
|
|
|
|||
Loading…
Reference in New Issue