kyper.yml Reference

Complete field reference for the configuration file that describes your app to Kyper.

Full example

yaml
name: "my-cool-app"
version: "1.2.0"
category: productivity

docker:
  dockerfile: "./Dockerfile"

processes:
  web: "bundle exec puma -C config/puma.rb"
  worker: "bundle exec sidekiq -C config/sidekiq.yml"

deps:
  - postgres: "15"
    storage_gb: 50
  - redis

storage:
  mounts:
    - path: storage
      storage_gb: 5
    - path: uploads

env:
  - OPENAI_API_KEY

capabilities:
  - email
  - payments

hooks:
  release: "bundle exec rails db:prepare"
  on_deploy: "bundle exec rails cache:warmup"
  on_update: "bundle exec rails cache:warmup"

healthcheck:
  path: "/up"
  initial_delay: 15
  interval: 30
  timeout: 10

pricing:
  one_time: 49.00
  subscription: 12.00

resources:
  min_memory_mb: 512
  min_cpu: 0.5

name required

The unique identifier for your app on Kyper. Used to construct your app's URL (kyper.shop/apps/my-cool-app). Cannot be changed after first push without creating a new app.

Type: string — lowercase letters, digits, and hyphens only; max 100 characters
yaml
name: "invoice-hero"

version required

The current version of your app, following semantic versioning (MAJOR.MINOR.PATCH). Bump this on every push — Kyper enforces that each pushed version is greater than the previous.

Version update behaviour: Patch/minor bumps are auto-deployed to all running consumer instances. Major bumps notify consumers and require opt-in before their deployment upgrades. See Versioning.

yaml
version: "1.0.0"

category required

Used for marketplace filtering. Choose the most relevant category.

Allowed values: developer_tools, productivity, finance, health, media, education, business_operations, data_analytics, gaming

docker required

Configuration for the Docker build. Kyper builds your image from source — you do not need a container registry account.

Important: docker.image is rejected. Kyper always builds from your Dockerfile to ensure security scanning can run.

Key Type Default Description
docker.dockerfile string "./Dockerfile" Path to your Dockerfile, relative to project root

processes required

A map of process type names to the commands that run them. At least one web process is required. The web process must bind to $PORT.

Each process runs independently using the same Docker image with a different command. Only the web process receives external traffic — all other processes run in the background without exposed ports.

yaml
processes:
  web: "bundle exec puma -C config/puma.rb"
  worker: "bundle exec sidekiq -C config/sidekiq.yml"
  scheduler: "bundle exec clockwork config/clock.rb"

Port 3000 is required. Your web process must listen on $PORT (always set to 3000). Add EXPOSE 3000 to your Dockerfile. Apps that bind to port 80 or 443 will fail with "permission denied" at deploy time.

Max 5 processes. Names: [a-z0-9-], max 63 chars. All share the same image, env vars, and deps. Adding/removing processes between versions is handled automatically.

deps

Backing services that Kyper provisions alongside your app. Each dep gets a managed instance with connection details injected as environment variables.

Formats

yaml
# Plain string (platform default version)
deps:
  - postgres
  - redis

# Version-pinned hash
deps:
  - postgres: "15"
  - redis: "6"

# With custom storage
deps:
  - postgres: "15"
    storage_gb: 50    # default: 20 GB
  - redis

App-local persistent storage

Use storage.mounts for framework-local files such as Rails Active Storage local, Django media uploads, Laravel storage/app, or explicit upload directories. Relative paths resolve against the image working directory. Up to 5 mounts are allowed; storage_gb is optional and must be 1-10 GB.

yaml
storage:
  mounts:
    - path: storage
      storage_gb: 5
    - path: /app/uploads

Supported versions

Dep Allowed versions Default Injected variable
postgres 14, 15, 16 16 DATABASE_URL
mysql 8 8 DATABASE_URL
redis 6, 7 7 REDIS_URL
elasticsearch 8 8 ELASTICSEARCH_URL
opensearch 2 2 OPENSEARCH_URL
s3 none (Kyper-managed) latest AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_BUCKET, AWS_ENDPOINT_URL

Storage is billed at $0.10/GB/month and included in the consumer-facing subscription price. Dep containers include readiness healthchecks — your app won't start until all deps are accepting connections.

S3-compatible object storage (s3)

Provisions a fully S3-compatible object storage service. Any AWS SDK (ActiveStorage, Shrine, boto3, etc.) works against it unmodified. The app bucket is auto-created on first write. Data persists across app updates. Version pinning not supported.

pricing at least one required

At least one pricing option must be set. Prices must be ≥ $1.00. Kyper takes a 15% commission; your net payout is 85% minus Stripe processing fees.

Key Type Description
pricing.one_time decimal (USD) One-time purchase price. Consumer downloads the latest approved zip.
pricing.subscription decimal (USD/month) Monthly hosted subscription price. Kyper deploys and manages the app.

env

Declares the environment variable keys that consumers must supply before their deployment can start. Use this for API keys, third-party tokens, and other secrets that Kyper cannot inject automatically.

yaml
env:
  - OPENAI_API_KEY
  - STRIPE_SECRET_KEY
  - SENDGRID_API_KEY

Keys listed here are names only (no values). Consumers enter the values through the deployment configure page. Values are stored encrypted and injected at provision time.

Auto-injected variables

These are always available — do not list them in env:.

Variable Value
SECRET_KEY_BASE Securely generated per-deployment
PORT The port your web process must listen on
KYPER_DEPLOYMENT_ID The UUID of the consumer's deployment
ORIGIN The deployment's public URL (e.g. https://abc123.apps.kyper.shop) — for WebAuthn, OAuth callbacks, CORS
DATABASE_URL Injected if postgres or mysql dep declared
REDIS_URL Injected if redis dep declared
ELASTICSEARCH_URL Injected if elasticsearch dep declared
OPENSEARCH_URL Injected if opensearch dep declared
AWS_ACCESS_KEY_ID Injected if s3 dep declared
AWS_SECRET_ACCESS_KEY Injected if s3 dep declared
AWS_BUCKET "app" — injected if s3 dep declared
AWS_ENDPOINT_URL Injected if s3 dep declared — points to your deployment's object storage service

capabilities

Declares user-facing services your app needs. Kyper manages email, Google Maps, and Mapbox by default, while payments and SMS require the buyer to connect or provide their own service account before deploy.

yaml
capabilities:
  - email
  - maps
  - mapbox
  - payments
  - sms

Available capabilities

Capability Default source Provider
email Kyper-managed Resend
maps Kyper-managed Google Maps
mapbox Kyper-managed Mapbox
payments Buyer-managed setup Stripe
sms Buyer-managed setup Twilio

Legacy integrations: is no longer supported; use capabilities:. Do not list capability-provided keys in env: — they are injected automatically.

Managed email injects both RESEND_API_KEY and a verified sender address KYPER_MAIL_FROM. Read your "from" address from KYPER_MAIL_FROM; do not declare a sender in env:. See Services.

hooks

Commands that Kyper runs at key lifecycle points. release runs as a one-shot Job before your app pods start (after deps are ready). on_deploy and on_update run inside a healthy web pod, after pods are ready.

Key When it runs
hooks.release Before app pods start, after deps (postgres, redis, etc.) are ready. Use for migrations and one-time setup.
hooks.on_deploy After pods are healthy on a new deployment. Use for cache warmup, post-deploy notifications, etc.
hooks.on_update After pods are healthy on a version update. Same execution model as on_deploy; auto-rollback on failure.

Apps with a database dep should always set hooks.release for migrations. Do not use on_deploy for migrations — it runs after pods are healthy, so it can't help an app that crashes on first boot waiting for its schema. Kyper warns at push time if a postgres/mysql dep is declared without hooks.release.

yaml
# Rails
hooks:
  release: "bundle exec rails db:prepare"
  on_deploy: "bundle exec rails cache:warmup"

# Prisma / Node
hooks:
  release: "prisma migrate deploy"

healthcheck

Controls how Kyper polls your app's health endpoint. Checked during provisioning, during updates, and on an ongoing schedule (3 consecutive failures mark the deployment as failed).

Key Type Default Description
healthcheck.path string /up HTTP path to GET. Must start with /.
healthcheck.initial_delay integer 10 Seconds to wait before the first health check. Increase this if your app takes a while to boot (e.g., Rails with Thrust). Must be 0–300.
healthcheck.interval integer 10 Seconds between checks. Must be 10–300.
healthcheck.timeout integer 5 Seconds before a check is considered failed. Must be positive.

resources

Hints that Kyper uses to select the right server size for hosted subscriptions. These are minimums — Kyper may provision a larger size if needed. Consumers can also resize after deployment.

min_memory_mb min_cpu Suggested tier
512 0.5 Hobby ($5/mo)
512 1 Hobby ($5/mo)
1024 1 Pro ($15/mo)
2048 2 Turbo ($25/mo)
4096 2 Turbo ($25/mo)

CPU hints can be fractional. These are hints — consumers pick their tier at subscribe time. See Pricing.

Validation rules

Kyper validates kyper.yml at push time. Run kyper check locally to catch issues before pushing. Common rejection reasons:

Rule Error message
name contains uppercase or special chars name must be lowercase alphanumeric + hyphens
version not semver version must follow semver (MAJOR.MINOR.PATCH)
docker.image present docker.image is not allowed — Kyper builds from source
web process missing processes must include a 'web' key
More than 5 processes processes is limited to 5 entries
Invalid process name process name must contain only lowercase letters, digits, and hyphens
Unknown dep listed unknown dep 'mongodb' — allowed: postgres, mysql, redis, elasticsearch, opensearch, s3
No pricing set at least one of pricing.one_time or pricing.subscription must be present
Unknown category category 'saas' is not a valid category