Перейти до вмісту
На сайт

Конфігурація

Railhook налаштовується змінними середовища у файлі .env поруч із docker-compose.yml. Якщо змінну не задано, діє типове значення, вбудоване в Compose-файл. Після зміни .env виконайте ./railhook up -d: Compose перестворить лише ті сервіси, чиї налаштування змінилися.

Більшість типових значень придатні. Ці підібрано для розробки, і вони стають неправильними, щойно інстанс доступний ззовні.

Змінна Чому це важливо
APP_ENV Зі значенням production API відмовляється запускатися з небезпечною конфігурацією, замість того щоб із нею працювати
WEBHOOK_ENCRYPTION_KEY, WEBHOOK_ENCRYPTION_SALT Шифрують кожен секрет ендпоінта в базі даних. Зробіть їх резервну копію. Ніколи не змінюйте сіль, якщо в базі вже є дані
JWT_SECRET Підписує сесії входу
POSTGRES_PASSWORD, DB_PASSWORD Перша створює користувача бази даних, а з другою підключаються API та воркер. Значення мають збігатися
REDIS_PASSWORD Захищає кеш
APP_BASE_URL URL, який користувачі вводять у браузері. З нього будуються посилання для підтвердження адреси, запрошень і скидання пароля
CORS_ALLOWED_ORIGINS Має містити origin, з якого відкривається панель керування, інакше вхід завершиться помилкою «Invalid CORS request»
TUNNEL_INGRESS_BASE_URL Публічна базова адреса для ingress-адрес джерел і адрес тунелів CLI. Якщо змінну не задано, використовується APP_BASE_URL
EMAIL_ENABLED, EMAIL_FROM, SMTP_* Якщо пошту вимкнено, облікові записи створюються вже підтвердженими, а запрошення надсилати не можна
RAILHOOK_PORT, RAILHOOK_BIND Де слухає єдиний опублікований порт
WEBHOOK_TRUSTED_PROXIES Проксі, заголовку X-Forwarded-For яких Railhook довіряє. Порожнє значення — не довіряти нікому
WEBHOOK_ALLOW_PRIVATE_IPS, WEBHOOK_ALLOWED_HOSTS Не знімайте блокування приватних адрес. Щоб дозволити лише один внутрішній хост, додайте його назву до списку
DB_HOST і COMPOSE_PROFILES Щоб використовувати керовану PostgreSQL, задайте змінні DB_* і приберіть embedded-db із профілів
PLATFORM_ADMIN_TOKEN Відкриває доступ до операторських ендпоінтів. Якщо значення порожнє, вони недоступні
API_REPLICAS 2 лишає API доступним, поки ./railhook upgrade його перезапускає, ціною ще приблизно 600 МБ. З 1 очікуйте близько 30 с відповідей 502 на кожне оновлення

Листи для нових облікових записів

Section titled “Листи для нових облікових записів”

ONBOARDING_EMAILS_ENABLED вмикає два листи для нових облікових записів: привітальний, щойно адресу підтверджено, і одне нагадування через два дні, якщо організація облікового запису досі не надіслала й не отримала жодної події. Кожен лист надсилається не більше одного разу на обліковий запис, відповіді йдуть на EMAIL_SUPPORT_ADDRESS, і нічого не надсилається, якщо не ввімкнено також EMAIL_ENABLED. Облікові записи, створені до оновлення, у якому з’явилося це налаштування, не отримають жодного з цих листів.

На власному інстансі не вмикайте це налаштування. Обидва листи написав від першої особи автор Railhook для Railhook Cloud, а ваші користувачі реєструвалися не в нього.

BLOG_ENABLED вмикає /blog, його дописи та стрічку. Образ містить їх лише тому, що railhook.io працює на тому самому образі, що й ваш інстанс: це власні статті Railhook, а не вашого сайту.

За замовчуванням блог вимкнено, і вмикає його лише railhook.io. Коли він вимкнений, /blog і все під ним відповідають 404, у шапці й підвалі немає посилання на блог, а /sitemap.xml не містить жодного допису. UI-контейнер читає це налаштування під час запуску, тож щоб його змінити, достатньо docker compose up -d ui, без перезбирання. У Kubernetes це налаштування ui.publicBlog.

262

Database location

ЗміннаТиповоОпис
DB_MODEembedded

embedded | external. Read by `make backup-db`, `restore-db` and `shell-db` only; Compose starts the PostgreSQL container when COMPOSE_PROFILES includes embedded-db.

COMPOSE_PROJECT_NAMErailhook

Compose project name. Pinned because the monitoring stack joins this project's network by name, and Compose would otherwise derive it from the clone's directory name.

DOCKER_REGISTRYне заданоприклад: ghcr.io/yourorg/railhook

Registry prefix for the api, worker and ui images; defaults to ghcr.io/vadymkykalo/railhook.

Application environment

ЗміннаТиповоОпис
APP_ENVdevelopment

development | staging | production. Production refuses to start with placeholder secrets.

APP_BASE_URLhttp://localhost:8080

Public origin of the dashboard, used in emails, shared links, canonical tags and the sitemap. Include the port when it is not 80; this one matches RAILHOOK_PORT below.

Database - embedded mode (COMPOSE_PROFILES=embedded-db)

ЗміннаТиповоОпис
POSTGRES_IMAGEpostgres:16-alpine

Image and credentials of the PostgreSQL container.

POSTGRES_DBwebhook_platform

Image and credentials of the PostgreSQL container.

POSTGRES_USERwebhook_user

Image and credentials of the PostgreSQL container.

POSTGRES_PASSWORDwebhook_dev_pass_12345

Image and credentials of the PostgreSQL container.

Database - external mode (no embedded-db profile)

ЗміннаТиповоОпис
DB_HOSTpostgres

Database connection; DB_HOST stays `postgres` (the Compose service) in embedded mode.

DB_PORT5432

Database connection; DB_HOST stays `postgres` (the Compose service) in embedded mode.

DB_NAMEwebhook_platform

Database connection; DB_HOST stays `postgres` (the Compose service) in embedded mode.

DB_USERwebhook_user

Database connection; DB_HOST stays `postgres` (the Compose service) in embedded mode.

DB_PASSWORDwebhook_dev_pass_12345

Database connection; DB_HOST stays `postgres` (the Compose service) in embedded mode.

DB_POOL_MAX_SIZE20

API connection pool (connections; timeout in ms). Named apart from the worker's on purpose: a shared name once gave the worker the API's smaller pool.

DB_POOL_MIN_IDLE10

API connection pool (connections; timeout in ms). Named apart from the worker's on purpose: a shared name once gave the worker the API's smaller pool.

DB_POOL_CONNECTION_TIMEOUT30000

API connection pool (connections; timeout in ms). Named apart from the worker's on purpose: a shared name once gave the worker the API's smaller pool.

WORKER_DB_POOL_MAX_SIZE40

Worker connection pool. Smaller than the worker's thread count because no transaction spans the outbound HTTP call; check hikari_connections_pending under load before changing it.

WORKER_DB_POOL_MIN_IDLE20

Worker connection pool. Smaller than the worker's thread count because no transaction spans the outbound HTTP call; check hikari_connections_pending under load before changing it.

Redis configuration (for distributed rate limiting & concurrency)

ЗміннаТиповоОпис
REDIS_IMAGEredis:7-alpine

Redis image, address, password and memory cap.

REDIS_HOSTredis

Redis image, address, password and memory cap.

REDIS_PORT6379

Redis image, address, password and memory cap.

REDIS_PASSWORDwebhook_redis_pass

Redis image, address, password and memory cap.

REDIS_MAXMEMORY256mb

Redis image, address, password and memory cap.

Security (required - must change for production)

ЗміннаТиповоОпис
WEBHOOK_ENCRYPTION_KEYdev_encryption_key_32_chars_min!

Key that encrypts stored secrets, 32+ characters.

WEBHOOK_ENCRYPTION_SALTdev_encryption_salt_16_chars

PBKDF2 salt for the AES-256 key, 16+ characters, unique per deployment.

WEBHOOK_ENCRYPTION_KEYSпорожньо

Keys for zero-downtime rotation as "version:key,version:key"; empty uses WEBHOOK_ENCRYPTION_KEY as version 1.

WEBHOOK_ENCRYPTION_KEY_ACTIVE_VERSION0

Key version new encryptions use; 0 picks the highest.

JWT_SECRETdev_jwt_secret_key_32_chars_minimum

JWT signing secret, 32+ characters.

PLATFORM_ADMIN_TOKENпорожньо

Token for /api/v1/admin/** (X-Platform-Admin-Token header), including key rotation across all organizations; an organization OWNER does not get this. Empty keeps those endpoints closed.

PLATFORM_ADMIN_EMAILSпорожньо

Comma-separated emails allowed into the platform admin panel (sign-in under 12 hours old). Empty means nobody.

API service

ЗміннаТиповоОпис
API_IMAGE_TAGlatest

API image tag.

Worker service

ЗміннаТиповоОпис
WORKER_IMAGE_TAGlatest

Worker image tag.

Scheduling (api + worker)

ЗміннаТиповоОпис
SCHEDULING_POOL_SIZE8

Threads shared by all scheduled jobs. Keep at 8 or more: with Spring's default of 1, one slow job stalls every other one.

UI service

ЗміннаТиповоОпис
RAILHOOK_PORT8080

Host port and bind address of the dashboard's nginx, the only published port; it also proxies the API. Use RAILHOOK_BIND=127.0.0.1 behind a reverse proxy.

RAILHOOK_BIND0.0.0.0

Host port and bind address of the dashboard's nginx, the only published port; it also proxies the API. Use RAILHOOK_BIND=127.0.0.1 behind a reverse proxy.

RAILHOOK_DOMAINпорожньо

Domain and ACME contact for the built-in Caddy TLS terminator (COMPOSE_PROFILES=tls).

ACME_EMAILпорожньо

Domain and ACME contact for the built-in Caddy TLS terminator (COMPOSE_PROFILES=tls).

UI_IMAGE_TAGlatest

UI image tag.

VITE_API_URLпорожньо

Build-time only: API origin baked into the UI bundle. Leave empty; the UI's nginx proxies the API on the same origin. If set, add it to CORS_ALLOWED_ORIGINS too.

VITE_CSP_EXTRA_CONNECTпорожньо

Build-time only: extra CSP connect-src origins, space-separated.

RAILHOOK_CONTACT_DOMAINпорожньо

Domain for the sales@ and support@ addresses in the contact form and footer, e.g. example.com. Empty offers no addresses. Read by the ui container at start.

Data retention policies

ЗміннаТиповоОпис
DATA_RETENTION_ATTEMPTS_DAYS90

Days to keep failed and successful (2xx) Attempts, and received incoming events.

DATA_RETENTION_SUCCESSFUL_ATTEMPTS_DAYS14

Days to keep failed and successful (2xx) Attempts, and received incoming events.

DATA_RETENTION_INCOMING_EVENTS_DAYS30

Days to keep failed and successful (2xx) Attempts, and received incoming events.

DATA_RETENTION_EVENTS_DAYS90

Days to keep Events and, by cascade, their Deliveries; -1 keeps them forever. The only bound on those tables when billing is off. Matches DATA_RETENTION_ATTEMPTS_DAYS on purpose.

DATA_RETENTION_DLQ_DAYS14

Days a Delivery or Forward stays in the DLQ (Failed Messages) before it is deleted; -1 keeps it until its Event expires.

DATA_RETENTION_MAX_ATTEMPTS_PER_DELIVERY10

Most recent Attempts kept per Delivery.

DATA_RETENTION_BATCH_SIZE1000

Rows per cleanup batch.

DATA_RETENTION_CRON0 0 2 * * *

Cleanup schedule (cron, daily at 2 AM).

DATA_RETENTION_LIMIT_CRON0 */30 * * * *

Limit enforcement schedule (cron, every 30 minutes).

DATA_RETENTION_BURST_CLEANUP_CRON0 0 */4 * * *

Extra cleanup for daytime error spikes (cron, every 4 hours).

DATA_RETENTION_TABLE_METRICS_INTERVAL_MS900000

Table size gauge refresh interval (ms).

Partition maintenance

ЗміннаТиповоОпис
PARTITION_MAINTENANCE_ENABLEDtrue

Creates delivery_attempts and tunnel_request_log partitions ahead of need and drops those past retention; lookahead in months and weeks, schedule as cron.

PARTITION_MAINTENANCE_DELIVERY_ATTEMPTS_LOOKAHEAD_MONTHS3

Creates delivery_attempts and tunnel_request_log partitions ahead of need and drops those past retention; lookahead in months and weeks, schedule as cron.

PARTITION_MAINTENANCE_TUNNEL_LOG_LOOKAHEAD_WEEKS3

Creates delivery_attempts and tunnel_request_log partitions ahead of need and drops those past retention; lookahead in months and weeks, schedule as cron.

PARTITION_MAINTENANCE_CRON0 45 1 * * *

Creates delivery_attempts and tunnel_request_log partitions ahead of need and drops those past retention; lookahead in months and weeks, schedule as cron.

Rate limiting

ЗміннаТиповоОпис
GLOBAL_RATE_LIMIT_PER_SECOND5000

Platform-wide request limit per instance (requests/s).

ORG_RATE_LIMIT_ENABLEDfalse

Per-organization request limit (requests/s), for shared installs where one tenant must not spend everyone's budget. Costs a Redis round trip per request, so leave it off when self-hosting.

ORG_RATE_LIMIT_PER_SECOND200

Per-organization request limit (requests/s), for shared installs where one tenant must not spend everyone's budget. Costs a Redis round trip per request, so leave it off when self-hosting.

GLOBAL_RATE_LIMIT_ENABLEDtrue

Per-organization request limit (requests/s), for shared installs where one tenant must not spend everyone's budget. Costs a Redis round trip per request, so leave it off when self-hosting.

EVENT_INGESTION_RATE_LIMIT_PER_SECOND100

Events per second per project (token bucket).

AUTH_RATE_LIMIT_LOGIN_PER_MINUTE10

Sign-in and registration attempts per minute, per IP and per email.

AUTH_RATE_LIMIT_REGISTER_PER_MINUTE5

Sign-in and registration attempts per minute, per IP and per email.

AUTH_RATE_LIMIT_REFRESH_PER_TOKEN_PER_MINUTE30

Session refreshes per minute, per refresh token and per IP. Separate from sign-in, whose budget page loads would otherwise exhaust.

AUTH_RATE_LIMIT_REFRESH_PER_IP_PER_MINUTE600

Session refreshes per minute, per refresh token and per IP. Separate from sign-in, whose budget page loads would otherwise exhaust.

Password authentication

ЗміннаТиповоОпис
AUTH_BCRYPT_STRENGTH12

BCrypt cost, 4-31; each step doubles the work. Changing it never invalidates stored hashes.

AUTH_LOCKOUT_ENABLEDtrue

Lock an account after consecutive failed sign-ins. Held in Postgres, not Redis, so it does not weaken when Redis is down. Locks expire on their own and a password reset clears them.

AUTH_LOCKOUT_THRESHOLD5

Consecutive failures before the account locks.

AUTH_LOCKOUT_INITIAL_SECONDS60

First lockout, in seconds. Doubles with each further failure.

AUTH_LOCKOUT_MAX_SECONDS900

Cap on the doubling, in seconds; longer only helps someone locking a stranger out.

AUTH_LOCKOUT_FAILURE_WINDOW_MINUTES60

Minutes after which a failure no longer counts toward the lockout.

AUTH_SESSION_CLEANUP_INTERVAL_MS3600000

Interval for purging expired sessions (ms).

Webhook delivery

ЗміннаТиповоОпис
WEBHOOK_MAX_PAYLOAD_SIZE_BYTES262144

Largest event payload accepted (bytes).

WEBHOOK_MAX_FANOUT_PER_EVENT100

Most Deliveries one Event may fan out to.

WEBHOOK_PAYLOAD_COMPRESSION_THRESHOLD_BYTES1024

Payloads larger than this are stored gzip-compressed (bytes).

ORGANIZATION_SUSPENSION_CACHE_TTL_SECONDS60

Seconds an organization's suspension state is cached on each node; other nodes see a change within this window.

WEBHOOK_PROJECT_RATE_LIMIT_PER_SECOND50

Deliveries per second one project may take from the shared worker pool. Not the plan's ingest limit: size it from WEBHOOK_OUTGOING_POOL_SIZE.

WEBHOOK_ENDPOINT_VERIFICATION_REQUIREDfalse

Require new endpoints to prove ownership before they receive deliveries (true | false).

WEBHOOK_INGRESS_REPLAY_WINDOW_MINUTES5

Minutes a received signature is remembered to reject replays. For a source signed with a plain body HMAC this is the only replay bound; raise it for such sources.

WEBHOOK_ALLOW_PRIVATE_IPSfalse

Allow delivery to private IPs (SSRF risk, e.g. cloud metadata). Development only; refused in production.

WEBHOOK_MAX_CONCURRENT_PER_ENDPOINT5

Concurrent deliveries per endpoint.

WEBHOOK_MAX_CONCURRENT_PER_TENANT20

Concurrent in-flight attempts per organization across all its endpoints, so one tenant's slow receivers cannot occupy the whole WEBHOOK_OUTGOING_POOL_SIZE.

WEBHOOK_CONCURRENCY_PERMIT_LEASE_SECONDS90

Seconds a concurrency permit lives before Redis reclaims it; must exceed the 60s maximum delivery timeout plus setup time.

WEBHOOK_OUTGOING_POOL_SIZE50

Threads for outgoing deliveries.

WEBHOOK_INCOMING_POOL_SIZE20

Threads for incoming forwards.

WEBHOOK_CLAIM_ENABLEDtrue

Worker claims due Deliveries and Forwards from Postgres (true | false).

WEBHOOK_CLAIM_IDLE_POLL_MS200

How long a poll that found nothing sleeps (ms); a full batch polls again at once.

WEBHOOK_CLAIM_TIMEOUT_SECONDS300

Seconds after which a claimed row whose worker has not finished is claimed again; keep above 60s plus transformation time.

WEBHOOK_CLAIM_MAX_TARGETS500

Endpoints or destinations one poll visits.

WEBHOOK_ASYNC_SHUTDOWN_TIMEOUT_SECONDS60

Seconds to wait for in-flight deliveries on shutdown.

CLIENT_ERROR_REPORTING_ENABLEDtrue

Dashboard error reporting.

Dashboard errors are posted back and written to this installation's own logs, never to a third party; reports per user per minute.

CLIENT_ERROR_REPORTS_PER_USER_PER_MINUTE20

Dashboard error reporting.

Dashboard errors are posted back and written to this installation's own logs, never to a third party; reports per user per minute.

WEBHOOK_MAX_RESPONSE_BODY_BYTES1048576

Receiver response body buffered per attempt (bytes); past it the status code alone decides. Only the first 10 KiB is stored.

TRANSFORM_SCRIPT_TIMEOUT_MS2000

JavaScript transformations.

Wall-clock limit per script run (ms); a runaway script holds one delivery slot this long. Exceeding any of these limits fails the Delivery, which is retried.

TRANSFORM_SCRIPT_MAX_MEMORY_MB128

Allocation limit per run (MB), counted as total allocation rather than live heap.

TRANSFORM_SCRIPT_MAX_OUTPUT_BYTES1048576

Largest body a script may return (bytes).

TRANSFORM_SCRIPT_MAX_CONSOLE_LINES100

console.* lines kept per run for the Transform Studio.

TRANSFORM_SCRIPT_MAX_CHARS65536

Largest script the engine compiles (characters).

WEBHOOK_POOL_MAX_CONNECTIONS200

Outgoing HTTP connection pool shared by deliveries and forwards (connections, seconds).

WEBHOOK_POOL_PENDING_ACQUIRE_TIMEOUT_SECONDS10

Outgoing HTTP connection pool shared by deliveries and forwards (connections, seconds).

WEBHOOK_POOL_MAX_IDLE_TIME_SECONDS60

Outgoing HTTP connection pool shared by deliveries and forwards (connections, seconds).

WEBHOOK_ALLOWED_HOSTSпорожньо

Comma-separated host names exempt from the private-IP check, matched as written in the endpoint URL. Empty exempts nothing; other rules still apply.

WEBHOOK_TRUSTED_PROXIESпорожньо

Comma-separated proxy IPs/CIDRs whose X-Forwarded-For sets the client IP (rate limits, audit, source IP checks); behind a CDN include its ranges. Empty trusts nothing.

Incoming webhooks

ЗміннаТиповоОпис
WEBHOOK_INGRESS_BASE_URLhttp://localhost:8080

Base URL for ingress URLs shown in the dashboard.

WEBHOOK_INCOMING_MAX_PAYLOAD_SIZE_BYTES524288

Largest incoming payload accepted (bytes).

WEBHOOK_INCOMING_RATE_LIMIT_PER_SECOND100

Default ingress limit for a source that sets none (requests/s); 0 disables the default.

DLQ_MONITORING_INTERVAL_MS60000

DLQ monitoring interval (ms).

Ordering (FIFO delivery per endpoint)

ЗміннаТиповоОпис
ORDERING_GAP_TIMEOUT_SECONDS60

Seconds an ordered Delivery waits on a gap before going out of order, and only once nothing in the gap is being or about to be attempted.

ORDERING_BUFFER_RESCHEDULE_DELAY_SECONDS5

Fallback poll for a Delivery parked behind a missing sequence (seconds).

ORDERING_DELIVERED_SEQ_TTL_HOURS24

TTL of delivered-sequence tracking in Redis (hours).

ORDERING_BUFFER_TTL_MINUTES10

TTL of the ordering buffer in Redis (minutes).

ORDERING_BUFFER_GAUGE_RESYNC_MS30000

How often the ordering buffer size gauge resyncs from Redis (ms).

ORDERING_STRANDED_SEQUENCE_AFTER_SECONDS120

Backfills ordered Deliveries left without a sequence number by a process that died after commit; only rows older than this many seconds, per batch. Below a few seconds it races ingest.

ORDERING_STRANDED_SEQUENCE_BATCH_SIZE500

Backfills ordered Deliveries left without a sequence number by a process that died after commit; only rows older than this many seconds, per batch. Below a few seconds it races ingest.

ORDERING_SEQUENCE_RECONCILIATION_LOOKBACK_HOURS48

How far back sequence reconciliation looks for active ordered endpoints (hours).

ORDERING_SEQUENCE_RECONCILIATION_INTERVAL_MS900000

Sequence reconciliation interval (ms).

Event time machine (replay)

ЗміннаТиповоОпис
REPLAY_BATCH_SIZE200

Events read per replay batch.

REPLAY_BATCH_DELAY_MS50

Pause between replay batches (ms).

REPLAY_MAX_EVENTS_PER_SESSION500000

Most events one replay session may cover.

WEBHOOK_RETRY_AFTER_MAX_SECONDS21600

Longest a receiver's Retry-After (on 429 and 503) may delay the next attempt (seconds); it only ever delays. 0 ignores the header. Kept within DELIVERY_ESCALATION_HARD_CAP_HOURS.

Auto-disable a persistently failing target

ЗміннаТиповоОпис
ENDPOINT_AUTO_DISABLE_ENABLEDtrue

Turn off an endpoint or destination that has only failed for a whole window, and notify its owners. Set it the same on api and worker.

ENDPOINT_AUTO_DISABLE_AFTER_HOURS72

Hours of failures without a success before disabling, at least 1. Shorter than DELIVERY_ESCALATION_HARD_CAP_HOURS on purpose.

ENDPOINT_AUTO_DISABLE_MIN_FAILURES10

Failed attempts that window must also contain, so an idle endpoint is not disabled.

ENDPOINT_AUTO_DISABLE_INTERVAL_MS300000

Sweep interval (ms) and targets checked per sweep.

ENDPOINT_AUTO_DISABLE_BATCH_SIZE200

Sweep interval (ms) and targets checked per sweep.

Circuit breaker (Redis-backed, shared across worker pods)

ЗміннаТиповоОпис
CIRCUIT_BREAKER_FAILURE_RATE_THRESHOLD50

Failure rate that opens the circuit (percent, 0-100).

CIRCUIT_BREAKER_MINIMUM_CALLS5

Calls needed before the failure rate is evaluated.

CIRCUIT_BREAKER_WAIT_DURATION_SECONDS30

Seconds the circuit stays open before probing.

CIRCUIT_BREAKER_WINDOW_TTL_SECONDS120

Sliding window of the failure counters (seconds).

CIRCUIT_BREAKER_SLOW_CALL_THRESHOLD_MS10000

A call slower than this counts as slow, even with a 2xx (ms).

CIRCUIT_BREAKER_SLOW_CALL_RATE_THRESHOLD80

Slow call rate that opens the circuit (percent, 0-100).

Stale delivery escalation (hard-cap auto-DLQ)

ЗміннаТиповоОпис
DELIVERY_ESCALATION_HARD_CAP_HOURS96

Hours after which a PENDING Delivery goes to the DLQ. Must cover the outgoing retry ladder's worst case (~83h), or startup fails.

DELIVERY_ESCALATION_BATCH_SIZE100

Deliveries per escalation batch.

Stale forward escalation (hard-cap auto-DLQ, Incoming)

ЗміннаТиповоОпис
FORWARD_ESCALATION_HARD_CAP_HOURS24

Hours from receipt after which an outstanding Forward goes to the DLQ; batch size and interval (ms). Must cover the incoming retry ladder's worst case (~11h), or startup fails.

FORWARD_ESCALATION_BATCH_SIZE100

Hours from receipt after which an outstanding Forward goes to the DLQ; batch size and interval (ms). Must cover the incoming retry ladder's worst case (~11h), or startup fails.

FORWARD_ESCALATION_INTERVAL_MS300000

Hours from receipt after which an outstanding Forward goes to the DLQ; batch size and interval (ms). Must cover the incoming retry ladder's worst case (~11h), or startup fails.

DELIVERY_ESCALATION_INTERVAL_MS300000

Stale delivery check interval (ms).

Queue depth metrics

ЗміннаТиповоОпис
QUEUE_DEPTH_METRICS_INTERVAL_MS900000

Queue depth gauge refresh interval (ms).

QUEUE_DEPTH_METRICS_RETENTION_DAYS30

Only rows created within this many days are counted.

Test endpoints (Request Bin)

ЗміннаТиповоОпис
TEST_ENDPOINT_BASE_URLне задано

Public origin of test endpoint URLs (…/hook/<slug>); defaults to APP_BASE_URL. Never an internal name.

TEST_ENDPOINT_MAX_PER_PROJECT10

Test endpoints per project.

TEST_ENDPOINT_MAX_TTL_HOURS72

Longest test endpoint lifetime (hours).

TEST_ENDPOINT_CLEANUP_INTERVAL_MS3600000

Expired test endpoint cleanup interval (ms).

Rules engine

ЗміннаТиповоОпис
RULES_CACHE_REFRESH_MS30000

Compiled rules cache refresh (ms).

RULES_EXECUTION_LOG_RETENTION_DAYS7

Rule execution log retention (days).

Transformations

ЗміннаТиповоОпис
TRANSFORMATION_HISTORY_LIMIT50

Published versions kept per transformation (up to ~64 KB each); the one in use is never dropped.

Workflow engine

ЗміннаТиповоОпис
WORKFLOW_POOL_CORE_SIZE4

Workflow executor threads and queue capacity.

WORKFLOW_POOL_MAX_SIZE8

Workflow executor threads and queue capacity.

WORKFLOW_POOL_QUEUE_CAPACITY50

Workflow executor threads and queue capacity.

WORKFLOW_MAX_DURATION_SECONDS600

Longest a workflow run may take (seconds).

WORKFLOW_MAX_RECURSION_DEPTH3

Deepest workflow → CreateEvent → workflow chain.

WORKFLOW_STUCK_THRESHOLD_MINUTES15

Stuck execution recovery: threshold (minutes) and check interval (ms).

WORKFLOW_RECOVERY_INTERVAL_MS120000

Stuck execution recovery: threshold (minutes) and check interval (ms).

WORKFLOW_RESUME_INTERVAL_MS5000

How often suspended delay nodes are checked for being due (ms); the resolution of a delay.

WORKFLOW_RESUME_BATCH_SIZE50

Due executions resumed per tick; the rest wait for the next tick.

WORKFLOW_NODE_TIMEOUT_DEFAULT_SECONDS30

Per-node timeouts (seconds) and the timeout thread pool size.

WORKFLOW_NODE_TIMEOUT_HTTP_SECONDS60

Per-node timeouts (seconds) and the timeout thread pool size.

WORKFLOW_NODE_TIMEOUT_SLACK_SECONDS60

Per-node timeouts (seconds) and the timeout thread pool size.

WORKFLOW_NODE_TIMEOUT_CREATE_EVENT_SECONDS30

Per-node timeouts (seconds) and the timeout thread pool size.

WORKFLOW_NODE_TIMEOUT_POOL_SIZE16

Per-node timeouts (seconds) and the timeout thread pool size.

WORKFLOW_SHUTDOWN_AWAIT_SECONDS30

Seconds to wait for in-flight workflows on shutdown.

WORKFLOW_TRIGGER_OUTBOX_POLL_INTERVAL_MS2000

Workflow trigger outbox: poll interval (ms), batch size, attempts per trigger.

WORKFLOW_TRIGGER_OUTBOX_BATCH_SIZE50

Workflow trigger outbox: poll interval (ms), batch size, attempts per trigger.

WORKFLOW_TRIGGER_OUTBOX_MAX_ATTEMPTS3

Workflow trigger outbox: poll interval (ms), batch size, attempts per trigger.

WORKFLOW_TRIGGER_OUTBOX_MAX_PER_PROJECT5

Triggers claimed per project per batch.

WORKFLOW_TRIGGER_OUTBOX_MAX_CONCURRENT_PER_PROJECT3

Concurrent workflow executions per project.

WORKFLOW_TRIGGER_OUTBOX_STALLED_AFTER_MINUTES15

Minutes after which a trigger abandoned in PROCESSING is requeued, and the sweep interval (ms). Keep it above your longest workflow, or a live one runs twice.

WORKFLOW_TRIGGER_OUTBOX_STALLED_SWEEP_MS300000

Minutes after which a trigger abandoned in PROCESSING is requeued, and the sweep interval (ms). Keep it above your longest workflow, or a live one runs twice.

Device authorization

ЗміннаТиповоОпис
DEVICE_AUTH_CLEANUP_INTERVAL_MS300000

Expired device code cleanup interval (ms).

Email verification

ЗміннаТиповоОпис
EMAIL_ENABLEDfalse

Send real email (false logs links to the console). Also enforces email verification: while off, new accounts are marked verified. Turn on wherever registration is open to strangers.

EMAIL_FROMnoreply@example.com

Sender address; use a domain you own, or mail fails SPF/DKIM and lands in spam.

EMAIL_SUPPORT_ADDRESSпорожньо

Contact address in the notice about an unexpected email change; empty says to contact the administrator.

ONBOARDING_EMAILS_ENABLEDfalse

Welcome and follow-up mail to new accounts, written for Railhook Cloud; keep off when self-hosting.

CONTACT_DAILY_LIMIT30

Contact form messages sent per UTC day, so the form cannot spend the mail quota verification needs.

SMTP_HOSTlocalhost

SMTP relay, used when EMAIL_ENABLED=true.

SMTP_PORT1025

SMTP relay, used when EMAIL_ENABLED=true.

SMTP_USERNAMEпорожньо

SMTP relay, used when EMAIL_ENABLED=true.

SMTP_PASSWORDпорожньо

SMTP relay, used when EMAIL_ENABLED=true.

SMTP_AUTHfalse

SMTP relay, used when EMAIL_ENABLED=true.

SMTP_STARTTLSfalse

SMTP relay, used when EMAIL_ENABLED=true.

Alert notifications

ЗміннаТиповоОпис
ALERTS_NOTIFICATIONS_ENABLEDfalse

Send alert notifications to Slack, webhooks and email (false logs them instead).

ALERTS_EVALUATION_CRON0 * * * * *

Alert rule evaluation schedule (cron); how late an alert can be, not its window.

Entitlements (limits when billing is off)

ЗміннаТиповоОпис
ENTITLEMENT_DEFAULT_RATE_LIMIT100

Rate limit (events/s) and fan-out applied when BILLING_ENABLED=false, instead of no limit.

ENTITLEMENT_DEFAULT_MAX_FANOUT50

Rate limit (events/s) and fan-out applied when BILLING_ENABLED=false, instead of no limit.

Captcha (registration)

ЗміннаТиповоОпис
CAPTCHA_SECRET_KEYне задано

Registration CAPTCHA secret and verify URL (Turnstile by default; hCaptcha works too). Empty means no challenge; required with APP_ENV=production and BILLING_ENABLED=true. Fails closed.

CAPTCHA_VERIFY_URLне заданоприклад: https://challenges.cloudflare.com/turnstile/v0/siteverify

Registration CAPTCHA secret and verify URL (Turnstile by default; hCaptcha works too). Empty means no challenge; required with APP_ENV=production and BILLING_ENABLED=true. Fails closed.

CAPTCHA_SITE_KEYне задано

Site key and script for the registration page, read by the ui container at start. Set together with CAPTCHA_SECRET_KEY, or every registration is refused.

CAPTCHA_SCRIPT_URLне заданоприклад: https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit

Site key and script for the registration page, read by the ui container at start. Set together with CAPTCHA_SECRET_KEY, or every registration is refused.

Public webhook tester

ЗміннаТиповоОпис
PUBLIC_TESTER_ENABLEDне заданоприклад: false

The anonymous /tester page; off by default. Live URLs per address and overall when on.

PUBLIC_TESTER_PER_ADDRESSне заданоприклад: 3

The anonymous /tester page; off by default. Live URLs per address and overall when on.

PUBLIC_TESTER_MAX_ACTIVEне заданоприклад: 5000

The anonymous /tester page; off by default. Live URLs per address and overall when on.

Live demo

ЗміннаТиповоОпис
DEMO_ENABLEDне заданоприклад: false

Anonymous read-only demo organization; off by default, and turning it off deletes it. Session length and data refresh in minutes. Set on both api and ui.

DEMO_SESSION_TTL_MINUTESне заданоприклад: 30

Anonymous read-only demo organization; off by default, and turning it off deletes it. Session length and data refresh in minutes. Set on both api and ui.

DEMO_REFRESH_INTERVAL_MINUTESне заданоприклад: 60

Anonymous read-only demo organization; off by default, and turning it off deletes it. Session length and data refresh in minutes. Set on both api and ui.

DEMO_SCRIPT_RUNS_PER_SESSION_PER_MINUTEне заданоприклад: 20

JavaScript transformation runs per minute for a demo session and per IP. Runs hold request threads, so at a 2000 ms timeout 60 per IP bounds one address to two threads.

DEMO_SCRIPT_RUNS_PER_IP_PER_MINUTEне заданоприклад: 60

JavaScript transformation runs per minute for a demo session and per IP. Runs hold request threads, so at a 2000 ms timeout 60 per IP bounds one address to two threads.

Blog

ЗміннаТиповоОпис
BLOG_ENABLEDне заданоприклад: false

Serve Railhook's own blog at /blog; off by default. Read by the ui container.

Web analytics

ЗміннаТиповоОпис
WEB_ANALYTICS_TOKENне задано

Cloudflare Web Analytics token; empty loads no analytics. Read by the ui container at start.

STATUS_PAGE_URLне задано

Status page URL linked from the footer; empty shows no link. Read by the ui container at start.

Sign in with google

ЗміннаТиповоОпис
GOOGLE_OAUTH_CLIENT_IDне задано

"Continue with Google", off unless both are set. Redirect URI: <APP_BASE_URL>/api/v1/auth/oauth/google/callback

GOOGLE_OAUTH_CLIENT_SECRETне задано

"Continue with Google", off unless both are set. Redirect URI: <APP_BASE_URL>/api/v1/auth/oauth/google/callback

Billing / plans

ЗміннаТиповоОпис
BILLING_ENABLEDfalse

Enforce plan quotas (false = self-hosted, unlimited). In production it also requires EMAIL_ENABLED=true and CAPTCHA_SECRET_KEY.

BILLING_DEFAULT_PROVIDERnoop

noop | stripe | wayforpay; noop with billing on runs the free plan only.

STRIPE_SECRET_KEYне заданоприклад: sk_test_...

Stripe credentials; STRIPE_PRICE_MAP is plan_interval=price_id (interval _monthly or _yearly).

STRIPE_WEBHOOK_SECRETне заданоприклад: whsec_...

Stripe credentials; STRIPE_PRICE_MAP is plan_interval=price_id (interval _monthly or _yearly).

STRIPE_PRICE_MAPне заданоприклад: starter_monthly=price_xxx,starter_yearly=price_xxy,pro_monthly=price_yyy,pro_yearly=price_yyz

Stripe credentials; STRIPE_PRICE_MAP is plan_interval=price_id (interval _monthly or _yearly).

BILLING_RECONCILIATION_CRON0 0 */6 * * *

Schedule for syncing billing state from Stripe (cron).

WAYFORPAY_MERCHANT_ACCOUNTне заданоприклад: your_merchant_account

WayForPay credentials; WAYFORPAY_PLAN_PRICES is plan_interval=amount_in_cents.

WAYFORPAY_MERCHANT_SECRETне заданоприклад: your_merchant_secret_key

WayForPay credentials; WAYFORPAY_PLAN_PRICES is plan_interval=amount_in_cents.

WAYFORPAY_MERCHANT_DOMAINне заданоприклад: example.com

WayForPay credentials; WAYFORPAY_PLAN_PRICES is plan_interval=amount_in_cents.

WAYFORPAY_SERVICE_URLне заданоприклад: https://example.com/api/v1/billing/webhook/wayforpay

WayForPay credentials; WAYFORPAY_PLAN_PRICES is plan_interval=amount_in_cents.

WAYFORPAY_PLAN_PRICESне заданоприклад: starter_monthly=2900,starter_yearly=29000,pro_monthly=9900,pro_yearly=99000

WayForPay credentials; WAYFORPAY_PLAN_PRICES is plan_interval=amount_in_cents.

PRERENDER_LOCALEen

Build-time only: locale the public pages are prerendered in.

Tunnel (CLI local webhook tunnels)

ЗміннаТиповоОпис
TUNNEL_INGRESS_BASE_URLhttp://localhost:8080

Public base URL of incoming-source and tunnel URLs; defaults to APP_BASE_URL.

TUNNEL_HEARTBEAT_TIMEOUT_SECONDS120

Seconds without a heartbeat before a tunnel session is stale.

TUNNEL_CLEANUP_INTERVAL_MS60000

Stale session cleanup interval (ms).

TUNNEL_REQUEST_LOG_RETENTION_DAYS7

Tunnel request log retention (days), enforced by dropping weekly partitions.

Mcp server (ai agents)

ЗміннаТиповоОпис
MCP_ENABLEDtrue

Serve the MCP server at /mcp, authenticated with a project API key.

MCP_OAUTH_ENABLEDtrue

OAuth sign-in for MCP connectors (claude.ai, ChatGPT); needs APP_BASE_URL to be the public origin. false accepts API keys only.

CORS configuration

ЗміннаТиповоОпис
CORS_ALLOWED_ORIGINShttp://localhost:8080,http://localhost:5173

Comma-separated allowed origins. Must include the RAILHOOK_PORT origin: browsers send Origin on same-origin POSTs too.

Observability

ЗміннаТиповоОпис
LOG_LEVELINFO

TRACE | DEBUG | INFO | WARN | ERROR

SWAGGER_ENABLEDfalse

Serve Swagger UI; keep false in production.

JVM tuning

ЗміннаТиповоОпис
API_JAVA_OPTSне заданоприклад: -Xms256m -Xmx384m

Extra JVM flags, appended to the image's container tuning; an explicit -Xmx still wins.

WORKER_JAVA_OPTSне заданоприклад: -Xms384m -Xmx512m

Extra JVM flags, appended to the image's container tuning; an explicit -Xmx still wins.

METRICS_ENABLEDtrue

Expose Prometheus metrics.

Resource limits (Docker deploy.resources)

ЗміннаТиповоОпис
POSTGRES_MEMORY_LIMITне заданоприклад: 1G

Container memory limits.

REDIS_MEMORY_LIMITне заданоприклад: 512m

Container memory limits.

API_MEMORY_LIMITне заданоприклад: 768m

Container memory limits.

WORKER_MEMORY_LIMITне заданоприклад: 768m

Container memory limits.

API_REPLICAS1

API containers. Two keep the API answering during `railhook upgrade` (about 600 MB more); one costs ~30s of 502 per upgrade while the JVM starts.

UI_MEMORY_LIMITне заданоприклад: 128m

UI container memory limit.

Monitoring stack (optional)

ЗміннаТиповоОпис
GRAFANA_ADMIN_PASSWORDпорожньо

Grafana admin password, 16+ characters; the stack refuses to start without it. Re-applied on every start.

GRAFANA_ADMIN_USERadmin

Grafana admin login.

GRAFANA_PORT3001

Loopback port Grafana is published on.

MONITORING_DOMAINпорожньо

Host name to serve Grafana on through the built-in Caddy; empty keeps it loopback-only. Put an identity-aware proxy in front.

MONITORING_TLS_CERTпорожньо

Certificate and key Caddy serves for MONITORING_DOMAIN instead of obtaining one, as paths inside the Caddy container. Both or neither.

MONITORING_TLS_KEYпорожньо

Certificate and key Caddy serves for MONITORING_DOMAIN instead of obtaining one, as paths inside the Caddy container. Both or neither.

MONITORING_PROBE_URLSпорожньо

Comma-separated URLs for the uptime probes; empty probes RAILHOOK_DOMAIN when set.

RAILHOOK_NETWORKпорожньо

Platform Docker network to join; empty finds it by its Compose label.

MONITORING_NODENAMEпорожньо

Server name shown on the Host dashboard; empty uses the hostname.

MONITORING_BACKUP_DIR../backups

Backup directory, relative to monitoring/, read by the BackupStale alert.

PROMETHEUS_RETENTION15d

Prometheus retention time and disk budget.

PROMETHEUS_RETENTION_SIZE4GB

Prometheus retention time and disk budget.

Alerting (optional)

ЗміннаТиповоОпис
ALERTMANAGER_SLACK_WEBHOOK_URLпорожньо

Alertmanager receivers. With none set, alerts show only in Grafana.

Slack incoming webhook URL and channel.

ALERTMANAGER_SLACK_CHANNEL#railhook-alerts

Alertmanager receivers. With none set, alerts show only in Grafana.

Slack incoming webhook URL and channel.

ALERTMANAGER_WEBHOOK_URLпорожньо

Generic webhook receiver URL (PagerDuty Events v2, Opsgenie, …).

ALERTMANAGER_EMAIL_TOпорожньо

Alert email recipient; sender and relay default to EMAIL_FROM and SMTP_*.

ALERTMANAGER_EMAIL_FROMпорожньо

Alert email recipient; sender and relay default to EMAIL_FROM and SMTP_*.

ALERTMANAGER_SMTP_HOSTпорожньо

Alert email recipient; sender and relay default to EMAIL_FROM and SMTP_*.

ALERTMANAGER_SMTP_PORTпорожньо

Alert email recipient; sender and relay default to EMAIL_FROM and SMTP_*.

ALERTMANAGER_SMTP_USERNAMEпорожньо

Alert email recipient; sender and relay default to EMAIL_FROM and SMTP_*.

ALERTMANAGER_SMTP_PASSWORDпорожньо

Alert email recipient; sender and relay default to EMAIL_FROM and SMTP_*.

ALERTMANAGER_SMTP_REQUIRE_TLSпорожньо

true | false; empty requires TLS except for localhost, mailpit and mailhog.

ALERTMANAGER_TELEGRAM_BOT_TOKENпорожньо

Telegram bot token and chat id (negative for groups); both, or Telegram stays off.

ALERTMANAGER_TELEGRAM_CHAT_IDпорожньо

Telegram bot token and chat id (negative for groups); both, or Telegram stays off.

ALERTMANAGER_HEARTBEAT_URLпорожньо

Heartbeat URL pinged every minute by the Watchdog alert, so an outside service notices this host going down.

ALERTMANAGER_EXTERNAL_URLhttp://localhost:9093

Alertmanager's address in Slack and webhook payloads.

Log aggregation (Loki)

ЗміннаТиповоОпис
LOKI_RETENTION_PERIOD168h

How long Loki keeps log lines (Go duration, e.g. 168h).

Backup configuration

ЗміннаТиповоОпис
BACKUP_DIR./backups

Backup directory and retention (days) for `make backup-db` and the db-backup service.

BACKUP_RETENTION_DAYS30

Backup directory and retention (days) for `make backup-db` and the db-backup service.

DB_BACKUP_INTERVAL_SECONDS86400

Seconds between scheduled backups by the db-backup service.