Skip to content
Kudos

Self-hosting

Kudos runs as a hosted service at getkudos.eu. You can also run it on your own server with Docker Compose. A self-hosted install usually serves a single Tenant: your own company.

Licence

Kudos is source-available under the Business Source License 1.1. Testing and other non-production use are free. Running it in production on your own server needs a commercial licence from Erwins Enkel GmbH; contact us. Each version becomes Apache 2.0 four years after its release.

Requirements

  • A Linux server with Docker and Docker Compose
  • A domain name and a reverse proxy for HTTPS (for example Caddy or nginx)
  • Your company's sign-in: Microsoft Entra ID, another OpenID Connect provider or GitHub
  • An Autotask API user (see Autotask)
  • Optional: an SMTP account for email (an EU provider is recommended)

Install

  1. Get the Kudos source code and change into its directory.

  2. Create a file .env next to compose.yaml:

    ORIGIN=https://kudos.example.com
    SECRET_KEY=<output of: openssl rand -base64 32>
    POSTGRES_PASSWORD=<output of: openssl rand -hex 24>
    OWNER_DB_PASSWORD=<output of: openssl rand -hex 24>
    APP_DB_PASSWORD=<output of: openssl rand -hex 24>
    ADDRESS_HEADER=X-Forwarded-For
    

    ORIGIN is the address your users open; sign-in redirects and email links use it. SECRET_KEY encrypts your sign-in and Autotask secrets in the database: keep it safe, without it they cannot be read. The database passwords must be hex.

  3. Start Kudos: docker compose up -d. Compose builds the image, sets up the database, applies migrations and starts the app on 127.0.0.1:3000.

  4. Create your Tenant and its first Admin, see First Tenant.

First Tenant

docker compose run --rm ops bun build/cli/kudos.js tenant create --name "Example GmbH"
docker compose run --rm ops bun build/cli/kudos.js admin bootstrap <slug> --email you@example.com --name "Your Name"

The first command prints the Tenant's slug, the second a sign-in link for the first Admin, valid once for 24 hours. Open it and continue with Getting started. Once your company's sign-in is set up and an Admin has used it, no more such links are issued.

Set SINGLE_TENANT_SLUG=<slug> in .env and run docker compose up -d again: the start page then leads straight to your Tenant's sign-in.

Reverse proxy

The app listens on 127.0.0.1 only. Put a reverse proxy on the same host in front of it that terminates HTTPS, for example with Caddy:

kudos.example.com {
	reverse_proxy 127.0.0.1:3000
}

Kudos uses the visitor's IP address for rate limits, so it needs to know where it comes from. Set exactly one of:

  • ADDRESS_HEADER=X-Forwarded-For behind a proxy. XFF_DEPTH (default 1) is the number of proxies in front of the app. Only use this while the proxy is the sole way in, since a visitor reaching the app directly could fake the header.
  • DIRECT_CLIENT_ADDRESS=true when visitors connect to the app directly, without a proxy.

The app refuses to start without one of them.

If anything else can reach the app (another container on its network, say), set PROXY_SECRET to a long random value (openssl rand -hex 32) and have the proxy send it in the X-Kudos-Proxy-Secret header. The app then refuses every request without it, except GET /healthz.

Options

Variable Effect
SMTP_URL, MAIL_FROM Send email (invitations, alerts), e.g. smtps://user:pass@host:465. Unset, it is only logged
SENTRY_DSN Report server errors and failed jobs to Sentry or a compatible tracker
PORT Host port of the app, default 3000
SINGLE_TENANT_SLUG The start page leads to this Tenant's sign-in

Customer CSAT PDFs are rendered by the pdf service that Compose starts with the app. Self-hosted installs have no billing and no public signup. The full list of settings with explanations is in .env.schema.

Updates and backups

To update, get the new source code and run docker compose up -d --build. Database migrations run automatically before the app starts.

All data lives in the PostgreSQL database in the Docker volume db-data. Back it up regularly with your usual tooling, for example pg_dumpall, and keep .env (above all SECRET_KEY) with it.

Command line

Run commands as docker compose run --rm ops bun build/cli/kudos.js <command>:

Command Effect
tenant create --name <name> Create a Tenant, prints its slug
tenant list List Tenants with status and active Members
tenant suspend <slug>, tenant reactivate <slug> Suspend or reactivate a Tenant
admin bootstrap <slug> --email <e> --name <n> Sign-in link for the first Admin
demo seed <slug> Fill an empty Tenant with six months of demo data
scanner list, scanner add ua|ip <value>, scanner remove ua|ip <value> Link scanners (by user agent or IP range) whose clicks on rating links are ignored

bun build/cli/kudos.js --help lists every command.