# Plesk Agency Management Portal (MVP) Next.js + Tailwind + Supabase + Stripe multi-tenant SaaS starter for agencies managing one or more Plesk instances. ## Included MVP Features - Supabase Postgres schema + RLS (`supabase/schema.sql`) - Supabase Auth (magic-link login) - Agency tenancy context (`agency_members` based) - Dashboard with: - Plesk instance connect + validation - Plesk sync (subscriptions + domains) - Subscription suspend / unsuspend actions - Stripe checkout + billing portal launch - Stripe webhook endpoint to sync billing state ## 1) Setup 1. Install dependencies: ```bash npm install ``` 2. Create local env: ```bash cp .env.example .env.local ``` 3. Fill `.env.local` with your Supabase + Stripe values. 4. In Supabase SQL Editor, run: ```sql -- contents of supabase/schema.sql ``` 5. In Supabase Auth settings, set site URL and redirect URL(s), e.g.: - `http://localhost:3000` - `http://localhost:3000/dashboard` 6. Run dev server: ```bash npm run dev ``` ## 2) Seed Minimum Data After first login user is created in `auth.users`, then add membership rows (via SQL) so tenant context resolves: ```sql insert into agencies (name) values ('My Agency') returning id; -- replace values insert into agency_members (agency_id, user_id, role) values ('', '', 'owner'); ``` ## 3) API Endpoints - `POST /api/plesk/instances` — create + validate Plesk connection - `POST /api/plesk/instances/:id/sync` — pull/sync subscriptions + domains from one Plesk instance - `POST /api/plesk/instances/:id/autosync` — update auto-sync enabled/frequency for one Plesk instance - `POST /api/jobs/plesk-sync-all` — background sync job for all connected instances (requires `X-JOB-SECRET`) - `POST /api/cron/autosync` — scheduled auto-sync tick (requires `X-CRON-SECRET`) - `POST /api/plesk/subscriptions/:id/action` — suspend or unsuspend - `POST /api/stripe/checkout` — create Stripe Checkout session - `POST /api/stripe/portal` — create Stripe Customer Portal session - `POST /api/stripe/webhook` — Stripe webhook receiver ## 4) Important Notes - Set a strong `ENCRYPTION_KEY`; it encrypts stored Plesk auth secrets. - Set a strong `PLESK_CRED_ENC_KEY` (32-byte base64 or 64-char hex) for Plesk credential encryption. - Set `JOB_SECRET` for internal cron-triggered job auth. - Set `CRON_SECRET` for `/api/cron/autosync` auth. - `/api/stripe/webhook` is excluded from auth middleware for Stripe signature verification. - Current implementation is intentionally MVP-focused; add stronger validation, retries, idempotency keys, and richer error observability for production. ## 5) Automatic Plesk Auto-Sync (CL3.5) Background auto-sync endpoint: ```bash curl -sS -X POST http://localhost:3000/api/jobs/plesk-sync-all \ -H "X-JOB-SECRET: " ``` Recommended cron (every 5 minutes): ```cron */5 * * * * curl -sS -X POST http://localhost:3000/api/jobs/plesk-sync-all -H "X-JOB-SECRET: ${JOB_SECRET}" ``` Notes: - Job uses DB lock (`job_locks`) to avoid overlapping runs. - Job processes at most 10 connected instances per run. - Instances synced in the last 3 minutes are skipped. ## 6) Auto Sync Worker (CL6) New scheduler fields live on `plesk_instances`: - `auto_sync_enabled` - `auto_sync_frequency_minutes` - `last_auto_sync_at` - `next_auto_sync_at` - `auto_sync_lock_until` - `auto_sync_lock_token` Endpoint for periodic worker ticks: ```bash curl -sS -X POST http://localhost:3000/api/cron/autosync \ -H "X-CRON-SECRET: " ``` Recommended system cron (every 5 minutes): ```cron */5 * * * * curl -sS -X POST https:///api/cron/autosync -H "X-CRON-SECRET: ${CRON_SECRET}" ``` Or schedule the same call from Jenkins. Worker safety behavior: - processes at most 5 instances per tick - concurrency limited to 2 at a time - per-instance lock lease 15 minutes - per-instance timeout guard 14 minutes - per-instance failures are isolated and logged to `actions_log`