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.
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.
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 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 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
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.
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/hostscaddy 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 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 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 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.