Deployment
Deploy Kener with Docker or Node.js and verify service health with the healthcheck endpoint
Use this guide when moving from local testing to production. It includes .env examples for PostgreSQL, MySQL, subpath deployments, and both SMTP/Resend email providers.
Quick start with Docker Compose
For most teams, Docker Compose is the fastest path to production.
- Clone the repo.
- Create a
.envfile. - Start services with Docker Compose.
Minimum required values:
KENER_SECRET_KEYORIGINREDIS_URL
Required and common variables
| Variable | Required | Notes |
|---|---|---|
KENER_SECRET_KEY |
Yes | Use a strong random secret |
ORIGIN |
Yes | Public URL, no trailing slash |
REDIS_URL |
Yes | redis:// or rediss:// |
DATABASE_URL |
No | Defaults to SQLite if omitted |
PORT |
No | Defaults to 3000 |
KENER_BASE_PATH |
No | Example: /status |
For full variable reference, see Environment Variables.
.env examples
PostgreSQL + external Redis
KENER_SECRET_KEY=replace_with_a_long_random_secret
ORIGIN=https://status.example.com
DATABASE_URL=postgresql://kener:strongpassword@postgres.example.com:5432/kener
REDIS_URL=redis://redis.example.com:6379
PORT=3000
MySQL + external Redis
KENER_SECRET_KEY=replace_with_a_long_random_secret
ORIGIN=https://status.example.com
DATABASE_URL=mysql://kener:strongpassword@mysql.example.com:3306/kener
REDIS_URL=redis://redis.example.com:6379
PORT=3000
Subpath deployment (`/status`) + PostgreSQL
KENER_SECRET_KEY=replace_with_a_long_random_secret
ORIGIN=https://example.com
KENER_BASE_PATH=/status
DATABASE_URL=postgresql://kener:strongpassword@postgres.example.com:5432/kener
REDIS_URL=redis://redis.example.com:6379
PORT=3000
Important
For subpath deployments, ORIGIN remains the domain root (for example https://example.com), and KENER_BASE_PATH carries the subpath (for example /status).
Email examples in .env
Add one of these blocks to any .env example above.
SMTP enabled
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=mailer-user
SMTP_PASS=mailer-password
SMTP_FROM_EMAIL=status@example.com
SMTP_SECURE=0
Resend enabled
RESEND_API_KEY=re_xxxxxxxxxxxxx
RESEND_SENDER_EMAIL=status@example.com
Note
If SMTP and Resend are both configured, SMTP is used first. See Email Setup.
Using the current Docker Compose with your own DB/Redis
If your team already runs managed PostgreSQL/MySQL/Redis, keep docker-compose.yml and set connection URLs in .env.
Example: current Compose + managed PostgreSQL/Redis
KENER_SECRET_KEY=replace_with_a_long_random_secret
ORIGIN=https://status.example.com
DATABASE_URL=postgresql://kener:strongpassword@pg-managed.example.com:5432/kener
REDIS_URL=rediss://redis-managed.example.com:6380
PORT=3000
Example: current Compose + managed MySQL/Redis
KENER_SECRET_KEY=replace_with_a_long_random_secret
ORIGIN=https://status.example.com
DATABASE_URL=mysql://kener:strongpassword@mysql-managed.example.com:3306/kener
REDIS_URL=redis://redis-managed.example.com:6379
PORT=3000
Docker Compose override examples (self-host DB/Redis)
If you want PostgreSQL/MySQL/Redis containers in the same Docker Compose stack, add an override file and keep app variables in .env.
Option A: `docker-compose.pg.yml`
services:
postgres:
image: postgres:16
environment:
POSTGRES_DB: kener
POSTGRES_USER: kener
POSTGRES_PASSWORD: kener_password
volumes:
- pg_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redis_data:/data
volumes:
pg_data:
redis_data:
Use with this .env:
KENER_SECRET_KEY=replace_with_a_long_random_secret
ORIGIN=https://status.example.com
DATABASE_URL=postgresql://kener:kener_password@postgres:5432/kener
REDIS_URL=redis://redis:6379
PORT=3000
Option B: `docker-compose.mysql.yml`
services:
mysql:
image: mysql:8
environment:
MYSQL_DATABASE: kener
MYSQL_USER: kener
MYSQL_PASSWORD: kener_password
MYSQL_ROOT_PASSWORD: root_password
command: ["--default-authentication-plugin=mysql_native_password"]
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redis_data:/data
volumes:
mysql_data:
redis_data:
Use with this .env:
KENER_SECRET_KEY=replace_with_a_long_random_secret
ORIGIN=https://status.example.com
DATABASE_URL=mysql://kener:kener_password@mysql:3306/kener
REDIS_URL=redis://redis:6379
PORT=3000
Tip
Keep secrets in .env and avoid hardcoding credentials in Compose files.
Pre-built image deployment
You can run official images from either registry:
- Docker Hub:
docker.io/rajnandan1/kener:latest - GHCR:
ghcr.io/rajnandan1/kener:latest
Example using .env:
mkdir -p database
# .env should contain at least KENER_SECRET_KEY, ORIGIN, REDIS_URL
docker run -d \
--name kener \
-p 3000:3000 \
-v "$(pwd)/database:/app/database" \
--env-file .env \
docker.io/rajnandan1/kener:latest
Node.js deployment (without Docker)
Use this when you prefer managing runtime directly on a VM/server.
Requirements:
- Node.js
>= 20 - Redis
git clone https://github.com/rajnandan1/kener.git
cd kener
mv .env-min.example .env
npm install
npm run build
npm run start
Minimum .env:
KENER_SECRET_KEY=replace_with_a_random_string
ORIGIN=https://status.example.com
REDIS_URL=redis://localhost:6379
PORT=3000
# Optional (defaults to SQLite):
# DATABASE_URL=sqlite://./database/kener.sqlite.db
Healthcheck URL
Kener exposes a healthcheck endpoint from the server entrypoint.
- Default path:
https://your-domain/healthcheck - With base path (
KENER_BASE_PATH=/status):https://your-domain/status/healthcheck
Quick verification:
curl -fsS https://your-domain/healthcheck
Expected response body:
ok
Next steps
- For reverse proxy and TLS setup, continue with Reverse Proxy Setup.
- If you deploy under a subpath (
/status), follow Base Path Deployment. - For initial local setup, see Quick Start.
- For database-specific guidance, see Database Setup.
- For email configuration details, see Email Setup.