# ───────────────────────────────────────────────────────────────────────────── # DigitalOcean App Platform spec — Property Management Network # # Deploy: doctl apps create --spec .do/app.yaml (or the DO MCP apps-create) # Update: doctl apps update --spec .do/app.yaml # # SOURCE: App Platform builds the Dockerfile directly from GitHub # (github.com/silkoserfo/property-management-network). Pushes to `main` # auto-redeploy (deploy_on_push). No DOCR image build/push needed. # # SECRETS: values marked `type: SECRET` are placeholders — set the real values in # the App Platform dashboard (App → Settings → Environment Variables) or via the # create spec. Never commit real secrets to this file. # ───────────────────────────────────────────────────────────────────────────── name: property-management-network region: nyc services: - name: web # Built by App Platform from GitHub using the repo Dockerfile. github: repo: silkoserfo/property-management-network branch: main deploy_on_push: true dockerfile_path: Dockerfile instance_count: 1 instance_size_slug: apps-s-1vcpu-1gb http_port: 3000 health_check: http_path: /api/health initial_delay_seconds: 20 period_seconds: 30 timeout_seconds: 5 success_threshold: 1 failure_threshold: 3 envs: # ── App URLs ────────────────────────────────────────────────────────── # NEXT_PUBLIC_* are inlined into the client bundle at BUILD time, so they # must be RUN_AND_BUILD_TIME with the literal domain we serve on. - key: NEXT_PUBLIC_APP_URL scope: RUN_AND_BUILD_TIME value: https://propertymanagement.network - key: BETTER_AUTH_URL scope: RUN_TIME value: https://propertymanagement.network - key: NEXT_PUBLIC_APP_NAME scope: RUN_AND_BUILD_TIME value: Property Management Network # ── Admin & auth policy ─────────────────────────────────────────────── - key: ADMIN_EMAILS scope: RUN_TIME value: leon@phluit.com - key: REQUIRE_EMAIL_VERIFICATION scope: RUN_TIME value: "true" # ── Database (managed Postgres — PRIVATE host, direct port 25060) ── - key: DATABASE_URL scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD # Verified TLS: DO's Managed Postgres CA isn't in the system trust store, so # paste the cluster CA PEM (repo root ca-certificate.crt) into DATABASE_CA. # With `require` + a valid CA the app connects verified; without a valid CA # it fails loud rather than run unverified. - key: DATABASE_SSL scope: RUN_TIME value: require - key: DATABASE_CA scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD # Schema is migrated out-of-band (as doadmin), NOT on boot. - key: RUN_MIGRATIONS_ON_START scope: RUN_TIME value: "false" # ── Better Auth ─────────────────────────────────────────────────────── - key: BETTER_AUTH_SECRET scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD # Google OAuth (optional — leave blank to disable the Google button). - key: GOOGLE_CLIENT_ID scope: RUN_TIME type: SECRET value: "" - key: GOOGLE_CLIENT_SECRET scope: RUN_TIME type: SECRET value: "" # ── Stripe ──────────────────────────────────────────────────────────── - key: STRIPE_SECRET_KEY scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD - key: STRIPE_WEBHOOK_SECRET scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD # ── AI provider (Anthropic default; OpenAI optional) ────────────────── - key: ANTHROPIC_API_KEY scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD - key: ANTHROPIC_MODEL scope: RUN_TIME value: claude-haiku-4-5 - key: OPENAI_API_KEY scope: RUN_TIME type: SECRET value: "" # ── Email (SMTP — SMTP2GO) ──────────────────────────────────────────── - key: SMTP_HOST scope: RUN_TIME value: mail.smtp2go.com - key: SMTP_PORT scope: RUN_TIME value: "2525" - key: SMTP_USER scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD - key: SMTP_PASS scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD - key: EMAIL_FROM scope: RUN_TIME value: postmaster@propertymanagement.network # ── Cloudflare Turnstile (site key public; baked at build time) ── - key: NEXT_PUBLIC_TURNSTILE_SITE_KEY scope: RUN_AND_BUILD_TIME value: 0x4AAAAAADuDQverznfv1a60 - key: TURNSTILE_SECRET_KEY scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD # ── Object storage (DigitalOcean Spaces + CDN) ──────────────────────── - key: SPACES_KEY scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD - key: SPACES_SECRET scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD - key: SPACES_REGION scope: RUN_TIME value: nyc3 - key: SPACES_BUCKET scope: RUN_TIME value: property-management-network - key: SPACES_ENDPOINT scope: RUN_TIME value: https://nyc3.digitaloceanspaces.com - key: SPACES_CDN_ENDPOINT scope: RUN_TIME value: https://nyc3.cdn.digitaloceanspaces.com # ── Accounting sync (optional — per-landlord QuickBooks / Xero OAuth) ── - key: QBO_CLIENT_ID scope: RUN_TIME type: SECRET value: "" - key: QBO_CLIENT_SECRET scope: RUN_TIME type: SECRET value: "" - key: QBO_ENVIRONMENT scope: RUN_TIME value: production - key: XERO_CLIENT_ID scope: RUN_TIME type: SECRET value: "" - key: XERO_CLIENT_SECRET scope: RUN_TIME type: SECRET value: "" - key: XERO_SALES_ACCOUNT_CODE scope: RUN_TIME value: "200" - key: XERO_EXPENSE_ACCOUNT_CODE scope: RUN_TIME value: "400" # ── Error monitoring (Sentry — DSN is public; browser DSN baked at build) ── - key: SENTRY_DSN scope: RUN_TIME value: https://ef6aa585a080711e14a855b6cc024e9a@o4509830676873216.ingest.us.sentry.io/4511667160219648 - key: NEXT_PUBLIC_SENTRY_DSN scope: RUN_AND_BUILD_TIME value: https://ef6aa585a080711e14a855b6cc024e9a@o4509830676873216.ingest.us.sentry.io/4511667160219648 - key: SENTRY_ENVIRONMENT scope: RUN_TIME value: production # ── Cron (Bearer token the DO Function sends to /api/cron/*) ── - key: CRON_SECRET scope: RUN_TIME type: SECRET value: REPLACE_IN_DASHBOARD # ── Custom domains (DNS hosted on Cloudflare — set CNAMEs there, DNS-only) ── domains: - domain: propertymanagement.network type: PRIMARY - domain: www.propertymanagement.network type: ALIAS