Self-host HookTray

HookTray is designed to be self-hosted. The codebase is small, the dependencies are minimal, and the configuration is explicit. You can run it with Docker Compose in a few minutes.

Prerequisites

  • Docker and Docker Compose (for the Docker path)
  • .NET 10 SDK and Node.js 20+ (for the manual path)
  • A domain or reverse proxy if you want HTTPS

Quick start with Docker Compose

Clone the repository, set the deployment environment, and start the production compose file:

git clone https://github.com/dgknttr/hooktray.git
cd hooktray
printf "DOMAIN=hooktray.example.com\nTOKEN_SIGNING_KEY=$(openssl rand -base64 32)\n" > .env
docker compose -f docker-compose.prod.yml --env-file .env up -d

The nginx service binds to 127.0.0.1:3000 so it can sit behind your host reverse proxy. Point HTTPS traffic for your domain at that local port.

Manual setup

Backend

cd backend
dotnet restore HookTray.sln
dotnet run --project HookTray.Api

Frontend

cd frontend
npm ci
NEXT_PUBLIC_API_URL=http://localhost:5221 npm run dev

Configuration reference

Backend settings live in backend/HookTray.Api/appsettings.json. All values can be overridden with environment variables.

SettingPurpose
Webhook:MaxBodyBytesMaximum accepted webhook payload size
Webhook:BodyPreviewLengthPreview length shown in the request list
Session:TtlSession lifetime after inactivity
Session:CleanupIntervalBackground cleanup interval
RateLimit:MaxWebhooksPerMinutePer-token webhook receive limit
RateLimit:MaxTokenCreationsPerMinutePerIpToken creation limit per IP
RateLimit:MaxSessionRestoresPerMinutePerIpSame-token SSE restore limit per IP
Token:SigningKeyProduction signing key for new hook tokens
Cors:AllowedOriginsFrontend origins allowed to call the API

Production deployments must provide Token:SigningKey. In Docker Compose, set TOKEN_SIGNING_KEY. The frontend API origin is configured at build time with NEXT_PUBLIC_API_URL.

Behind a reverse proxy

The SSE endpoint (/api/stream/*) requires proxy buffering to be disabled. For nginx, set proxy_buffering off on that location block. The included nginx/hooktray.conf.template has this configured correctly.