Self Hosting

Keygen is designed to be self-hosted through Docker. You don't have to be a Docker expert to launch your own instance of Keygen, but you should have a basic understanding of the command line and networking to successfully set up your own instance of Keygen.

Don't want to manage infrastructure? The easiest way to get started with Keygen is with our managed offering, Keygen Cloud. High availability, backups, security, and maintenance are all handled for you by our team. The section below is for self-hosting our licensing and distribution API on your own servers and managing your own infrastructure.

The source code for Keygen can be found on our GitHub.

Editions

There are two editions of Keygen. One tailored to hobbyists and DIYers, and one for businesses.

Community Edition

Keygen CE is the Community Edition of Keygen. Keygen CE is free (as in beer). This is the default edition, but can be explicitly configured with the following environment variable:

KEYGEN_EDITION="CE"

We offer best-effort support for Keygen CE users. If your business runs Keygen and needs dedicated support, consider purchasing Keygen EE or becoming a Keygen Cloud customer.

There is a community-supported Discord server and forum where you can ask for help.

Enterprise Edition

Keygen EE is the Enterprise Edition of Keygen. Keygen EE requires a valid license key to run. To purchase a license key, click here, or reach out for a 30-day no-strings-attached trial.

Keygen EE can be configured with the following environment variables:

KEYGEN_LICENSE_FILE_PATH="/etc/keygen/ee.lic"
KEYGEN_LICENSE_KEY="C1B6DE-39A6E3-DE1529-8559A0-4AF593-V3"
KEYGEN_EDITION="EE"

Keygen EE enables the following features:

  • Request logs: keep a historical record of API requests, along with who made the request, the request body, response body, status code, IP address, and other information.
  • Event logs: keep an audit trail of every single event that happens on a Keygen account.
  • Environments: manage separate environments within a Keygen account, from test environments, to a sandbox, to QA, to production.
  • Permissions: enterprise-grade roles and permissions.
  • SSO/SAML: support for SSO/SAML coming soon.

In addition, Keygen EE customers are entitled to dedicated support.

To purchase a Keygen EE license, click here. Not ready to purchase? Contact sales with any questions, or for a 30-day no-strings-attached trial of Keygen EE.

We'd love to get your team set up!

Modes

There are also two modes of Keygen.

Singleplayer mode

The single-tenant mode of Keygen. This is the default mode, but can be explicitly configured with the following environment variable:

KEYGEN_MODE="singleplayer"

In singleplayer mode, the account URL prefix can be ommitted. For example, /v1/accounts/<account>/licenses would become /v1/licenses. This is because in singleplayer mode, there is only 1 account, making the prefix superfluous.

Multiplayer mode

The multi-tenant mode of Keygen. This mode requires a Keygen EE license with the multiplayer entitlement. Currently, Keygen Cloud is the only multiplayer instance of Keygen.

KEYGEN_MODE="multiplayer"

If you're interested in multiplayer mode, please reach out.

Versioning

Keygen follows semantic versioning. You can find all available Keygen versions on Docker Hub.

The default latest tag refers to the latest stable release tag.

You can also pin your version:

  • keygen/api:v1 pins the major version to 1 but allows minor and patch version upgrades.
  • keygen/api:v1.3 pins the minor version to 1.3 but allows only patch upgrades.

The self-hosted versions of Keygen are somewhat of a Long-Term Support (LTS) release, getting a new release roughly twice a year after being battle tested in Keygen Cloud. If you want features as soon as they're available, consider becoming a Keygen Cloud customer, or alteratively, build the Docker image from source (but understand the risks associated with running edge software).

After reviewing what other maintainers of popular open source projects do, it seems like a bi-yearly schedule works well for everyone vs. more frequent updates:

  • Self-hosters can upgrade their setup less frequently, which saves them time spent on maintenance and reduces their workload.
  • We can cut new self-hosted releases less frequently and are able to put more effort into creating a better release DX.
This means that any new features that we announce and release in Keygen Cloud may take a bit longer to make their way into Keygen CE and Keygen EE. But the features will be well-tested, and the upgrade process can be better understood and better documented.

No functionality or bug fixes will be backported to older versions. If you wish to get the latest bug fixes and security updates, you can upgrade to the latest version.

The Docker image and Keygen's API itself are versioned separately. For information on our API's versioning policy, please see Versioning.

You can subscribe to version updates via our RSS feed:

https://github.com/keygen-sh/keygen-api/tags.atom

Use your favorite RSS reader.

Requirements

The only thing you need to install Keygen is a server with Docker installed. The server must have a CPU with the x86_64 architecture, and support for SSE 4.2 instructions. We recommend using a minimum of 500MB of RAM, but exact requirements will depend on configuration.

If your server does not have Docker installed, you can follow their instructions.

Keygen requires Ruby >= 3.1, Postgres >= 13, and Redis >= 6.2.

Installation

Installing Keygen can be done in a few ways, depending on if you're just checking out Keygen CE or if you're looking to self-host Keygen EE for production use.

Docker Compose

The easiest way to get up and running for small or hobby instances is by using Docker Compose. This will set up everything you need for a small-scale production-ready Keygen installation — a server, worker, databases, and a reverse-proxy with TLS.

After cloning, run the setup container and note the output:

docker compose --profile setup run --rm setup

Next, configure your environment via .env, and run:

docker compose up

Alternatively, you can use Docker directly as described below.

Docker Hub

The easiest way to get started with Keygen is to pull via Docker Hub.

docker pull keygen/api

For most production deployments, you will use Docker Hub.

Clone the repository

Alternatively, you can clone the GitHub repository and build the image manually:

git clone https://github.com/keygen-sh/keygen-api

After cloning, you can can build the Docker image:

docker build -t keygen/api .

Tarball

Alternatively, you can download and extract a tarball from GitHub:

curl -L https://github.com/keygen-sh/keygen-api/archive/master.tar.gz | tar -xz

After downloading, you can build the Docker image.

Configuration

Keygen is a twelve-factor app, therefore configuring Keygen can be accomplished using environment variables. Keygen can be configured with the following variables:

Required Default Description
KEYGEN_EDITION No CE The edition of Keygen to run: either CE for the Community Edition, or EE for the Enterprise Edition.
KEYGEN_MODE No singleplayer The mode of Keygen: either singleplayer for single-tenant, or multiplayer for multi-tenant.
Multiplayer mode requires a Keygen EE license with the multiplayer entitlement.
KEYGEN_ACCOUNT_ID Yes* The account ID used for setting the tenant of Keygen in singleplayer mode. Use bundle exec rails keygen:setup to generate one, or use uuidgen or cat /proc/sys/kernel/random/uuid to set a pre-determined ID.
* Required in singleplayer mode.
KEYGEN_HOST Yes The primary host that Keygen's API will be accessible at, e.g. licensing.example.com. This cannot be an IP address — it MUST a domain name.
KEYGEN_HOSTS No Additional hosts that Keygen will be accessible at, e.g. pypi.pkg.example.com. Like KEYGEN_HOST, these MUST be domain names, not IPs.
KEYGEN_LICENSE_FILE_PATH No* The path to a Keygen EE license file, e.g. /etc/keygen/ee.lic.
* Either KEYGEN_LICENSE_FILE_PATH or KEYGEN_LICENSE_FILE are required in Keygen EE.
KEYGEN_LICENSE_FILE No* A base64 encoded Keygen EE license file. This is useful when a file system is not available for KEYGEN_LICENSE_FILE_PATH, e.g. with Heroku.
* Either KEYGEN_LICENSE_FILE_PATH or KEYGEN_LICENSE_FILE are required in Keygen EE.
KEYGEN_LICENSE_KEY No* The license key used to decrypt the Keygen EE license file.
* Required in Keygen EE.
KEYGEN_DOMAIN No The primary domain Keygen's API will be accessible at. By default, this is parsed from KEYGEN_HOST, but that may result in inaccuracies under certain TLDs, e.g. co.uk.
KEYGEN_SUBDOMAIN No The primary subdomain Keygen's API will be accessible at. By default, parsed from KEYGEN_HOST, but that may result in inaccuracies under multiple subdomains.
KEYGEN_PRUNE_EVENT_BACKLOG_DAYS No 90 The number of days that high-volume event logs are kept before being pruned.
Set to -1 to disable pruning.
KEYGEN_PRUNE_REQUEST_BACKLOG_DAYS No 30 The number of days that request logs are kept before being pruned.
Set to -1 to disable pruning.
KEYGEN_PRUNE_WEBHOOK_BACKLOG_DAYS No 30 The number of days that webhook events are kept before being pruned.
Set to -1 to disable pruning.
KEYGEN_PRUNE_BATCH_SIZE No 10000 The number of rows pruned per-batch during pruning.
KEYGEN_PRUNE_BATCH_WAIT No 1 The amount of time, in seconds, to wait in between batches during pruning.
KEYGEN_ADMIN_EMAIL No The admin email used during setup. Must be a valid email address for your organization.
KEYGEN_ADMIN_PASSWORD No The admin password used during setup. Must be at least 6 characters. Use openssl rand -hex 16 to generate one.
We recommend a random 16-byte secret.
PORT No 3000 The port on which the server is available.
BIND No 0.0.0.0 The IP address on which the server is listening.
E.g. 0.0.0.0 = all interfaces, 127.0.0.1 = localhost.
DATABASE_URL Yes The Postgres database URL, e.g. postgres://postgres:postgres@localhost:5432.
DB_POOL No The number of database connections Keygen will use per-process. By default, this will equal RAILS_MAX_THREADS or SIDEKIQ_CONCURRENCY, determined by web vs worker process, respectively (i.e. each thread will have its own database connection). Because of this default, most applications do not need to set this. But it's there if you need to override the default behavior for some reason.
DB_TIMEOUT No 5000 The database query timeout, in ms.
REDIS_URL Yes The Redis database URL, e.g. redis://localhost:6379.
REDIS_PROVIDER No REDIS_URL The name of the environment variable pointing to Sidekiq's Redis. Set if you want to use an isolated Redis database for background jobs.
This should be the name of an environment variable, not a Redis URL.
REDIS_POOL_SIZE No The number of Redis connections Keygen will use per-process. By default, this will equal RAILS_MAX_THREADS or SIDEKIQ_CONCURRENCY, determined by web vs worker process, respectively (i.e. each thread will have its own database connection). Because of this default, most applications do not need to set this. But it's there if you need to override the default behavior for some reason.
REDIS_POOL_TIMEOUT No 5 The Redis pool timeout, in seconds.
REDIS_CONNECT_TIMEOUT No 5 The Redis connect timeout, in seconds.
REDIS_READ_TIMEOUT No 5 The Redis read timeout, in seconds.
REDIS_WRITE_TIMEOUT No 5 The Redis write timeout, in seconds.
REDIS_RECONNECT_ATTEMPTS No 5 The number of reconnect attempts for failed connections to Redis.
SECRET_KEY_BASE Yes An internal secret key used by Ruby on Rails. Use rails secret or openssl rand -hex 64 to generate one.
We recommend a random 64-byte secret.
ENCRYPTION_DETERMINISTIC_KEY Yes The deterministic key used for at-work encryption. Use rails db:encryption:init or openssl rand -base64 32 to generate one.
We recommend a random 32-byte secret. No less than 12-bytes.
ENCRYPTION_PRIMARY_KEY Yes The primary key used for at-work encryption. Use rails db:encryption:init or openssl rand -base64 32 to generate one.
We recommend a random 32-byte secret. No less than 12-bytes.
ENCRYPTION_KEY_DERIVATION_SALT Yes The key derivation salt used for at-work encryption. Use rails db:encryption:init or openssl rand -base64 32 to generate one.
We recommend a random 32-byte secret. No less than 20-bytes.
CF_ACCESS_KEY_ID No* The Cloudflare R2 access key ID.
* Without Cloudflare R2 or AWS S3, uploading and downloading release artifacts will fail.
CF_SECRET_ACCESS_KEY No* The Cloudflare R2 secret access key.
* Without Cloudflare R2 or AWS S3, uploading and downloading release artifacts will fail.
CF_ACCOUNT_ID No* The Cloudflare R2 account ID.
* Without Cloudflare R2 or AWS S3, uploading and downloading release artifacts will fail.
CF_BUCKET No* The Cloudflare R2 bucket to upload artifacts to.
* Without Cloudflare R2 or AWS S3, uploading and downloading release artifacts will fail.
CF_REGION No* The Cloudflare R2 region.
* Without Cloudflare R2 or AWS S3, uploading and downloading release artifacts will fail.
AWS_ACCESS_KEY_ID No* The AWS S3 access key ID.
* Without Cloudflare R2 or AWS S3, uploading and downloading release artifacts will fail.
AWS_SECRET_ACCESS_KEY No* The AWS S3 secret access key.
* Without Cloudflare R2 or AWS S3, uploading and downloading release artifacts will fail.
AWS_BUCKET No* The AWS S3 bucket to upload artifacts to.
* Without Cloudflare R2 or AWS S3, uploading and downloading release artifacts will fail.
AWS_REGION No* The AWS S3 region.
* Without Cloudflare R2 or AWS S3, uploading and downloading release artifacts will fail.
RAILS_ENV No production The environment for Ruby on Rails.
RAILS_LOG_LEVEL No info The log level for Ruby on Rails.
RAILS_LOG_TO_STDOUT No 1 Set this environment variable to send all application logs to stdout.
RAILS_KEEP_ALIVE_TIMEOUT No 20 The timeout for idle connections to Puma, in seconds.
RAILS_MAX_THREADS No 2 The maximum number of threads per Puma worker. Each thread can handle a concurrent request, thus this controls concurrency. Generally, you should aim to be between 1 and 5 threads per-worker; anything else and you may begin trading throughput for latency due to Ruby's GIL. You SHOULD NOT exceed your available CPU core count.
RAILS_MIN_THREADS No $RAILS_MAX_THREADS The minimum number of threads per Puma worker.
RAILS_SERVE_STATIC_FILES No Set this environment varialbe to serve assets from the public/ directory.
RUBY_YJIT_ENABLE No Enable YJIT, a just-in-time compiler for Ruby. This will increase execution speed at the cost of memory. When memory allows, we recommend enabling YJIT. We've seen up to a 30% improvement in execution speed with YJIT, which equals more throughput.
RUBYOPT No Configure the MRI Ruby runtime. For example, you can add flags such as --yjit-exec-mem-size=32 to adjust YJIT memory usage, or set -W2 to adjust warning verbosity.
WEB_CONCURRENCY No 2 The number of Puma workers. Each worker is a separate process that runs an instance of Keygen. The higher the worker count, the higher the memory consumption. The more workers you have, the throughput (concurrency) you will you have. Generally, you should have as many workers as memory allows. For the average 512MB server, that may be 2; for a more beefy 14GB server, that may be 42.
SIDEKIQ_CONCURRENCY No 10 The number of Sidekiq workers. The more workers, the faster background jobs are processed. The higher the worker count, the higher the memory consumption.
SIDEKIQ_WEB_USER No The username for accessing the Sidekiq monitoring UI.
SIDEKIQ_WEB_PASSWORD No The password for accessing the Sidekiq monitoring UI.
RACK_TIMEOUT_SERVICE_TIMEOUT No 15 Documentation for rack-timeout can be found here.
RACK_TIMEOUT_WAIT_TIMEOUT No 30 Documentation for rack-timeout can be found here.
RACK_TIMEOUT_WAIT_OVERTIME No 60 Documentation for rack-timeout can be found here.
RACK_TIMEOUT_SERVICE_PAST_WAIT No 0 Documentation for rack-timeout can be found here.
RACK_TIMEOUT_TERM_ON_TIMEOUT No 0 Documentation for rack-timeout can be found here.
RACK_ATTACK_IP_WHITELIST No Comma-delimited list of IP addresses or IP ranges that are whitelisted by the internal rate limiter. These IPs will never be rate limited.
RACK_ATTACK_IP_BLACKLIST No Comma-delimited list of IP addresses or IP ranges that are blacklisted by the internal rate limiter. These IPs will always be blocked.
RACK_ATTACK_MAX_RPS No -1 The maximum number of requests per-second that a given IP address can make before being rate limited. Set to -1 to disable this rate limiter.
RACK_ATTACK_MAX_RPM No -1 The maximum number of requests per-minute that a given IP address can make before being rate limited. Set to -1 to disable this rate limiter.
NO_RACK_ATTACK No Set this environment variable to completely disable the rate limiter.
NO_SENTRY No Set this environment variable to disable Sentry.
SENTRY_DSN No The DSN for Sentry, for error reporting and performance monitoring.
SENTRY_TRACES_SAMPLE_RATE No 0.0 Trace sample rate for Sentry performance monitoring (APM). We recommend a value under 0.2, but it will ultimately depend on your production load.
SENTRY_PROFILES_SAMPLE_RATE No 0.0 Profile sample rate for Sentry performance monitoring (APM). We recommend a value of 0.1, but it will ultimately depend on your production load.
JUDOSCALE_URL No The URL for Judoscale (Rails Autoscale), an autoscaler for Heroku, Render, and other PaaS providers.
NO_JUDOSCALE No Set this environment variable to disable Judoscale.
CRONITOR_API_KEY No The API key for Cronitor, a background job monitor.
NO_CRONITOR No Set this environment variable to disable Cronitor.
SENDGRID_API_KEY No The API key for SendGrid, for sending transactional email.
NO_SENDGRID No Set this environment variable to disable SendGrid.
TRUSTED_PROXIES No A comma-delimited list of trusted proxy IP addresses.

Configure Postgres

Keygen's main application database is Postgres. The minimum supported version is Postgres 13. Storage and connection requirements will vary depending on volume.

You can set the Postgres database using the following environment variable:

DATABASE_URL="postgres://postgres:postgres@localhost:5432"

To start a non-production Postgres container, run:

docker run --name postgres -d -p 5432:5432 \
-v postgres:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=postgres \
postgres

Ensure Postgres is running before proceeding.

Configure Redis

Keygen's cache and background job database is Redis. The minimum supported version is Redis 6.2. Storage and connection requirements will vary.

The default eviction policy for Redis is volatile-lru for most databases, but we recommend using noeviction for the Redis database used for background jobs, to prevent catastrophic job loss in case the Redis maxmemory value is reached.

You can set the Redis database using the following environment variable:

REDIS_URL="redis://localhost:6379"

To start a non-production Redis container, run:

docker run --name redis -d -p 6379:6379 \
-v redis:/var/lib/redis/data \
redis

Ensure Redis is running before proceeding.

Configure Keygen

The easiest way to get Keygen set up is to use the setup command. It will walk you through the necessary steps to set up your Keygen instance and environment.

docker run --rm -it -e SECRET_KEY_BASE="$(openssl rand -hex 64)" \
-e ENCRYPTION_DETERMINISTIC_KEY="$(openssl rand -base64 32)" \
-e ENCRYPTION_PRIMARY_KEY="$(openssl rand -base64 32)" \
-e ENCRYPTION_KEY_DERIVATION_SALT="$(openssl rand -base64 32)" \
-e DATABASE_URL="postgres://postgres:[email protected]:5432/postgres" \
-e REDIS_URL="redis://host.docker.internal:6379" \
-e KEYGEN_HOST="api.keygen.localhost" \
-e KEYGEN_MODE="singleplayer" \
-e KEYGEN_EDITION="EE" \
keygen/api setup

The setup command requires a TTY by default. If you're deploying to a platform that does not provide a TTY, you can manually supply the following environment variables to skip all prompts: SECRET_KEY_BASE, ENCRYPTION_DETERMINISTIC_KEY, ENCRYPTION_PRIMARY_KEY, ENCRYPTION_KEY_DERIVATION_SALT, KEYGEN_ACCOUNT_ID, KEYGEN_ADMIN_EMAIL, KEYGEN_ADMIN_PASSWORD, KEYGEN_EDITION, and KEYGEN_MODE.

If you're unsure what any of these environment variables are for, please refer to the configuration section of this page. If you do not provide all the aforementioned variables and a TTY is not available, the setup command will fail.

Please note that Postgres and Redis must be setup and running beforehand.

After running the setup command, set the resulting environment variables.

Running

Keygen has two processes types, server and worker.

Starting the server

Keygen uses Puma as its web server to serve the API. By default, the server listens for HTTP(S) requests on port 3000. The server only supports HTTP 1.1, it does NOT support HTTP 2.

To start the server, run the following command:

docker run --name web.1 -p 127.0.0.1:3000:3000 -e SECRET_KEY_BASE="${SECRET_KEY_BASE}" \
-e ENCRYPTION_DETERMINISTIC_KEY="${ENCRYPTION_DETERMINISTIC_KEY}" \
-e ENCRYPTION_PRIMARY_KEY="${ENCRYPTION_PRIMARY_KEY}" \
-e ENCRYPTION_KEY_DERIVATION_SALT="${ENCRYPTION_KEY_DERIVATION_SALT}" \
-e DATABASE_URL="postgres://postgres:[email protected]:5432/postgres" \
-e REDIS_URL="redis://host.docker.internal:6379" \
-e KEYGEN_LICENSE_FILE_PATH="${KEYGEN_LICENSE_FILE_PATH}" \
-e KEYGEN_LICENSE_KEY="${KEYGEN_LICENSE_KEY}" \
-e KEYGEN_ACCOUNT_ID="${KEYGEN_ACCOUNT_ID}" \
-e KEYGEN_EDITION="${KEYGEN_EDITION}" \
-e KEYGEN_MODE="${KEYGEN_MODE}" \
-e KEYGEN_HOST="${KEYGEN_HOST}" \
-v /etc/keygen:/etc/keygen \
keygen/api web
Docker on Linux does not support the above host.docker.internal hostnames used for the non-production Postgres and Redis URLs. You may need to add the --add-host host.docker.internal:host-gateway flag.
Keygen requires TLS and implements HTTP Strict Transport Security (HSTS), but Keygen does not perform TLS termination itself. A reverse proxy providing TLS termination is required, sitting in front of the web process. Traefik, Nginx, and Caddy are popular reverse proxies.

To access Keygen on localhost over TLS, you can use a reverse proxy such as Caddy:

echo '127.0.0.1 api.keygen.localhost' | sudo tee -a /etc/hosts
caddy reverse-proxy --from api.keygen.localhost --to :3000

Feel free to use a different reverse proxy, such as Traefik, Nginx, or Apache.

Your reverse proxy MUST be a well-behaved reverse proxy by setting all X-Forwarded-* headers. Keygen WILL NOT be accessible and WILL NOT operate correctly if your reverse proxy does not provide the following forwarding information:

  • X-Forwarded-Proto is used to determine if the original request was over TLS before passing through a TSL-terminating reverse proxy.
  • X-Forwarded-For is used to determine the original client IP for rate limiting/logging purposes.
  • X-Forwarded-Host is used to determine the original host of the request.

If your reverse proxy does not provide these headers, you MUST modify it to do so.

Keygen should now be available at:

curl -I https://api.keygen.localhost/v1/ping
# HTTP/2 200
# ...

If you're unable to ping the server, check the logs. Keygen logs to stdout by default. If you're able to ping the server but it redirects, your reverse proxy may not be providing forwarding information (see above i.r.t. well-behaved reverse proxies).

For health checks, use the /v1/health endpoint.

Starting a worker

Keygen uses Sidekiq to process background jobs, including jobs for license expirations, webhooks, machine heartbeats, and more.

To start Sidekiq, run the following command:

docker run --name worker.1 -e SECRET_KEY_BASE="${SECRET_KEY_BASE}" \
-e ENCRYPTION_DETERMINISTIC_KEY="${ENCRYPTION_DETERMINISTIC_KEY}" \
-e ENCRYPTION_PRIMARY_KEY="${ENCRYPTION_PRIMARY_KEY}" \
-e ENCRYPTION_KEY_DERIVATION_SALT="${ENCRYPTION_KEY_DERIVATION_SALT}" \
-e DATABASE_URL="postgres://postgres:[email protected]:5432/postgres" \
-e REDIS_URL="redis://host.docker.internal:6379" \
-e KEYGEN_LICENSE_FILE_PATH="${KEYGEN_LICENSE_FILE_PATH}" \
-e KEYGEN_LICENSE_KEY="${KEYGEN_LICENSE_KEY}" \
-e KEYGEN_ACCOUNT_ID="${KEYGEN_ACCOUNT_ID}" \
-e KEYGEN_EDITION="${KEYGEN_EDITION}" \
-e KEYGEN_MODE="${KEYGEN_MODE}" \
-e KEYGEN_HOST="${KEYGEN_HOST}" \
-v /etc/keygen:/etc/keygen \
keygen/api worker

Sidekiq should now be running.

Managing

Keygen can be managed directly via the API (see API reference), or via the console.

Looking for the UI? We don't have a self-hosted one yet. But we're working on open-sourcing a brand new Portal app soon. For now, use the API or console, or create a front-end portal app yourself backed by the Keygen API.

Opening a console

Keygen is a Ruby on Rails app, and as such, supports the rails console command. This allows you to programatically manage your data. You can, for example, set up a product and generate an API token, or create a license for a new customer.

To open a console, run the following command:

docker run --rm -it -e SECRET_KEY_BASE="${SECRET_KEY_BASE}" \
-e ENCRYPTION_DETERMINISTIC_KEY="${ENCRYPTION_DETERMINISTIC_KEY}" \
-e ENCRYPTION_PRIMARY_KEY="${ENCRYPTION_PRIMARY_KEY}" \
-e ENCRYPTION_KEY_DERIVATION_SALT="${ENCRYPTION_KEY_DERIVATION_SALT}" \
-e DATABASE_URL="postgres://postgres:[email protected]:5432/postgres" \
-e REDIS_URL="redis://host.docker.internal:6379" \
-e KEYGEN_LICENSE_FILE_PATH="${KEYGEN_LICENSE_FILE_PATH}" \
-e KEYGEN_LICENSE_KEY="${KEYGEN_LICENSE_KEY}" \
-e KEYGEN_ACCOUNT_ID="${KEYGEN_ACCOUNT_ID}" \
-e KEYGEN_EDITION="${KEYGEN_EDITION}" \
-e KEYGEN_MODE="${KEYGEN_MODE}" \
-e KEYGEN_HOST="${KEYGEN_HOST}" \
-v /etc/keygen:/etc/keygen \
keygen/api console

The console prompt should now be available.

An example of a good first command would be to read your account's public key:

Account.sole.ed25519_public_key
# => "db03db1e0a5e6457da3307a6508f00642fc2549adef32106c609ffff37346813"

Upgrading

Keygen is updated regularly, but it's up to you to apply these updates on your server.

Using Docker, upgrades are safe and easy to apply.

docker pull keygen/api:latest

New versions of Keygen CE and Keygen EE are released roughly every 6 months.

Migrations

Some upgrades to Keygen may require database schema changes. Database migrations can be run inside of the container using the following rails command:

rails db:migrate

As part of your deployment process, we typically recommend running a single release container before rolling out an upgrade, which will run the above command.

To run the release command, run the following:

docker run --rm -e SECRET_KEY_BASE="${SECRET_KEY_BASE}" \
-e ENCRYPTION_DETERMINISTIC_KEY="${ENCRYPTION_DETERMINISTIC_KEY}" \
-e ENCRYPTION_PRIMARY_KEY="${ENCRYPTION_PRIMARY_KEY}" \
-e ENCRYPTION_KEY_DERIVATION_SALT="${ENCRYPTION_KEY_DERIVATION_SALT}" \
-e DATABASE_URL="postgres://postgres:[email protected]:5432/postgres" \
-e REDIS_URL="redis://host.docker.internal:6379" \
-e KEYGEN_LICENSE_FILE_PATH="${KEYGEN_LICENSE_FILE_PATH}" \
-e KEYGEN_LICENSE_KEY="${KEYGEN_LICENSE_KEY}" \
-e KEYGEN_ACCOUNT_ID="${KEYGEN_ACCOUNT_ID}" \
-e KEYGEN_EDITION="${KEYGEN_EDITION}" \
-e KEYGEN_MODE="${KEYGEN_MODE}" \
-e KEYGEN_HOST="${KEYGEN_HOST}" \
-v /etc/keygen:/etc/keygen \
keygen/api release

It is advised to run the above release command BEFORE shutting down old instances and routing to new instances (i.e. rolling over a release). Database migrations are typically backwards compatibile, so running the release command WILL NOT break existing instances running an older version of Keygen, unless otherwise noted in the release notes.

Some upgrades may require other migrations to be run. For example, some upgrades may require a data migration (e.g. seeding new permissions or event types). These migrations will be detailed in the documentation for the new version.

If you ever get tired of managing maintenance and upgrades for your own instances of Keygen, we'd love to have you over at Keygen Cloud. By using Keygen Cloud, you not only support the further development of Keygen, but you also get a great value. We'll handle high availability, backups, security, and maintenance for you.

Monitoring

Server

For server health checks, you can use the following endpoint:

GET https://api.keygen.localhost/v1/health

Using Docker, you can use the --health-cmd flag to monitor the container:

docker run --name web.1 -p 127.0.0.1:3000:3000 \
+ --health-cmd "wget --no-verbose --tries=1 --spider http://localhost:3000/v1/health || exit 1" \
+ --health-interval 5m \
+ --health-timeout 60s \
keygen/api console

This health endpoint supports both HTTP and HTTPS.

Worker

To access the Sidekiq monitoring UI, set the SIDEKIQ_WEB_USER and SIDEKIQ_WEB_PASSWORD environment variables and visit the following endpoint:

https://api.keygen.localhost/-/sidekiq/

You can use this UI to monitor usage and diagnose issues.

Migrating

Keygen facilitates moving data between installs, including Keygen CE/EE and Keygen Cloud, via an export/import feature. This is ideal when you want to move from self-hosting to Keygen Cloud, or when you want to move from Keygen Cloud to Keygen EE.

How can I migrate from self-hosting to Keygen Cloud?

To migrate from a self-hosted install of Keygen to Keygen Cloud, first upgrade your self-hosted Keygen install to the latest version. Then generate an encrypted export of your local account data via the keygen:export Rake task:

rake keygen:export[<secret>] > encrypted.export
# or...
rake keygen:export > unencrypted.export

Finally, reach out to [email protected] with the export file, and the shared secret if your export is encrypted, and we'll get you all set up.

How can I migrate from Keygen Cloud to Keygen EE?

To migrate from Keygen Cloud to a self-hosted Keygen EE install, please reach out to your onboarding contact for an export. Then import the encrypted export of your Keygen Cloud account data via the keygen:import Rake task:

rake keygen:import[<secret>] < encrypted.export
# or...
rake keygen:import < unencrypted.export

Please make sure that your local Keygen EE installation is up to date and that the shared secret is correct. If you have any trouble, reach out to [email protected].

We do not offer account exports for customers moving to Keygen CE.

Telemetry

Keygen takes your privacy very seriously, and we do not use any form of telemetry.

How does Keygen license Keygen EE without telemetry?

Keygen uses cryptographically signed and encrypted License Files to securely handle licensing Keygen EE without an internet connection.

tl;dr Keygen uses Keygen to license Keygen EE. It's turtles Keygens all the way down.

Tuning

How can I tune Keygen?

Keygen is a standard Rails application, using Puma as its web server. This means existing material on scaling a modern Rails application will apply. There's a lot of existing knowledge on the web, so we won't dive into too much detail here because tuning and scaling Keygen will ultimately depend on your instance's unique workload.

The most common ways to tune Keygen is through its various concurrency controls. You can tune RAILS_MAX_THREADS and WEB_CONCURRENCY according to your server specs.

  • The higher the WEB_CONCURRENCY, the more throughput you will have, at the cost of memory.
  • The higher the RAILS_MAX_THREADS, the more throughput you will have, at the cost of CPU.

Aim for WEB_CONCURRENCY to be as high as memory allows. Aim for RAILS_MAX_THREADS to be between 2 and 5, depending on your CPU core count; anything higher and Ruby's GIL will become a bottleneck, and latency will suffer.