Skip to content

Self-Hosting

Run Kitbase on your own server in minutes with our interactive setup script.

Prerequisites

  • A server running Ubuntu (the setup script is only tested on Ubuntu)
  • At least 4 GB of RAM

Quick Start

1

Run the setup script

bash
git clone https://github.com/scr2em/kitbase-sdk.git
cd kitbase-sdk/self-host
sudo bash setup.sh

Why sudo?

The setup script installs Docker and Docker Compose if they're not already present, which requires root privileges. Running with sudo ensures the script can install dependencies and manage Docker without permission errors.

The script will check and install dependencies (Docker, Docker Compose), walk you through the configuration, generate your .env file, and start all services.

2

Open Kitbase

Once the script finishes, open your configured domain in the browser.

Architecture

Everything runs behind Caddy, which handles SSL automatically:

Routing

PathService
/Dashboard (SPA)
/api/Backend API

Services

ContainerPurpose
kitbase_caddyCaddy — reverse proxy with automatic HTTPS
kitbase_dashboardServes the dashboard SPA
kitbase_backendJava/Spring API server
kitbase_mysqlMySQL 8.3 database
kitbase_clickhouseClickHouse analytics database
kitbase_redisRedis cache

Configuration

All configuration is done through environment variables in your .env file (generated by the setup script). The setup script handles the essentials — you can fine-tune everything else later.

VariableDefaultDescription
JWT_SECRETRequired. Secret key for JWT tokens. Generate with openssl rand -base64 32
DATABASE_PASSWORDRequired. MySQL root password
APP_DOMAINlocalhostYour domain name (without protocol)
APP_PROTOCOLhttphttp or https

For the full list of variables (email, OAuth, Stripe, storage, logging, and more), see the Environment Variables reference.

Email

The setup script lets you choose between three email providers:

  • SMTP — any SMTP server (Mailgun, SendGrid SMTP, Postmark, your own server, etc.)
  • AWS SES — send via the AWS SES API using an access key and secret (no SMTP needed)
  • Resend — send via the Resend API using an API key

You can skip email during setup and configure it later. See the Email Providers guide for detailed setup and switching instructions.

Billing

Self-hosted instances have unlimited usage with no plan restrictions.

Changing Configuration

The setup script generates two files: .env (environment variables) and Caddyfile (reverse proxy). To change anything after the initial setup, edit these files directly and restart:

bash
# Edit configuration
nano .env

# Apply changes
docker compose up -d

If you changed the Caddyfile, restart Caddy specifically:

bash
docker compose restart caddy

TIP

You can also re-run sudo bash setup.sh to go through the interactive setup again. This will overwrite your .env and Caddyfile with the new values.

Custom Domain

Point your domain's DNS to your server's IP, then re-run the setup script with https://yourdomain.com as the domain. Caddy will automatically provision an SSL certificate from Let's Encrypt.

Alternatively, update the files manually:

  1. Update your .env:
bash
APP_DOMAIN=kitbase.example.com
APP_PROTOCOL=https
MAIL_BASE_URL=https://kitbase.example.com
  1. Update your Caddyfile:
caddyfile
kitbase.example.com {
    encode gzip

    handle /api/* {
        reverse_proxy backend:8100
    }

    handle {
        reverse_proxy dashboard:80
    }
}
  1. If using OAuth, update the redirect URIs in .env:
bash
OAUTH_GOOGLE_REDIRECT_URI=https://kitbase.example.com/api/auth/oauth/google/callback
OAUTH_GITHUB_REDIRECT_URI=https://kitbase.example.com/api/auth/oauth/github/callback
  1. Restart:
bash
docker compose restart caddy

TIP

Make sure ports 80 and 443 are open in your firewall / security group. Caddy needs port 80 for the ACME challenge and HTTP → HTTPS redirect, and port 443 for HTTPS.

External Databases

By default, the Docker Compose setup includes MySQL, ClickHouse, and Redis containers. If you prefer to use managed or external instances (e.g., Amazon RDS, ClickHouse Cloud, ElastiCache), you can point Kitbase to them instead.

External MySQL

  1. Add the connection details to your .env:
bash
DATABASE_URL=jdbc:mysql://your-mysql-host:3306/flyway_db?createDatabaseIfNotExist=true&useSSL=true
DATABASE_USERNAME=kitbase
DATABASE_PASSWORD=your-password
  1. Remove the mysql service from docker-compose.yml and remove mysql from the backend's depends_on.

TIP

The database must be MySQL 8.0+. Kitbase runs migrations automatically on startup, so the database can be empty.

External ClickHouse

  1. Add the connection details to your .env:
bash
CLICKHOUSE_URL=jdbc:clickhouse://your-clickhouse-host:8123/analytics
CLICKHOUSE_USERNAME=default
CLICKHOUSE_PASSWORD=your-password
  1. Remove the clickhouse service from docker-compose.yml and remove clickhouse from the backend's depends_on.

External Redis

  1. Add the connection details to your .env:
bash
REDIS_HOST=your-redis-host
REDIS_PORT=6379
  1. Remove the redis service from docker-compose.yml and remove redis from the backend's depends_on.

WARNING

When removing a service from docker-compose.yml, make sure to also remove it from the depends_on section of the backend service, otherwise Docker Compose will fail to start.

SDK Configuration

When using the Kitbase SDK with a self-hosted instance, point baseUrl to your server's /api path:

typescript
import { init } from '@kitbase/analytics';

const kitbase = init({
  sdkKey: '<YOUR_SDK_KEY>',
  baseUrl: 'https://kitbase.example.com/api',
});

For the tracking script:

html
<script>
  window.KITBASE_CONFIG = {
    sdkKey: 'YOUR_SDK_KEY',
    baseUrl: 'https://kitbase.example.com/api',
  };
</script>
<script defer src="https://kitbase.dev/lite.js"></script>

TIP

The lite.js script itself is a lightweight loader hosted on the Kitbase CDN. It sends all data to the baseUrl you configure — your self-hosted server receives all the analytics data directly.

Managing Data

Backups

Back up your data by dumping the Docker volumes:

bash
# MySQL
docker exec kitbase_mysql mysqldump -u root -p flyway_db > backup.sql

# ClickHouse
docker exec kitbase_clickhouse clickhouse-client --query "SELECT * FROM analytics.custom_events FORMAT Native" > events.backup

Data Volumes

VolumeContents
mysql_dataUser accounts, projects, feature flags, settings
clickhouse_dataAnalytics events, sessions, pageviews
redis_dataCache and rate limiting data

Updating

When a new version of Kitbase is released, update your self-hosted instance by pulling the latest images and restarting:

bash
cd ~/kitbase-sdk/self-host

# Pull latest changes (e.g. docker-compose.yml, setup script)
git pull

# Pull latest images
docker compose pull

# Restart with new images
docker compose up -d

Your data is stored in Docker volumes and is preserved across updates. To update a specific service only:

bash
# Update just the dashboard
docker compose pull dashboard
docker compose up -d dashboard

# Update just the backend
docker compose pull backend
docker compose up -d backend

TIP

The backend may take up to a minute to start while it runs database migrations and loads resources. During this time, API requests will return 502. The dashboard will remain accessible.

Troubleshooting

Checking logs

bash
# All services
docker compose logs -f

# Specific service
docker compose logs -f backend

Backend won't start

The backend waits for MySQL, ClickHouse, and Redis to be healthy before starting. Check their health:

bash
docker compose ps

Reset everything

bash
docker compose down -v
docker compose up -d

WARNING

This deletes all data. Only use this if you want a fresh start.

Released under the MIT License.