124 lines
3.5 KiB
Markdown
124 lines
3.5 KiB
Markdown
# Echoboard
|
|
|
|
Self-hosted feedback board. Users submit feature requests and bug reports without creating an account - anonymous by default, with optional passkey registration for persistence across devices. No email required for anything.
|
|
|
|
## Self-hosting with Docker
|
|
|
|
```bash
|
|
git clone https://git.lashman.live/lashman/echoboard.git
|
|
cd echoboard
|
|
cp .env.example .env
|
|
```
|
|
|
|
Edit `.env` and fill in:
|
|
|
|
1. Set `POSTGRES_PASSWORD` to something random
|
|
2. Generate five secrets (one for each of `APP_MASTER_KEY`, `APP_BLIND_INDEX_KEY`, `TOKEN_SECRET`, `JWT_SECRET`, `ALTCHA_HMAC_KEY`):
|
|
```bash
|
|
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
|
```
|
|
3. Generate VAPID keys for push notifications:
|
|
```bash
|
|
npx web-push generate-vapid-keys
|
|
```
|
|
4. Set `WEBAUTHN_RP_ID` to your domain (e.g. `feedback.example.com`)
|
|
5. Set `WEBAUTHN_ORIGIN` to your full URL (e.g. `https://feedback.example.com`)
|
|
|
|
Then start it:
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
Create the initial admin account:
|
|
|
|
```bash
|
|
docker compose exec app npx tsx packages/api/src/cli/create-admin.ts
|
|
```
|
|
|
|
The app is at `http://localhost:3000` (or whatever port you set). Put a reverse proxy in front for HTTPS.
|
|
|
|
## What's included
|
|
|
|
- Boards for organizing feedback by project or topic
|
|
- Feature requests and bug reports with voting and vote budgets
|
|
- Comments with markdown, @mentions, reactions, and file attachments
|
|
- Status tracking with custom statuses per board
|
|
- Roadmap and changelog pages (with scheduled publishing)
|
|
- Full-text search with similar post detection
|
|
- Push notifications and board-level subscriptions
|
|
- RSS feeds per board
|
|
- Post view counts
|
|
- Admin dashboard with post management, merge, bulk actions, edit rollback
|
|
- Team system with invites - super admin, admin, and moderator roles
|
|
- Granular locking - lock post edits, comment edits, threads, or voting independently
|
|
- Recovery codes for cookie-based users who can't use passkeys
|
|
- Plugin system - upload zip plugins through the admin dashboard, no restart needed
|
|
- Embed widget for external sites
|
|
- Dark and light themes
|
|
- i18n ready
|
|
- ALTCHA proof-of-work spam protection (no captchas)
|
|
|
|
## Reverse proxy
|
|
|
|
Echoboard needs HTTPS for passkeys to work. Example nginx config:
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl;
|
|
server_name feedback.example.com;
|
|
|
|
ssl_certificate /path/to/cert.pem;
|
|
ssl_certificate_key /path/to/key.pem;
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:3000;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
client_max_body_size 50m;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Updating
|
|
|
|
```bash
|
|
git pull
|
|
docker compose up -d --build
|
|
```
|
|
|
|
Migrations run automatically on startup.
|
|
|
|
## Data
|
|
|
|
All persistent data lives next to the compose file:
|
|
|
|
- `./data/postgres/` - database
|
|
- `./uploads/` - avatars and attachments
|
|
- `./plugins-installed/` - uploaded plugins
|
|
|
|
## Plugins
|
|
|
|
Plugins are zip files uploaded through the admin dashboard. A plugin contains a `manifest.json` and a JS entry point. Plugins can add API routes, respond to events (post created, status changed, etc.), and store their own data. They run with full server access so only install plugins you trust.
|
|
|
|
A Gitea sync plugin is included in `plugins/gitea-sync/` as an example.
|
|
|
|
## Development
|
|
|
|
```bash
|
|
npm install
|
|
cp .env.example .env
|
|
# set WEBAUTHN_RP_ID=localhost, WEBAUTHN_ORIGIN=http://localhost:5173
|
|
# point DATABASE_URL at a local postgres
|
|
|
|
npm run dev
|
|
```
|
|
|
|
API on port 3001, Vite dev server on port 5173.
|
|
|
|
## License
|
|
|
|
CC0-1.0
|