Files
property-management-network/docker-compose.yml
T
Leon SerfatyandClaude Opus 4.8 857b9a7811 Initial import: property management SaaS + security hardening + admin dashboard
Property Management Network — Next.js 16 (App Router), Better Auth,
Drizzle ORM over PostgreSQL, Stripe, OpenAI, Resend.

Includes:
- Security hardening: access-control/IDOR fixes, TLS-by-default DB layer,
  constant-time cron auth, strict security headers, atomic AI quota gating,
  HTML/email output encoding, demo-backdoor disabled in production.
- Superadmin dashboard at /admin (overview/MRR, server-paginated users with
  ban/impersonate/plan/delete, billing, platform activity + admin audit log,
  AI usage, system health) via the Better Auth admin plugin.
- Seed/migration utility scripts under scripts/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 20:36:07 -04:00

75 lines
2.7 KiB
YAML

# Optional all-in-one stack for Coolify's "Docker Compose" build pack.
# Bundles the app + a PostgreSQL database + persistent volumes.
#
# If you instead provision Postgres separately in Coolify (recommended for
# production), deploy with the Dockerfile build pack and skip this file.
#
# Set the referenced variables in Coolify's Environment Variables. Mark the
# NEXT_PUBLIC_* and POSTGRES_* values as available at build time.
services:
app:
build:
context: .
dockerfile: Dockerfile
args:
NEXT_PUBLIC_APP_URL: ${NEXT_PUBLIC_APP_URL}
NEXT_PUBLIC_APP_NAME: ${NEXT_PUBLIC_APP_NAME:-Property Management Network}
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
DATABASE_URL: postgres://${POSTGRES_USER:-pmn}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB:-pmn}
# Bundled Postgres talks plaintext over the private compose network.
DATABASE_SSL: ${DATABASE_SSL:-disable}
RUN_MIGRATIONS_ON_START: "true"
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
BETTER_AUTH_URL: ${BETTER_AUTH_URL}
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-}
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-}
STORAGE_DIR: /app/storage
STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY:-}
STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET:-}
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY:-}
STRIPE_PRO_MONTHLY_PRICE_ID: ${STRIPE_PRO_MONTHLY_PRICE_ID:-}
STRIPE_LANDLORD_MONTHLY_PRICE_ID: ${STRIPE_LANDLORD_MONTHLY_PRICE_ID:-}
STRIPE_LIFETIME_PRICE_ID: ${STRIPE_LIFETIME_PRICE_ID:-}
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
RESEND_API_KEY: ${RESEND_API_KEY:-}
RESEND_FROM_EMAIL: ${RESEND_FROM_EMAIL:-noreply@propertymanagement.network}
NEXT_PUBLIC_APP_URL: ${NEXT_PUBLIC_APP_URL}
NEXT_PUBLIC_APP_NAME: ${NEXT_PUBLIC_APP_NAME:-Property Management Network}
CRON_SECRET: ${CRON_SECRET}
volumes:
- app-storage:/app/storage
expose:
- "3000"
healthcheck:
test:
["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 30s
timeout: 5s
retries: 3
start_period: 25s
db:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:-pmn}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB:-pmn}
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-pmn} -d ${POSTGRES_DB:-pmn}"]
interval: 10s
timeout: 5s
retries: 10
start_period: 10s
volumes:
app-storage:
db-data: