The crawler identified as `OpenSEO-Audit/1.0` with almost no headers, which naive bot filters and security plugins block outright. - New crawl-request.ts: AUDIT_USER_AGENT (a current Chrome string), buildAuditHeaders() (Accept, Accept-Language, Sec-Fetch-*, Sec-Ch-Ua, Upgrade-Insecure-Requests), and fetchForAudit() — fetch + those headers + one retry on a transient 429/503. - Wired into the page crawl (site-audit-workflow-helpers), robots.txt + sitemap discovery, and start-URL redirect probing. Gets past the naive tier; still reported as "blocked" for JS/TLS challenges (Cloudflare Managed Challenge, DataDome) — those need a real browser. Doc note points operators at WAF IP/UA allowlisting for their own sites. No env dependency (keeps the audit lib importable without a cloudflare:workers mock). tsc / oxlint / knip clean; new crawl-request.test.ts (5); suite otherwise unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
103 lines
3.9 KiB
Markdown
103 lines
3.9 KiB
Markdown
# Self-hosting with team logins (`AUTH_MODE=team`)
|
|
|
|
`team` mode turns the app into a single shared workspace with individual
|
|
email/password logins. There is no billing, no Google login, no email
|
|
verification, and no self-serve signup — the owner provisions every account.
|
|
|
|
Use it when you want your team on one internal instance and need to see who did
|
|
what. For a public multi-tenant product, use `hosted` instead.
|
|
|
|
## What you get
|
|
|
|
- Email/password sign-in for each teammate.
|
|
- One shared workspace (organization). Everyone works in the same projects.
|
|
- Roles: **owner** (you), **admin** (full access except billing/owner actions),
|
|
**member** (research + view).
|
|
- Two ways to add people:
|
|
- **Settings → Users** — create an account with a temporary password directly.
|
|
- **Settings → Organization** — send an email invite link (needs no email
|
|
provider config to create the invite; the link is shown in the UI).
|
|
|
|
## 1. Set environment variables
|
|
|
|
Edit `.env` in the deployment directory (for the pm2 setup that is
|
|
`/home/dev/DOCKER/OPEN-SEO/open-seo/.env`):
|
|
|
|
```sh
|
|
AUTH_MODE=team
|
|
BETTER_AUTH_URL=https://seo.thedomainnest.com # the exact public origin, https
|
|
BETTER_AUTH_SECRET=<64 hex chars> # openssl rand -hex 32
|
|
```
|
|
|
|
`AUTH_MODE` is compiled into the browser bundle, so it must be present when
|
|
`vite build` runs — not only at runtime. Vite reads this same `.env` at build
|
|
time, so one edit covers both as long as the build runs in this directory.
|
|
|
|
Keep the existing `DATABASE_URL`, `DATAFORSEO_API_KEY`, etc.
|
|
|
|
## 2. Rebuild and restart
|
|
|
|
If your pipeline builds on push, commit/push and let it run. To do it by hand:
|
|
|
|
```sh
|
|
cd /home/dev/DOCKER/OPEN-SEO/open-seo
|
|
pnpm install --frozen-lockfile
|
|
pnpm build
|
|
pm2 restart OPEN-SEO --update-env
|
|
```
|
|
|
|
Confirm config: `curl -s http://127.0.0.1:3001/api/health | jq .checks.auth`
|
|
should report `team`.
|
|
|
|
## 3. Create the owner account
|
|
|
|
Open the site. With `team` mode on and no users yet, `/sign-in` redirects to
|
|
`/setup`. Fill in name, email, password → **Create workspace**. You are signed
|
|
in as the owner.
|
|
|
|
`/setup` disables itself the moment the owner exists. If you ever need to reset,
|
|
delete all rows from `user` (and `member`, `account`, `session`) in Postgres and
|
|
reload.
|
|
|
|
## 4. Add your team
|
|
|
|
**Settings → Users → Add user.** Enter their email, name, a temporary password,
|
|
and a role. Share the password out-of-band; they change it after signing in
|
|
(Settings → Personal, once that lands) or you reset it from the same screen.
|
|
|
|
Removing a user drops their membership and signs them out everywhere. Their
|
|
`user` row is kept so past activity still attributes correctly; re-adding them
|
|
issues a fresh password.
|
|
|
|
## 5. Activity log
|
|
|
|
**Settings → Activity** (owner/admin only) shows who did what — projects
|
|
created/archived, site audits started, users added/removed, invitations sent —
|
|
filterable by user and action.
|
|
|
|
It writes to a new `activity_log` table, so **run the migration once** after
|
|
deploying:
|
|
|
|
```sh
|
|
cd /home/dev/DOCKER/OPEN-SEO/open-seo
|
|
export $(grep -E '^DATABASE_URL=' .env | xargs)
|
|
pnpm exec drizzle-kit migrate --config drizzle-pg.config.ts
|
|
pm2 restart OPEN-SEO
|
|
```
|
|
|
|
Until the table exists, the writes fail silently (logged to the console) and the
|
|
app keeps working; the Activity tab just shows nothing.
|
|
|
|
## Notes
|
|
|
|
- Password reset by email is not available in `team` mode. The owner/admins
|
|
reset passwords from Settings → Users.
|
|
- Site audit sends a Chrome-like User-Agent and browser headers, which gets
|
|
past naive bot filters but not JS/TLS challenges (Cloudflare Managed
|
|
Challenge, DataDome). For those, allowlist the server's IP or the crawler's
|
|
User-Agent in the target site's WAF.
|
|
- The MCP server and its OAuth flow are hosted-only for now; `team` deployments
|
|
serve the app UI only.
|
|
- Rolling back: set `AUTH_MODE=local_noauth`, rebuild, restart. Existing users
|
|
and data stay in the database, just unused.
|