Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions backend/server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { Pool } from 'pg'
import { contactAutoReplyEmail, contactNotificationEmail, newsletterConfirmationEmail } from './email-templates.mjs'
import { sendEmail as sendResendEmail } from './resend-email.mjs'

const databaseUrl = process.env.DATABASE_URL
// Coolify injects application variables into each Compose service before
// Docker performs nested interpolation. Prefer the dedicated role explicitly
// so a retained legacy DATABASE_URL can remain available for rollback without
// silently widening the API's database privileges.
const databaseUrl = process.env.API_DATABASE_URL || process.env.DATABASE_URL
const isProduction = process.env.NODE_ENV === 'production'
const allowedOrigins = String(process.env.ALLOWED_ORIGINS || process.env.ALLOWED_ORIGIN || '')
.split(',')
Expand Down Expand Up @@ -37,7 +41,7 @@ const adminPostgrestUrl = process.env.ADMIN_POSTGREST_URL?.trim().replace(/\/$/,
const adminPostgrestApiKey = process.env.ADMIN_POSTGREST_API_KEY?.trim()
const publicSiteUrl = (process.env.PUBLIC_SITE_URL?.trim() || allowedOrigins[0] || '').replace(/\/$/, '')
const publicEmailSiteUrl = (process.env.PUBLIC_EMAIL_SITE_URL?.trim() || 'https://vezvision.com').replace(/\/$/, '')
if (!databaseUrl || allowedOrigins.length === 0) throw new Error('DATABASE_URL and ALLOWED_ORIGIN/ALLOWED_ORIGINS are required')
if (!databaseUrl || allowedOrigins.length === 0) throw new Error('API_DATABASE_URL/DATABASE_URL and ALLOWED_ORIGIN/ALLOWED_ORIGINS are required')
if (isProduction && (!turnstileSecret || turnstileExpectedHostnames.length === 0)) {
throw new Error('TURNSTILE_SECRET_KEY and TURNSTILE_EXPECTED_HOSTNAMES are required in production')
}
Expand Down
15 changes: 7 additions & 8 deletions coolify-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ services:
networks:
vezvision_internal:
aliases: [vezvision-api]
# The Coolify-managed PostgreSQL service is discoverable only on this
# network. The API still has no published port or Traefik labels.
coolify: {}
security_opt: ["no-new-privileges:true"]
cap_drop: [ALL]
read_only: true
Expand All @@ -54,17 +57,11 @@ services:
networks:
vezvision_internal:
aliases: [vezvision-postgrest]
coolify: {}
security_opt: ["no-new-privileges:true"]
cap_drop: [ALL]
read_only: true
tmpfs: [/tmp]
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3001/ >/dev/null || exit 1"]
interval: 10s
timeout: 3s
retries: 5
start_period: 10s

gateway:
build:
context: .
Expand All @@ -74,7 +71,9 @@ services:
api:
condition: service_healthy
postgrest:
condition: service_healthy
# The pinned PostgREST image is distroless and has no shell/wget for a
# Compose health command. PostgREST itself retries database startup.
condition: service_started
expose: ["8080"]
labels:
- traefik.docker.network=coolify
Expand Down
15 changes: 5 additions & 10 deletions deploy/hetzner/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ services:
ADMIN_POSTGREST_URL: ${ADMIN_POSTGREST_URL:-}
ADMIN_POSTGREST_API_KEY: ${ADMIN_POSTGREST_API_KEY:-}
PORT: 3000
networks: [vezvision_internal]
# Coolify's managed PostgreSQL DNS name is available only on `coolify`.
# No port or reverse-proxy label is published for this service.
networks: [vezvision_internal, coolify]
security_opt: ["no-new-privileges:true"]
cap_drop: [ALL]
read_only: true
Expand All @@ -35,18 +37,11 @@ services:
PGRST_DB_ANON_ROLE: anon
PGRST_SERVER_HOST: 0.0.0.0
PGRST_SERVER_PORT: 3001
networks: [vezvision_internal]
networks: [vezvision_internal, coolify]
security_opt: ["no-new-privileges:true"]
cap_drop: [ALL]
read_only: true
tmpfs: [/tmp]
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3001/ >/dev/null || exit 1"]
interval: 10s
timeout: 3s
retries: 5
start_period: 10s

gateway:
build:
context: ../..
Expand All @@ -56,7 +51,7 @@ services:
api:
condition: service_healthy
postgrest:
condition: service_healthy
condition: service_started
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
networks: [vezvision_internal, coolify]
Expand Down
Loading