@@ -33,6 +33,12 @@ Running at [clahub.com](https://www.clahub.com)
3333- ** Rate limiting** — tiered rate limits (100/60/30 req/min) with ` X-RateLimit-* ` headers
3434- ** CSV/PDF export** — download signatures as CSV or agreement documents as PDF
3535- ** Corporate CLA (CCLA)** — a company representative signs once, covering all contributors with a matching email domain
36+ - ** Docker self-hosting** — ` docker compose up -d ` with auto-migration, health checks, and SQLite volume persistence
37+ - ** Custom branding** — white-label with ` APP_NAME ` , ` APP_LOGO_URL ` , ` APP_PRIMARY_COLOR `
38+ - ** CONTRIBUTING.md generation** — auto-generate a CONTRIBUTING snippet with CLA signing link and badge
39+ - ** Admin dashboard** — audit log viewer and manual PR re-check on the agreement edit page
40+ - ** Health endpoint** — ` GET /api/health ` for uptime monitoring and container health checks
41+ - ** WCAG 2.1 AA accessible** — color contrast, ARIA labels, keyboard navigation, skip links
3642- Dashboard with signature tracking
3743- Full audit log of all changes
3844
@@ -96,76 +102,39 @@ Options: `?style=flat-square`, `?label=License`, `?color=4c1`.
96102- [ Sentry] ( https://sentry.io ) via ` @sentry/nextjs ` for error tracking (optional)
97103- [ @react-pdf/renderer ] ( https://react-pdf.org ) for PDF export
98104- [ PapaParse] ( https://www.papaparse.com ) for CSV export
105+ - [ Docker] ( https://www.docker.com ) for self-hosted deployment
99106- [ Vitest] ( https://vitest.dev ) + [ Playwright] ( https://playwright.dev ) for testing
100107
101108## Getting started
102109
103- ### Prerequisites
110+ > ** Full walkthrough: ** [ docs/getting-started.md ] ( docs/getting-started.md )
104111
105- You need ** Node.js 18+ ** and ** npm ** . You also need to set up three things on GitHub:
112+ ### Prerequisites
106113
107- 1 . ** GitHub App** — for webhook events and Check Runs
108- 2 . ** GitHub OAuth App (owner)** — full scope for project owners
109- 3 . ** GitHub OAuth App (contributor)** — minimal scope for CLA signers
114+ You need ** Node.js 20+** and ** npm** . You also need a GitHub App and two OAuth Apps (owner + contributor). See the [ Getting Started guide] ( docs/getting-started.md ) for step-by-step setup.
110115
111- ### 1. Clone and install
116+ ### Quick start
112117
113118``` bash
114119git clone https://github.com/clahub/clahub.git
115120cd clahub
116- npm install
117- ```
118-
119- ### 2. Configure environment
120-
121- ``` bash
122- cp .env.local.example .env.local
123- ```
124-
125- Fill in the values:
126-
127- | Variable | Required | Description |
128- | ---| ---| ---|
129- | ` DATABASE_URL ` | Yes | SQLite path, e.g. ` file:./clahub.db ` |
130- | ` NEXTAUTH_SECRET ` | Yes | Generate with ` openssl rand -base64 32 ` |
131- | ` GITHUB_APP_ID ` | Yes | GitHub App ID |
132- | ` GITHUB_APP_PRIVATE_KEY ` | Yes | GitHub App private key (PEM) |
133- | ` GITHUB_WEBHOOK_SECRET ` | Yes | Webhook secret configured on the GitHub App |
134- | ` GITHUB_OWNER_CLIENT_ID ` | Yes | OAuth App for owners — Client ID |
135- | ` GITHUB_OWNER_CLIENT_SECRET ` | Yes | OAuth App for owners — Client secret |
136- | ` GITHUB_CONTRIBUTOR_CLIENT_ID ` | Yes | OAuth App for contributors — Client ID |
137- | ` GITHUB_CONTRIBUTOR_CLIENT_SECRET ` | Yes | OAuth App for contributors — Client secret |
138- | ` APP_URL ` | Yes | Public URL, e.g. ` http://localhost:3000 ` |
139- | ` SENTRY_DSN ` | No | Sentry error tracking (server-side) |
140- | ` NEXT_PUBLIC_SENTRY_DSN ` | No | Sentry error tracking (client-side) |
141- | ` LOG_LEVEL ` | No | Log level: ` debug ` , ` info ` (default), ` warn ` , ` error ` |
142- | ` RESEND_API_KEY ` | No | Email via Resend |
143- | ` EMAIL_FROM ` | No | Sender address for emails |
144-
145- ### 3. Set up the database
146-
147- ``` bash
121+ npm ci
122+ cp .env.local.example .env.local # fill in your values
148123npm run db:push
149- npm run db:seed # optional — creates sample data
150- ```
151-
152- ### 4. Run the dev server
153-
154- ``` bash
155124npm run dev
156125```
157126
158127Open [ http://localhost:3000 ] ( http://localhost:3000 ) .
159128
160- ### Webhooks in development
129+ ** Required env vars: ** ` DATABASE_URL ` , ` NEXTAUTH_SECRET ` , ` GITHUB_APP_ID ` , ` GITHUB_APP_PRIVATE_KEY ` , ` GITHUB_WEBHOOK_SECRET ` , ` GITHUB_OWNER_CLIENT_ID/SECRET ` , ` GITHUB_CONTRIBUTOR_CLIENT_ID/SECRET ` , ` APP_URL ` .
161130
162- GitHub can't reach ` localhost ` , so use a tunnelling service like [ ngrok ] ( https://ngrok.com ) :
131+ ** Optional: ** ` SENTRY_DSN ` , ` RESEND_API_KEY ` , ` LOG_LEVEL ` , branding vars ( ` APP_NAME ` , ` APP_LOGO_URL ` , ` APP_PRIMARY_COLOR ` ).
163132
164- ``` bash
165- ngrok http 3000
166- ```
133+ See [ docs/configuration.md] ( docs/configuration.md ) for the full environment variable reference.
167134
168- Set the forwarding URL as your GitHub App's webhook URL and update ` APP_URL ` in ` .env.local ` .
135+ ### Webhooks in development
136+
137+ GitHub can't reach ` localhost ` , so use [ ngrok] ( https://ngrok.com ) (` ngrok http 3000 ` ) and update ` APP_URL ` in ` .env.local ` .
169138
170139## Scripts
171140
@@ -183,6 +152,20 @@ Set the forwarding URL as your GitHub App's webhook URL and update `APP_URL` in
183152| ` npm run db:seed ` | Seed database with sample data |
184153| ` npm run db:studio ` | Open Prisma Studio |
185154
155+ ## Self-hosting
156+
157+ The fastest way to self-host CLAHub is with Docker:
158+
159+ ``` bash
160+ cp .env.docker.example .env # fill in your values
161+ docker compose up -d
162+ ```
163+
164+ Also supports Vercel, Railway, Fly.io, and bare-metal Node.js (PM2 / systemd).
165+
166+ See [ Deployment Guide] ( docs/deployment.md ) for all options and
167+ [ Upgrading Guide] ( docs/upgrading.md ) for version updates.
168+
186169## Testing
187170
188171### Unit tests (Vitest)
235218 agreements/ Dashboard, create, edit, public signing page
236219 api/auth/ NextAuth endpoints
237220 api/badge/ SVG badge endpoints (public, no auth)
221+ api/health/ Health check endpoint
238222 api/v1/ REST API (agreements, signatures, check, export)
239223 api/webhooks/ GitHub App webhook handler
240224 auth/signin/ Sign-in page
243227 not-found.tsx Custom 404 page
244228 components/
245229 ui/ shadcn/ui primitives
246- agreements/ Agreement form, signing form, exclusion manager, signature manager, notification toggle, etc.
230+ agreements/ Agreement form, signing form, exclusion manager, signature manager, notification toggle, audit log viewer, recheck button, CONTRIBUTING.md section
247231 lib/
248232 actions/ Server actions (agreement, exclusion, signing, signature)
249233 schemas/ Zod validation schemas
254238 auth.ts NextAuth configuration (dual providers)
255239 access.ts Role-based access control (owner, org_admin)
256240 badge.ts SVG badge rendering (shields.io-compatible)
241+ branding.ts Custom instance branding from env vars
242+ contributing.ts CONTRIBUTING.md snippet generation
257243 cla-check.ts Core CLA verification + exclusion + corporate coverage
258244 email.ts Resend email wrapper + notification templates
259245 export-csv.ts CSV export with papaparse
@@ -273,6 +259,10 @@ tests/
273259 unit/ Vitest unit tests (schemas, lib, cla-check, actions)
274260 e2e/ Playwright E2E tests (signing flow, dashboard, webhook)
275261 setup.ts Vitest setup (jest-dom matchers)
262+ Dockerfile Multi-stage production image (node:20-alpine)
263+ docker-compose.yml Self-hosted deployment with SQLite volume
264+ docker-entrypoint.sh Auto-migration entrypoint script
265+ docs/ Deployment and operations documentation
276266```
277267
278268## Database models
0 commit comments