Fix: Remove hardcoded UUIDs and secrets from deploy scripts
- deploy.py: UUIDs from env vars or Coolify API lookup by name - fast-deploy.sh: No hardcoded UUIDs, APP_DOMAIN from env - docker-compose.yml: All secrets from env vars, no hardcoded values - .env.example: All required vars documented - Deleted obsolete fast-frontend-deploy.sh with hardcoded container name
This commit is contained in:
+109
-44
@@ -1,48 +1,94 @@
|
|||||||
# LeoCRM v1.0 - Environment Variables Template
|
# LeoCRM - Environment Variables Template
|
||||||
|
# Copy to .env and fill in real values.
|
||||||
|
|
||||||
# === REQUIRED ===
|
# === COOLIFY DEPLOYMENT (required for scripts/deploy.py) ===
|
||||||
DATABASE_URL=postgresql+asyncpg://crm_api:your_password@localhost:5432/crm_db
|
# Coolify API token (required for deploy)
|
||||||
AUTH_DATABASE_URL=postgresql+asyncpg://crm_auth:your_password@localhost:5432/crm_db
|
COOLIFY_API_TOKEN=
|
||||||
WORKER_DATABASE_URL=postgresql+asyncpg://crm_worker:your_password@localhost:5432/crm_db
|
# Coolify base URL
|
||||||
MIGRATION_DATABASE_URL=postgresql+asyncpg://crm_migration:your_password@localhost:5432/crm_db
|
COOLIFY_BASE_URL=https://server.media-on.de
|
||||||
REDIS_URL=redis://localhost:6379/0
|
# Application UUID (optional — resolved via API lookup by APP_NAME if absent)
|
||||||
|
COOLIFY_APP_UUID=
|
||||||
|
# Worker Service UUID (optional — resolved via API lookup by WORKER_NAME if absent)
|
||||||
|
COOLIFY_WORKER_UUID=
|
||||||
|
# Application name for API lookup
|
||||||
|
APP_NAME=leocrm-api
|
||||||
|
# Worker name for API lookup
|
||||||
|
WORKER_NAME=leocrm-worker
|
||||||
|
# App domain (required for deploy, used for health check and FQDN)
|
||||||
|
APP_DOMAIN=https://crm.media-on.de
|
||||||
|
|
||||||
# === REQUIRED for Docker/Production ===
|
# === COOLIFY INITIAL DEPLOY (only needed for --initial) ===
|
||||||
# Redis password (required in Docker)
|
# Coolify project UUID
|
||||||
REDIS_PASSWORD=your_redis_password
|
COOLIFY_PROJECT_UUID=
|
||||||
|
# Coolify server UUID
|
||||||
|
COOLIFY_SERVER_UUID=
|
||||||
|
# Coolify private key UUID (for Git deploy key)
|
||||||
|
COOLIFY_PRIVATE_KEY_UUID=
|
||||||
|
# Coolify environment name
|
||||||
|
COOLIFY_ENVIRONMENT=production
|
||||||
|
|
||||||
# === OPTIONAL (with defaults) ===
|
# === DATABASE (required) ===
|
||||||
|
# Single password for all DB roles (crm_user, crm_api, crm_auth, crm_worker, crm_migration)
|
||||||
|
DB_PASSWORD=
|
||||||
|
# Database name
|
||||||
|
POSTGRES_DB=crm_db
|
||||||
|
# Database user (superuser/owner)
|
||||||
|
POSTGRES_USER=crm_user
|
||||||
|
# Database host (container name in Docker network)
|
||||||
|
DB_HOST=crm-postgres
|
||||||
|
# Full database URLs (constructed from DB_PASSWORD/DB_HOST if not set explicitly)
|
||||||
|
DATABASE_URL=postgresql+asyncpg://crm_api:${DB_PASSWORD}@crm-postgres:5432/${POSTGRES_DB}
|
||||||
|
AUTH_DATABASE_URL=postgresql+asyncpg://crm_auth:${DB_PASSWORD}@crm-postgres:5432/${POSTGRES_DB}
|
||||||
|
WORKER_DATABASE_URL=postgresql+asyncpg://crm_worker:${DB_PASSWORD}@crm-postgres:5432/${POSTGRES_DB}
|
||||||
|
MIGRATION_DATABASE_URL=postgresql+asyncpg://crm_migration:${DB_PASSWORD}@crm-postgres:5432/${POSTGRES_DB}
|
||||||
|
|
||||||
|
# === REDIS (required) ===
|
||||||
|
REDIS_PASSWORD=
|
||||||
|
REDIS_HOST=crm-redis
|
||||||
|
REDIS_URL=redis://:${REDIS_PASSWORD}@crm-redis:6379/0
|
||||||
|
|
||||||
|
# === SECURITY (required) ===
|
||||||
|
# Secret key for signing, sessions (use a secure random string >= 32 chars)
|
||||||
|
SECRET_KEY=
|
||||||
|
|
||||||
|
# === SSH VERIFICATION (optional, deploy.py verification only) ===
|
||||||
|
SSH_KEY=/a0/usr/workdir/.ssh/coolify-01-root
|
||||||
|
SERVER_IP=46.225.91.159
|
||||||
|
# Login test credentials (optional, for deploy verification)
|
||||||
|
LOGIN_EMAIL=
|
||||||
|
LOGIN_PASSWORD=
|
||||||
|
|
||||||
|
# === APPLICATION ===
|
||||||
# Environment: development | production | testing
|
# Environment: development | production | testing
|
||||||
ENVIRONMENT=development
|
ENVIRONMENT=production
|
||||||
|
|
||||||
# Log level: DEBUG | INFO | WARNING | ERROR
|
# Log level: DEBUG | INFO | WARNING | ERROR
|
||||||
LOG_LEVEL=INFO
|
LOG_LEVEL=INFO
|
||||||
|
|
||||||
# Database pool
|
|
||||||
DB_POOL_SIZE=10
|
|
||||||
DB_MAX_OVERFLOW=20
|
|
||||||
DB_ECHO=false
|
|
||||||
|
|
||||||
# Session settings
|
|
||||||
SESSION_TTL_SECONDS=28800
|
|
||||||
SESSION_COOKIE_NAME=leocrm_session
|
|
||||||
SESSION_COOKIE_SECURE=false
|
|
||||||
SESSION_COOKIE_SAMESITE=strict
|
|
||||||
SESSION_COOKIE_HTTPONLY=true
|
|
||||||
|
|
||||||
# Password hashing
|
|
||||||
BCRYPT_ROUNDS=12
|
|
||||||
PASSWORD_RESET_EXPIRY_HOURS=1
|
|
||||||
|
|
||||||
# CORS allowed origins (comma-separated, NO wildcards)
|
# CORS allowed origins (comma-separated, NO wildcards)
|
||||||
CORS_ORIGINS=http://localhost:5173,http://localhost:3000
|
CORS_ORIGINS=https://crm.media-on.de
|
||||||
|
# Frontend URL
|
||||||
|
FRONTEND_URL=https://crm.media-on.de
|
||||||
|
# Session cookie secure (true in production)
|
||||||
|
SESSION_COOKIE_SECURE=true
|
||||||
|
|
||||||
# Secret Key (for signing, sessions — use a secure random string ≥32 chars in prod)
|
# === DOCKER COMPOSE (optional overrides) ===
|
||||||
SECRET_KEY=change-me-in-production-use-a-secure-random-string
|
# Container names
|
||||||
|
POSTGRES_CONTAINER_NAME=crm-postgres
|
||||||
|
REDIS_CONTAINER_NAME=crm-redis
|
||||||
|
APP_CONTAINER_NAME=crm-app
|
||||||
|
WORKER_CONTAINER_NAME=crm-worker
|
||||||
|
# Volume names
|
||||||
|
PGDATA_VOLUME_NAME=crm_pgdata
|
||||||
|
REDISDATA_VOLUME_NAME=crm_redisdata
|
||||||
|
STORAGE_VOLUME_NAME=crm_storage
|
||||||
|
# Network names
|
||||||
|
CRM_NETWORK_NAME=crm-net
|
||||||
|
COOLIFY_NETWORK_NAME=coolify
|
||||||
|
# Traefik host
|
||||||
|
APP_HOST=crm.media-on.de
|
||||||
|
APP_PORT=8000
|
||||||
|
|
||||||
# Storage (file uploads, DMS)
|
# === STORAGE ===
|
||||||
STORAGE_PATH=/tmp
|
STORAGE_PATH=/data/storage
|
||||||
# Storage backend: local (default) or s3
|
# Storage backend: local (default) or s3
|
||||||
STORAGE_BACKEND=local
|
STORAGE_BACKEND=local
|
||||||
# S3-compatible storage (when STORAGE_BACKEND=s3)
|
# S3-compatible storage (when STORAGE_BACKEND=s3)
|
||||||
@@ -53,15 +99,15 @@ S3_SECRET_KEY=
|
|||||||
S3_REGION=us-east-1
|
S3_REGION=us-east-1
|
||||||
S3_SECURE=true
|
S3_SECURE=true
|
||||||
|
|
||||||
# SMTP / Email
|
# === SMTP / EMAIL ===
|
||||||
SMTP_HOST=localhost
|
SMTP_HOST=localhost
|
||||||
SMTP_PORT=587
|
SMTP_PORT=587
|
||||||
SMTP_USERNAME=
|
SMTP_USER=
|
||||||
SMTP_PASSWORD=
|
SMTP_PASSWORD=
|
||||||
SMTP_FROM_EMAIL=noreply@leocrm.local
|
SMTP_FROM=no-reply@localhost
|
||||||
SMTP_USE_TLS=true
|
SMTP_TLS=true
|
||||||
|
|
||||||
# Rate limiting
|
# === RATE LIMITING ===
|
||||||
RATE_LIMIT_LOGIN_MAX=5
|
RATE_LIMIT_LOGIN_MAX=5
|
||||||
RATE_LIMIT_LOGIN_WINDOW=900
|
RATE_LIMIT_LOGIN_WINDOW=900
|
||||||
RATE_LIMIT_RESET_MAX=3
|
RATE_LIMIT_RESET_MAX=3
|
||||||
@@ -71,10 +117,29 @@ RATE_LIMIT_RESET_CONFIRM_WINDOW=3600
|
|||||||
RATE_LIMIT_GENERAL_MAX=60
|
RATE_LIMIT_GENERAL_MAX=60
|
||||||
RATE_LIMIT_GENERAL_WINDOW=60
|
RATE_LIMIT_GENERAL_WINDOW=60
|
||||||
|
|
||||||
# === AI / Search ===
|
# === DATABASE POOL ===
|
||||||
# Ollama Cloud API Key (für LiteLLM)
|
DB_POOL_SIZE=10
|
||||||
|
DB_MAX_OVERFLOW=20
|
||||||
|
DB_ECHO=false
|
||||||
|
|
||||||
|
# === SESSION ===
|
||||||
|
SESSION_TTL_SECONDS=28800
|
||||||
|
SESSION_COOKIE_NAME=leocrm_session
|
||||||
|
SESSION_COOKIE_SAMESITE=strict
|
||||||
|
SESSION_COOKIE_HTTPONLY=true
|
||||||
|
|
||||||
|
# === PASSWORD HASHING ===
|
||||||
|
BCRYPT_ROUNDS=12
|
||||||
|
PASSWORD_RESET_EXPIRY_HOURS=1
|
||||||
|
|
||||||
|
# === AI / SEARCH ===
|
||||||
|
# Ollama Cloud API Key (for LiteLLM)
|
||||||
API_KEY_OLLAMA_CLOUD=
|
API_KEY_OLLAMA_CLOUD=
|
||||||
# Embedding Modell (default: ollama/nomic-embed-text)
|
# Embedding model (default: ollama/nomic-embed-text)
|
||||||
SEARCH_EMBEDDING_MODEL=ollama/nomic-embed-text
|
SEARCH_EMBEDDING_MODEL=ollama/nomic-embed-text
|
||||||
# LLM Modell für Query Understanding (default: ollama/deepseek-v4)
|
# LLM model for query understanding (default: ollama/deepseek-v4)
|
||||||
SEARCH_LLM_MODEL=ollama/deepseek-v4
|
SEARCH_LLM_MODEL=ollama/deepseek-v4
|
||||||
|
|
||||||
|
# === GIT (for initial deployment) ===
|
||||||
|
API_GIT_REPO=https://forgejo.media-on.de/Leopoldadmin/leocrm.git
|
||||||
|
API_GIT_BRANCH=main
|
||||||
|
|||||||
+27
-25
@@ -14,10 +14,12 @@
|
|||||||
# - RLS policy enforcement
|
# - RLS policy enforcement
|
||||||
# - Health & domain verification
|
# - Health & domain verification
|
||||||
#
|
#
|
||||||
|
# No hardcoded secrets, UUIDs, or domains — everything from environment.
|
||||||
|
#
|
||||||
# Usage (local testing):
|
# Usage (local testing):
|
||||||
# cp .env.docker.example .env.docker
|
# cp .env.example .env
|
||||||
# $EDITOR .env.docker # fill SECRET_KEY, POSTGRES_PASSWORD, ...
|
# $EDITOR .env # fill SECRET_KEY, DB_PASSWORD, REDIS_PASSWORD, ...
|
||||||
# docker compose --env-file .env.docker up --build
|
# docker compose up --build
|
||||||
# curl http://localhost:8000/api/v1/health
|
# curl http://localhost:8000/api/v1/health
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
@@ -25,11 +27,11 @@ services:
|
|||||||
# ── PostgreSQL 16 with pgvector ─────────────────────────────────────
|
# ── PostgreSQL 16 with pgvector ─────────────────────────────────────
|
||||||
postgres:
|
postgres:
|
||||||
image: pgvector/pgvector:pg16
|
image: pgvector/pgvector:pg16
|
||||||
container_name: crm-postgres
|
container_name: ${POSTGRES_CONTAINER_NAME:-crm-postgres}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_USER: ${POSTGRES_USER:-crm_user}
|
POSTGRES_USER: ${POSTGRES_USER:-crm_user}
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
|
POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD is required}
|
||||||
POSTGRES_DB: ${POSTGRES_DB:-crm_db}
|
POSTGRES_DB: ${POSTGRES_DB:-crm_db}
|
||||||
PGDATA: /var/lib/postgresql/data/pgdata
|
PGDATA: /var/lib/postgresql/data/pgdata
|
||||||
volumes:
|
volumes:
|
||||||
@@ -53,7 +55,7 @@ services:
|
|||||||
# ── Redis 7 (sessions, rate limiting, ARQ queue) ────────────────────
|
# ── Redis 7 (sessions, rate limiting, ARQ queue) ────────────────────
|
||||||
redis:
|
redis:
|
||||||
image: redis:7-alpine
|
image: redis:7-alpine
|
||||||
container_name: crm-redis
|
container_name: ${REDIS_CONTAINER_NAME:-crm-redis}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: redis-server --requirepass ${REDIS_PASSWORD:?REDIS_PASSWORD is required}
|
command: redis-server --requirepass ${REDIS_PASSWORD:?REDIS_PASSWORD is required}
|
||||||
volumes:
|
volumes:
|
||||||
@@ -73,15 +75,15 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
container_name: crm-app
|
container_name: ${APP_CONTAINER_NAME:-crm-app}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.crm.rule=Host(`crm.media-on.de`)
|
- traefik.http.routers.crm.rule=Host(`${APP_HOST:-crm.media-on.de}`)
|
||||||
- traefik.http.routers.crm.entryPoints=http,https
|
- traefik.http.routers.crm.entryPoints=http,https
|
||||||
- traefik.http.routers.crm.tls=true
|
- traefik.http.routers.crm.tls=true
|
||||||
- traefik.http.routers.crm.tls.certresolver=letsencrypt
|
- traefik.http.routers.crm.tls.certresolver=letsencrypt
|
||||||
- traefik.http.services.crm.loadbalancer.server.port=8000
|
- traefik.http.services.crm.loadbalancer.server.port=${APP_PORT:-8000}
|
||||||
networks:
|
networks:
|
||||||
- crm-net
|
- crm-net
|
||||||
- coolify
|
- coolify
|
||||||
@@ -92,15 +94,15 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
# API uses crm_api (NOSUPERUSER, NOBYPASSRLS) — RLS enforced
|
# API uses crm_api (NOSUPERUSER, NOBYPASSRLS) — RLS enforced
|
||||||
DATABASE_URL: ${DATABASE_URL:?DATABASE_URL is required}
|
DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://crm_api:${DB_PASSWORD}@postgres:5432/${POSTGRES_DB:-crm_db}}
|
||||||
# Auth uses crm_auth (NOSUPERUSER, NOBYPASSRLS) — identity tables only
|
# Auth uses crm_auth (NOSUPERUSER, NOBYPASSRLS) — identity tables only
|
||||||
AUTH_DATABASE_URL: ${AUTH_DATABASE_URL:-postgresql+asyncpg://crm_auth:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-crm_db}}
|
AUTH_DATABASE_URL: ${AUTH_DATABASE_URL:-postgresql+asyncpg://crm_auth:${DB_PASSWORD}@postgres:5432/${POSTGRES_DB:-crm_db}}
|
||||||
# Migration/DDL uses crm_migration (owner, NOBYPASSRLS)
|
# Migration/DDL uses crm_migration (owner, NOBYPASSRLS)
|
||||||
MIGRATION_DATABASE_URL: ${MIGRATION_DATABASE_URL:-postgresql+asyncpg://crm_migration:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-crm_db}}
|
MIGRATION_DATABASE_URL: ${MIGRATION_DATABASE_URL:-postgresql+asyncpg://crm_migration:${DB_PASSWORD}@postgres:5432/${POSTGRES_DB:-crm_db}}
|
||||||
REDIS_URL: ${REDIS_URL:-redis://:${REDIS_PASSWORD}@redis:6379/0}
|
REDIS_URL: ${REDIS_URL:-redis://:${REDIS_PASSWORD}@redis:6379/0}
|
||||||
SECRET_KEY: ${SECRET_KEY:?SECRET_KEY is required (min 32 chars)}
|
SECRET_KEY: ${SECRET_KEY:?SECRET_KEY is required (min 32 chars)}
|
||||||
CORS_ORIGINS: ${CORS_ORIGINS:-https://crm.media-on.de}
|
CORS_ORIGINS: ${CORS_ORIGINS:-${APP_DOMAIN:-http://localhost:8000}}
|
||||||
FRONTEND_URL: ${FRONTEND_URL:-http://localhost:8000}
|
FRONTEND_URL: ${FRONTEND_URL:-${APP_DOMAIN:-http://localhost:8000}}
|
||||||
ENVIRONMENT: ${ENVIRONMENT:-production}
|
ENVIRONMENT: ${ENVIRONMENT:-production}
|
||||||
LOG_LEVEL: ${LOG_LEVEL:-INFO}
|
LOG_LEVEL: ${LOG_LEVEL:-INFO}
|
||||||
SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-true}
|
SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-true}
|
||||||
@@ -125,7 +127,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- storage:/data/storage
|
- storage:/data/storage
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "curl", "-fsS", "http://localhost:8000/api/v1/health"]
|
test: ["CMD", "curl", "-fsS", "http://localhost:${APP_PORT:-8000}/api/v1/health"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
@@ -141,7 +143,7 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
container_name: crm-worker
|
container_name: ${WORKER_CONTAINER_NAME:-crm-worker}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
@@ -162,12 +164,12 @@ services:
|
|||||||
cpus: "1.0"
|
cpus: "1.0"
|
||||||
environment:
|
environment:
|
||||||
# Worker uses crm_worker (NOSUPERUSER, NOBYPASSRLS) — RLS enforced
|
# Worker uses crm_worker (NOSUPERUSER, NOBYPASSRLS) — RLS enforced
|
||||||
DATABASE_URL: ${WORKER_DATABASE_URL:-${DATABASE_URL:?DATABASE_URL is required}}
|
DATABASE_URL: ${WORKER_DATABASE_URL:-postgresql+asyncpg://crm_worker:${DB_PASSWORD}@postgres:5432/${POSTGRES_DB:-crm_db}}
|
||||||
WORKER_DATABASE_URL: ${WORKER_DATABASE_URL:-postgresql+asyncpg://crm_worker:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-crm_db}}
|
WORKER_DATABASE_URL: ${WORKER_DATABASE_URL:-postgresql+asyncpg://crm_worker:${DB_PASSWORD}@postgres:5432/${POSTGRES_DB:-crm_db}}
|
||||||
MIGRATION_DATABASE_URL: ${MIGRATION_DATABASE_URL:-postgresql+asyncpg://crm_migration:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-crm_db}}
|
MIGRATION_DATABASE_URL: ${MIGRATION_DATABASE_URL:-postgresql+asyncpg://crm_migration:${DB_PASSWORD}@postgres:5432/${POSTGRES_DB:-crm_db}}
|
||||||
REDIS_URL: ${REDIS_URL:-redis://:${REDIS_PASSWORD}@redis:6379/0}
|
REDIS_URL: ${REDIS_URL:-redis://:${REDIS_PASSWORD}@redis:6379/0}
|
||||||
SECRET_KEY: ${SECRET_KEY:?SECRET_KEY is required (min 32 chars)}
|
SECRET_KEY: ${SECRET_KEY:?SECRET_KEY is required (min 32 chars)}
|
||||||
FRONTEND_URL: ${FRONTEND_URL:-http://localhost:8000}
|
FRONTEND_URL: ${FRONTEND_URL:-${APP_DOMAIN:-http://localhost:8000}}
|
||||||
ENVIRONMENT: ${ENVIRONMENT:-production}
|
ENVIRONMENT: ${ENVIRONMENT:-production}
|
||||||
LOG_LEVEL: ${LOG_LEVEL:-INFO}
|
LOG_LEVEL: ${LOG_LEVEL:-INFO}
|
||||||
SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-true}
|
SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-true}
|
||||||
@@ -191,16 +193,16 @@ services:
|
|||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
pgdata:
|
pgdata:
|
||||||
name: crm_pgdata
|
name: ${PGDATA_VOLUME_NAME:-crm_pgdata}
|
||||||
redisdata:
|
redisdata:
|
||||||
name: crm_redisdata
|
name: ${REDISDATA_VOLUME_NAME:-crm_redisdata}
|
||||||
storage:
|
storage:
|
||||||
name: crm_storage
|
name: ${STORAGE_VOLUME_NAME:-crm_storage}
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
crm-net:
|
crm-net:
|
||||||
name: crm-net
|
name: ${CRM_NETWORK_NAME:-crm-net}
|
||||||
driver: bridge
|
driver: bridge
|
||||||
coolify:
|
coolify:
|
||||||
name: coolify
|
name: ${COOLIFY_NETWORK_NAME:-coolify}
|
||||||
external: true
|
external: true
|
||||||
|
|||||||
+414
-246
File diff suppressed because it is too large
Load Diff
+78
-11
@@ -4,36 +4,103 @@
|
|||||||
# bash scripts/fast-deploy.sh frontend # Frontend-only: build + copy (~20s)
|
# bash scripts/fast-deploy.sh frontend # Frontend-only: build + copy (~20s)
|
||||||
# bash scripts/fast-deploy.sh full # Full: Coolify rebuild (~2min)
|
# bash scripts/fast-deploy.sh full # Full: Coolify rebuild (~2min)
|
||||||
# Default: frontend
|
# Default: frontend
|
||||||
|
#
|
||||||
|
# Environment variables:
|
||||||
|
# COOLIFY_API_TOKEN — Coolify API token (required for full deploy)
|
||||||
|
# COOLIFY_BASE_URL — Coolify base URL (default: https://server.media-on.de)
|
||||||
|
# COOLIFY_APP_UUID — Application UUID (optional, resolved via API if absent)
|
||||||
|
# APP_NAME — Application name for API lookup (default: leocrm-api)
|
||||||
|
# APP_DOMAIN — App domain (required for full deploy, e.g. https://crm.media-on.de)
|
||||||
|
# SSH_KEY — SSH key path (default: /a0/usr/workdir/.ssh/coolify-01-root)
|
||||||
|
# SERVER_IP — Server IP (default: 46.225.91.159)
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SERVER="root@46.225.91.159"
|
|
||||||
SSH_KEY="${SSH_KEY:-/a0/usr/workdir/.ssh/coolify-01-root}"
|
SSH_KEY="${SSH_KEY:-/a0/usr/workdir/.ssh/coolify-01-root}"
|
||||||
|
SERVER_IP="${SERVER_IP:-46.225.91.159}"
|
||||||
|
SERVER="root@${SERVER_IP}"
|
||||||
SSH_OPTS="-o StrictHostKeyChecking=no -i $SSH_KEY"
|
SSH_OPTS="-o StrictHostKeyChecking=no -i $SSH_KEY"
|
||||||
MODE="${1:-frontend}"
|
MODE="${1:-frontend}"
|
||||||
|
|
||||||
cd /a0/usr/workdir/leocrm-fix
|
# Resolve repo root from script location
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
REPO_ROOT="$(pwd)"
|
||||||
|
|
||||||
|
# ─── Helper: Resolve app UUID via Coolify API ────────────────────────
|
||||||
|
resolve_app_uuid() {
|
||||||
|
local token="${COOLIFY_API_TOKEN:-}"
|
||||||
|
local base_url="${COOLIFY_BASE_URL:-https://server.media-on.de}"
|
||||||
|
local app_name="${APP_NAME:-leocrm-api}"
|
||||||
|
|
||||||
|
if [ -z "$token" ]; then
|
||||||
|
echo "ERROR: COOLIFY_API_TOKEN not set" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl -sS -H "Authorization: Bearer $token" \
|
||||||
|
"${base_url}/api/v1/applications" \
|
||||||
|
| python3 -c "
|
||||||
|
import sys, json
|
||||||
|
apps = json.load(sys.stdin)
|
||||||
|
for app in apps:
|
||||||
|
if app.get('name') == '${app_name}':
|
||||||
|
print(app.get('uuid', ''))
|
||||||
|
break
|
||||||
|
" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# ─── Full Deploy ─────────────────────────────────────────────────────
|
||||||
if [ "$MODE" = "full" ]; then
|
if [ "$MODE" = "full" ]; then
|
||||||
echo "[Full Deploy] Triggering Coolify rebuild..."
|
echo "[Full Deploy] Triggering Coolify rebuild..."
|
||||||
COOLIFY_API_TOKEN="${COOLIFY_API_TOKEN:-}" \
|
|
||||||
COOLIFY_APP_UUID='stvabl4vaqru7jclx4ittzr3' \
|
if [ -z "${COOLIFY_API_TOKEN:-}" ]; then
|
||||||
COOLIFY_BASE_URL='https://server.media-on.de' \
|
echo "ERROR: COOLIFY_API_TOKEN not set" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ -z "${APP_DOMAIN:-}" ]; then
|
||||||
|
echo "ERROR: APP_DOMAIN not set (e.g. https://crm.media-on.de)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
COOLIFY_API_TOKEN="$COOLIFY_API_TOKEN" \
|
||||||
|
COOLIFY_BASE_URL="${COOLIFY_BASE_URL:-https://server.media-on.de}" \
|
||||||
|
COOLIFY_APP_UUID="${COOLIFY_APP_UUID:-}" \
|
||||||
|
COOLIFY_WORKER_UUID="${COOLIFY_WORKER_UUID:-}" \
|
||||||
|
APP_NAME="${APP_NAME:-leocrm-api}" \
|
||||||
|
WORKER_NAME="${WORKER_NAME:-leocrm-worker}" \
|
||||||
|
APP_DOMAIN="$APP_DOMAIN" \
|
||||||
SSH_KEY="$SSH_KEY" \
|
SSH_KEY="$SSH_KEY" \
|
||||||
SERVER_IP='46.225.91.159' \
|
SERVER_IP="$SERVER_IP" \
|
||||||
/opt/venv/bin/python scripts/deploy.py
|
/opt/venv/bin/python "$REPO_ROOT/scripts/deploy.py"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Frontend-only fast deploy
|
# ─── Frontend-only Fast Deploy ──────────────────────────────────────
|
||||||
|
|
||||||
|
# Resolve app UUID
|
||||||
|
APP_UUID="${COOLIFY_APP_UUID:-}"
|
||||||
|
if [ -z "$APP_UUID" ]; then
|
||||||
|
if [ -z "${COOLIFY_API_TOKEN:-}" ]; then
|
||||||
|
echo "ERROR: COOLIFY_APP_UUID or COOLIFY_API_TOKEN must be set" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "[1/6] Resolving app UUID via Coolify API..."
|
||||||
|
APP_UUID="$(resolve_app_uuid)"
|
||||||
|
if [ -z "$APP_UUID" ]; then
|
||||||
|
echo "ERROR: Could not resolve app UUID" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " App UUID: $APP_UUID"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "[1/5] Building frontend..."
|
echo "[1/5] Building frontend..."
|
||||||
cd frontend
|
cd "$REPO_ROOT/frontend"
|
||||||
npm run build 2>&1 | tail -3
|
npm run build 2>&1 | tail -3
|
||||||
|
|
||||||
echo "[2/5] Finding container..."
|
echo "[2/5] Finding container..."
|
||||||
CONTAINER=$(ssh $SSH_OPTS $SERVER 'docker ps --format "{{.Names}}" | grep "^stvabl4vaqru7jclx4ittzr3-" | head -1')
|
CONTAINER=$(ssh $SSH_OPTS $SERVER "docker ps --format '{{.Names}}' | grep '^${APP_UUID}-' | head -1")
|
||||||
if [ -z "$CONTAINER" ]; then
|
if [ -z "$CONTAINER" ]; then
|
||||||
echo "ERROR: Could not find app container"
|
echo "ERROR: Could not find app container with prefix ${APP_UUID}-" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo " Container: $CONTAINER"
|
echo " Container: $CONTAINER"
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Fast frontend-only deploy: build locally, copy to container, restart.
|
|
||||||
# Usage: bash scripts/fast-frontend-deploy.sh
|
|
||||||
# Skips Coolify rebuild entirely. ~20s total instead of ~2min.
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
CONTAINER="stvabl4vaqru7jclx4ittzr3-153149570355"
|
|
||||||
SERVER="root@46.225.91.159"
|
|
||||||
SSH_KEY="${SSH_KEY:-/a0/usr/workdir/.ssh/coolify-01-root}"
|
|
||||||
SSH_OPTS="-o StrictHostKeyChecking=no -i $SSH_KEY"
|
|
||||||
|
|
||||||
echo "[1/4] Building frontend..."
|
|
||||||
cd /a0/usr/workdir/leocrm-fix/frontend
|
|
||||||
npm run build 2>&1 | tail -3
|
|
||||||
|
|
||||||
echo "[2/4] Packaging & uploading..."
|
|
||||||
tar czf /tmp/frontend-dist.tar.gz -C dist .
|
|
||||||
scp $SSH_OPTS /tmp/frontend-dist.tar.gz $SERVER:/tmp/frontend-dist.tar.gz
|
|
||||||
|
|
||||||
echo "[3/4] Copying into container..."
|
|
||||||
ssh $SSH_OPTS $SERVER "docker cp /tmp/frontend-dist.tar.gz $CONTAINER:/tmp/ && docker exec $CONTAINER sh -c 'cd /app/frontend/dist && tar xzf /tmp/frontend-dist.tar.gz --overwrite && rm /tmp/frontend-dist.tar.gz' && rm /tmp/frontend-dist.tar.gz"
|
|
||||||
|
|
||||||
echo "[4/4] Restarting container (clears service worker cache)..."
|
|
||||||
ssh $SSH_OPTS $SERVER "docker restart $CONTAINER" 2>/dev/null || true
|
|
||||||
sleep 3
|
|
||||||
|
|
||||||
echo "✅ Fast deploy done (~20s). Container restarted."
|
|
||||||
Reference in New Issue
Block a user