From 4504279c1cdb8cc4fcc5fb3c380b9406726c4ba2 Mon Sep 17 00:00:00 2001 From: dotcomnerd <70242273+dotcomnerd@users.noreply.github.com> Date: Wed, 9 Sep 2026 01:20:03 -0700 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=97=82=EF=B8=8F=20move=20docker=20com?= =?UTF-8?q?pose=20under=20infra?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.cap.yml => infra/docker-compose.cap.yml | 0 docker-compose.crowdsec.yml => infra/docker-compose.crowdsec.yml | 0 .../docker-compose.ffs.local.yml | 0 docker-compose.ffs.yml => infra/docker-compose.ffs.yml | 0 docker-compose.imgproxy.yml => infra/docker-compose.imgproxy.yml | 0 .../docker-compose.local-stack.yml | 0 docker-compose.scrape.yml => infra/docker-compose.scrape.yml | 0 docker-compose.yml => infra/docker-compose.yml | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename docker-compose.cap.yml => infra/docker-compose.cap.yml (100%) rename docker-compose.crowdsec.yml => infra/docker-compose.crowdsec.yml (100%) rename docker-compose.ffs.local.yml => infra/docker-compose.ffs.local.yml (100%) rename docker-compose.ffs.yml => infra/docker-compose.ffs.yml (100%) rename docker-compose.imgproxy.yml => infra/docker-compose.imgproxy.yml (100%) rename docker-compose.local-stack.yml => infra/docker-compose.local-stack.yml (100%) rename docker-compose.scrape.yml => infra/docker-compose.scrape.yml (100%) rename docker-compose.yml => infra/docker-compose.yml (100%) diff --git a/docker-compose.cap.yml b/infra/docker-compose.cap.yml similarity index 100% rename from docker-compose.cap.yml rename to infra/docker-compose.cap.yml diff --git a/docker-compose.crowdsec.yml b/infra/docker-compose.crowdsec.yml similarity index 100% rename from docker-compose.crowdsec.yml rename to infra/docker-compose.crowdsec.yml diff --git a/docker-compose.ffs.local.yml b/infra/docker-compose.ffs.local.yml similarity index 100% rename from docker-compose.ffs.local.yml rename to infra/docker-compose.ffs.local.yml diff --git a/docker-compose.ffs.yml b/infra/docker-compose.ffs.yml similarity index 100% rename from docker-compose.ffs.yml rename to infra/docker-compose.ffs.yml diff --git a/docker-compose.imgproxy.yml b/infra/docker-compose.imgproxy.yml similarity index 100% rename from docker-compose.imgproxy.yml rename to infra/docker-compose.imgproxy.yml diff --git a/docker-compose.local-stack.yml b/infra/docker-compose.local-stack.yml similarity index 100% rename from docker-compose.local-stack.yml rename to infra/docker-compose.local-stack.yml diff --git a/docker-compose.scrape.yml b/infra/docker-compose.scrape.yml similarity index 100% rename from docker-compose.scrape.yml rename to infra/docker-compose.scrape.yml diff --git a/docker-compose.yml b/infra/docker-compose.yml similarity index 100% rename from docker-compose.yml rename to infra/docker-compose.yml From 18a2291d28acf1aa6f0c3dfbee61d88533692b73 Mon Sep 17 00:00:00 2001 From: dotcomnerd <70242273+dotcomnerd@users.noreply.github.com> Date: Wed, 9 Sep 2026 01:23:29 -0700 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20harden=20runtime=20?= =?UTF-8?q?and=20deploy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 21 +- README.md | 194 ++++++++-------- apps/web/app/api/tmdb/proxy/route.ts | 268 ++++++++++++++++++++++ apps/web/app/login/auth-shell.tsx | 5 +- apps/web/auth.ts | 2 +- apps/web/drizzle.config.ts | 14 +- apps/web/package.json | 4 + infra/docker-compose.local-stack.yml | 12 +- infra/docker-compose.scrape.yml | 13 +- scripts/db-migrate-if-needed.sh | 72 ++++-- scripts/deploy.sh | 19 ++ scripts/gluetun/docker-compose.local.yml | 1 + scripts/gluetun/docker-compose.yml | 10 + scripts/infra-health.sh | 139 +++++++++++ scripts/install-prod-watchdogs.sh | 39 ++++ scripts/local-compose.sh | 2 +- scripts/nginx-cache.conf | 30 +++ scripts/nyumatflix-infra-watchdog.service | 14 ++ scripts/nyumatflix-infra-watchdog.sh | 43 ++++ scripts/nyumatflix-infra-watchdog.timer | 11 + scripts/reconcile-cap.sh | 4 +- scripts/reconcile-crowdsec.sh | 4 +- scripts/reconcile-prod-infra.sh | 34 ++- scripts/setup-vpn.sh | 12 +- scripts/sync-prod-env.sh | 25 +- 25 files changed, 824 insertions(+), 168 deletions(-) create mode 100644 apps/web/app/api/tmdb/proxy/route.ts create mode 100644 scripts/infra-health.sh create mode 100644 scripts/install-prod-watchdogs.sh create mode 100644 scripts/nginx-cache.conf create mode 100644 scripts/nyumatflix-infra-watchdog.service create mode 100644 scripts/nyumatflix-infra-watchdog.sh create mode 100644 scripts/nyumatflix-infra-watchdog.timer diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa9c7731..d42a0d6c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -172,6 +172,19 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Set up Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Install dependencies + run: bun install --ignore-scripts + + - name: Sync production database + env: + PROD_DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }} + run: ./scripts/db-migrate-if-needed.sh + - name: Set up SSH key run: | install -m 700 -d ~/.ssh @@ -181,12 +194,12 @@ jobs: - name: Sync deploy files run: | - ssh -p "$DEPLOY_PORT" "$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p '$DEPLOY_PATH/scripts'" + ssh -p "$DEPLOY_PORT" "$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p '$DEPLOY_PATH/infra' '$DEPLOY_PATH/scripts'" rsync -avz -e "ssh -p $DEPLOY_PORT" \ - docker-compose.scrape.yml docker-compose.ffs.yml docker-compose.imgproxy.yml \ - "$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/" + infra/docker-compose.scrape.yml infra/docker-compose.ffs.yml infra/docker-compose.imgproxy.yml \ + "$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/infra/" rsync -avz -e "ssh -p $DEPLOY_PORT" \ - scripts/deploy.sh scripts/deploy-lib.sh scripts/reconcile-prod-infra.sh \ + scripts/deploy.sh scripts/deploy-lib.sh scripts/reconcile-prod-infra.sh scripts/db-migrate-if-needed.sh \ "$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/scripts/" if [[ -d flipt ]]; then rsync -avz -e "ssh -p $DEPLOY_PORT" \ diff --git a/README.md b/README.md index cc2b418e..6015c84e 100644 --- a/README.md +++ b/README.md @@ -28,14 +28,24 @@ ## 🏃🏾♂️ Run NyumatFlix Locally > [!IMPORTANT] -> Prerequisites: +> **Required** > -> - [Bun](https://bun.sh/) installed on your machine. -> - A [PostgreSQL](https://www.postgresql.org/) database. -> - A [TMDb](https://www.themoviedb.org/) API key. -> - A [Resend](https://resend.com/) API key. +> - [Bun](https://bun.sh/) `1.3+` (see `packageManager` in root `package.json`) +> - [Docker](https://www.docker.com/) — scrape stack on `bun run dev`, and first-time Movi player WASM build +> - [PostgreSQL](https://www.postgresql.org/) (or [Neon](https://neon.tech/)) +> - [TMDb](https://www.themoviedb.org/) API key +> - [Resend](https://resend.com/) API key (`AUTH_RESEND_KEY`) +> - `AUTH_SECRET` — e.g. `openssl rand -base64 32` +> +> **Optional (feature-specific)** +> +> - `ID_MOE_API_KEY` — anime ↔ TMDB mapping +> - `MAL_CLIENT_ID` / `MAL_CLIENT_SECRET` — MyAnimeList sync on login +> - `scripts/gluetun/.env` — Surfshark (or other) WireGuard creds for scrape VPN egress +> - `CALLUSPIRATES_*` — Direct playback provider (nyumatflix.com only in prod) +> - `bun run cap:up` — self-hosted Cap instead of dev bypass on `/login` -To run the project on your machine, follow the steps below: +Monorepo layout: app in `apps/web`, shared packages in `packages/*`. Env lives at **repo root** (`.env.local`); `apps/web` symlinks to it on build/dev. 1. Clone or fork the repository @@ -44,59 +54,65 @@ git clone git@github.com:Nyumat/NyumatFlix.git cd NyumatFlix ``` -2. Next, create a `.env.local` file in the root directory of the project and add the following environment variables: +2. Environment ```bash -TMDB_API_KEY= -ID_MOE_API_KEY= -AUTH_SECRET= -AUTH_RESEND_KEY= -APP_URL= -AUTH_URL= -NEXTAUTH_URL= -RESEND_FROM_EMAIL= -DATABASE_URL= +cp .env.example .env.local ``` -You can get your own instance of the API keys by creating an account on [TMDb](https://www.themoviedb.org/) and [Resend](https://resend.com/). +Fill in at minimum: `TMDB_API_KEY`, `DATABASE_URL`, `AUTH_SECRET`, `AUTH_RESEND_KEY`. Local URLs are prefilled (`APP_URL` / `AUTH_URL` / `NEXTAUTH_URL` → `http://localhost:3000`). See `.env.example` for scrape (`FLARESOLVERR_URL`, `SCRAPE_PROXY_URL`), feature flags (`FLIPT_*`), and Cap. > [!TIP] -> For a database, you can use any PostgreSQL-compatible database you want. I recommend using [Neon](https://neon.tech/) for production and [Local Postgres](https://www.postgresql.org/) for development. - -For local development, set `APP_URL`, `AUTH_URL`, and `NEXTAUTH_URL` to `http://localhost:3000`. +> Any Postgres-compatible host works. Neon is fine for dev and prod. 3. Install dependencies -Bun is the package manager of choice here, so you'll need to install it first. You can do so by following the instructions [here](https://bun.sh/docs/installation). - ```bash bun install ``` -4. Configure magic strings +4. Configure magic strings (optional) -There's a few places in the codebase where I'm hardcoding some strings that you might want to change. You can find some of them in `lib/constants.ts`. Additionally, you might want to modify the email templates in `emails/` and `metadata` objects in `app/` and `layout/`. +Hardcoded branding/metadata: `apps/web/lib/constants.ts`, `apps/web/emails/`, and `metadata` in `apps/web/app/`. > [!NOTE] -> If you end up not changing the magic strings, that's fine too, but I'd appreciate credit if you re-deploy the project without modifications! +> If you ship without changing these, credit is appreciated. -5. Set up the database +5. Database ```bash -bun run db:generate -bun run db:push -bun run db:studio # tbh this is optional +cd apps/web && bun run db:migrate +# optional: bun run db:studio ``` -These will generate the necessary migration files and push the schema to your local (or remote) PostgreSQL database instance. +Fresh schema only (no migration history): `bun run db:push`. After pulling schema changes: `bun run db:migrate`. Existing DBs from older deploys: `bun run db:ensure-baseline` then `db:migrate`. + +6. Local scrape stack (optional but recommended for playback) -6. Run the development server +`bun run dev` runs `scripts/bootstrap-scrape-vpn.sh ensure-local` first — starts **FlareSolverr** (`:8191`), **Flipt** (`:8090`), and **Gluetun** (`:8888` proxy, `:8000` control) when Docker is available. Writes scrape-related vars into `.env.local`. + +```bash +# full bootstrap + prod env sync (needs SSH host `leetbot` unless you skip) +bun run dev:stack + +# scrape stack only, no Next.js +./scripts/bootstrap-scrape-vpn.sh ensure-local + +# skip scrape containers (metadata/browse still works; many scrapes will fail) +SKIP_SCRAPE_STACK=1 bun run dev +``` + +Gluetun needs VPN creds in `scripts/gluetun/.env` (copy from `scripts/gluetun/.env.example`). Without VPN, FlareSolverr still helps; vixsrc/vidsrc/vidrock often need the proxy. + +7. Run the development server ```bash bun run dev ``` -7. Finally, open [http://localhost:3000](http://localhost:3000) in your browser to see the project in action! +First run may build `@nyumatflix/player` via Docker if `public/vendor/player/` is missing. + +8. Open [http://localhost:3000](http://localhost:3000) +
+ +