Installation
Step-by-step install on a bare-metal server or VM. Prefer containers? Use Docker production instead.Requirements
- PHP 8.2+ (with the extensions listed in Requirements)
- Node.js 20+
- PostgreSQL 14+ or MySQL 8+
- Redis 6+
- Composer 2.x
Install
1. Clone the repository
2. Install PHP and Node dependencies
php artisan key:generate writes APP_KEY into .env. Without it the app will not boot.
3. Configure the environment
Edit.env before migrating. Minimum for a working self-hosted instance:
Also configure mail (invites / password reset) and optional social OAuth / AI keys — see Configuration.
4. Run migrations
5. Passport keys (and local storage symlink)
Passport needs an RSA key pair on disk to sign and verify API / MCP tokens:FILESYSTEM_DISK=public, also create the public media symlink:
storage:link when using object storage (s3, r2, spaces) — those disks serve from the bucket URL.
6. Seed Passport client and admin user
Self-hosted installs close/register. Bootstrap the database once:
Admin credentials — change the password immediately on first login:
Further accounts come from workspace invites (Settings → Members).
7. Build the frontend
8. Run the app
Local / smoke test (one terminal):php artisan serve, a queue listener, log tail, and Vite. Open http://localhost:8000 and sign in with the admin user.
Production — do not use composer dev. You need long-running processes:
Full Supervisor configs, Nginx (including Reverb
/app/ + /apps/), SSL, and caches: Production setup.
End-to-end checklist
Verify
- Sign in at
APP_URLwith the admin credentials - Create an API key under workspace Settings → API Keys (fails with 500 if Passport keys or client are missing)
- Connect an MCP client via OAuth (Settings → MCP), or call the REST API with the key above
- Upload a media file (404s if you use
publicdisk withoutstorage:link) - Schedule a test post and confirm Horizon processes it
Next steps
- Configuration — mail, storage, social OAuth, AI
- Production setup — Nginx, SSL, Horizon, Reverb, cron
- Docker — same stack via Compose

