Конфігурація
Railhook налаштовується змінними середовища у файлі .env поруч із docker-compose.yml. Якщо змінну не задано, діє типове значення, вбудоване в Compose-файл. Після зміни .env виконайте ./railhook up -d: Compose перестворить лише ті сервіси, чиї налаштування змінилися.
Що треба визначити
Section titled “Що треба визначити”Більшість типових значень придатні. Ці підібрано для розробки, і вони стають неправильними, щойно інстанс доступний ззовні.
| Змінна | Чому це важливо |
|---|---|
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.
Усі змінні
Section titled “Усі змінні”Database location
| Змінна | Типово | Опис |
|---|---|---|
DB_MODE | embedded | 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_NAME | railhook | 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_ENV | development | development | staging | production. Production refuses to start with placeholder secrets. |
APP_BASE_URL | http://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_IMAGE | postgres:16-alpine | Image and credentials of the PostgreSQL container. |
POSTGRES_DB | webhook_platform | Image and credentials of the PostgreSQL container. |
POSTGRES_USER | webhook_user | Image and credentials of the PostgreSQL container. |
POSTGRES_PASSWORD | webhook_dev_pass_12345 | Image and credentials of the PostgreSQL container. |
Database - external mode (no embedded-db profile)
| Змінна | Типово | Опис |
|---|---|---|
DB_HOST | postgres | Database connection; DB_HOST stays `postgres` (the Compose service) in embedded mode. |
DB_PORT | 5432 | Database connection; DB_HOST stays `postgres` (the Compose service) in embedded mode. |
DB_NAME | webhook_platform | Database connection; DB_HOST stays `postgres` (the Compose service) in embedded mode. |
DB_USER | webhook_user | Database connection; DB_HOST stays `postgres` (the Compose service) in embedded mode. |
DB_PASSWORD | webhook_dev_pass_12345 | Database connection; DB_HOST stays `postgres` (the Compose service) in embedded mode. |
DB_POOL_MAX_SIZE | 20 | 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_IDLE | 10 | 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_TIMEOUT | 30000 | 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_SIZE | 40 | 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_IDLE | 20 | 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_IMAGE | redis:7-alpine | Redis image, address, password and memory cap. |
REDIS_HOST | redis | Redis image, address, password and memory cap. |
REDIS_PORT | 6379 | Redis image, address, password and memory cap. |
REDIS_PASSWORD | webhook_redis_pass | Redis image, address, password and memory cap. |
REDIS_MAXMEMORY | 256mb | Redis image, address, password and memory cap. |
Security (required - must change for production)
| Змінна | Типово | Опис |
|---|---|---|
WEBHOOK_ENCRYPTION_KEY | dev_encryption_key_32_chars_min! | Key that encrypts stored secrets, 32+ characters. |
WEBHOOK_ENCRYPTION_SALT | dev_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_VERSION | 0 | Key version new encryptions use; 0 picks the highest. |
JWT_SECRET | dev_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_TAG | latest | API image tag. |
Worker service
| Змінна | Типово | Опис |
|---|---|---|
WORKER_IMAGE_TAG | latest | Worker image tag. |
Scheduling (api + worker)
| Змінна | Типово | Опис |
|---|---|---|
SCHEDULING_POOL_SIZE | 8 | 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_PORT | 8080 | 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_BIND | 0.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_TAG | latest | 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_DAYS | 90 | Days to keep failed and successful (2xx) Attempts, and received incoming events. |
DATA_RETENTION_SUCCESSFUL_ATTEMPTS_DAYS | 14 | Days to keep failed and successful (2xx) Attempts, and received incoming events. |
DATA_RETENTION_INCOMING_EVENTS_DAYS | 30 | Days to keep failed and successful (2xx) Attempts, and received incoming events. |
DATA_RETENTION_EVENTS_DAYS | 90 | 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_DAYS | 14 | 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_DELIVERY | 10 | Most recent Attempts kept per Delivery. |
DATA_RETENTION_BATCH_SIZE | 1000 | Rows per cleanup batch. |
DATA_RETENTION_CRON | 0 0 2 * * * | Cleanup schedule (cron, daily at 2 AM). |
DATA_RETENTION_LIMIT_CRON | 0 */30 * * * * | Limit enforcement schedule (cron, every 30 minutes). |
DATA_RETENTION_BURST_CLEANUP_CRON | 0 0 */4 * * * | Extra cleanup for daytime error spikes (cron, every 4 hours). |
DATA_RETENTION_TABLE_METRICS_INTERVAL_MS | 900000 | Table size gauge refresh interval (ms). |
Partition maintenance
| Змінна | Типово | Опис |
|---|---|---|
PARTITION_MAINTENANCE_ENABLED | true | 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_MONTHS | 3 | 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_WEEKS | 3 | 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_CRON | 0 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_SECOND | 5000 | Platform-wide request limit per instance (requests/s). |
ORG_RATE_LIMIT_ENABLED | false | 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_SECOND | 200 | 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_ENABLED | true | 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_SECOND | 100 | Events per second per project (token bucket). |
AUTH_RATE_LIMIT_LOGIN_PER_MINUTE | 10 | Sign-in and registration attempts per minute, per IP and per email. |
AUTH_RATE_LIMIT_REGISTER_PER_MINUTE | 5 | Sign-in and registration attempts per minute, per IP and per email. |
AUTH_RATE_LIMIT_REFRESH_PER_TOKEN_PER_MINUTE | 30 | 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_MINUTE | 600 | 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_STRENGTH | 12 | BCrypt cost, 4-31; each step doubles the work. Changing it never invalidates stored hashes. |
AUTH_LOCKOUT_ENABLED | true | 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_THRESHOLD | 5 | Consecutive failures before the account locks. |
AUTH_LOCKOUT_INITIAL_SECONDS | 60 | First lockout, in seconds. Doubles with each further failure. |
AUTH_LOCKOUT_MAX_SECONDS | 900 | Cap on the doubling, in seconds; longer only helps someone locking a stranger out. |
AUTH_LOCKOUT_FAILURE_WINDOW_MINUTES | 60 | Minutes after which a failure no longer counts toward the lockout. |
AUTH_SESSION_CLEANUP_INTERVAL_MS | 3600000 | Interval for purging expired sessions (ms). |
Webhook delivery
| Змінна | Типово | Опис |
|---|---|---|
WEBHOOK_MAX_PAYLOAD_SIZE_BYTES | 262144 | Largest event payload accepted (bytes). |
WEBHOOK_MAX_FANOUT_PER_EVENT | 100 | Most Deliveries one Event may fan out to. |
WEBHOOK_PAYLOAD_COMPRESSION_THRESHOLD_BYTES | 1024 | Payloads larger than this are stored gzip-compressed (bytes). |
ORGANIZATION_SUSPENSION_CACHE_TTL_SECONDS | 60 | Seconds an organization's suspension state is cached on each node; other nodes see a change within this window. |
WEBHOOK_PROJECT_RATE_LIMIT_PER_SECOND | 50 | 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_REQUIRED | false | Require new endpoints to prove ownership before they receive deliveries (true | false). |
WEBHOOK_INGRESS_REPLAY_WINDOW_MINUTES | 5 | 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_IPS | false | Allow delivery to private IPs (SSRF risk, e.g. cloud metadata). Development only; refused in production. |
WEBHOOK_MAX_CONCURRENT_PER_ENDPOINT | 5 | Concurrent deliveries per endpoint. |
WEBHOOK_MAX_CONCURRENT_PER_TENANT | 20 | 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_SECONDS | 90 | Seconds a concurrency permit lives before Redis reclaims it; must exceed the 60s maximum delivery timeout plus setup time. |
WEBHOOK_OUTGOING_POOL_SIZE | 50 | Threads for outgoing deliveries. |
WEBHOOK_INCOMING_POOL_SIZE | 20 | Threads for incoming forwards. |
WEBHOOK_CLAIM_ENABLED | true | Worker claims due Deliveries and Forwards from Postgres (true | false). |
WEBHOOK_CLAIM_IDLE_POLL_MS | 200 | How long a poll that found nothing sleeps (ms); a full batch polls again at once. |
WEBHOOK_CLAIM_TIMEOUT_SECONDS | 300 | Seconds after which a claimed row whose worker has not finished is claimed again; keep above 60s plus transformation time. |
WEBHOOK_CLAIM_MAX_TARGETS | 500 | Endpoints or destinations one poll visits. |
WEBHOOK_ASYNC_SHUTDOWN_TIMEOUT_SECONDS | 60 | Seconds to wait for in-flight deliveries on shutdown. |
CLIENT_ERROR_REPORTING_ENABLED | true | 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_MINUTE | 20 | 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_BYTES | 1048576 | Receiver response body buffered per attempt (bytes); past it the status code alone decides. Only the first 10 KiB is stored. |
TRANSFORM_SCRIPT_TIMEOUT_MS | 2000 | 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_MB | 128 | Allocation limit per run (MB), counted as total allocation rather than live heap. |
TRANSFORM_SCRIPT_MAX_OUTPUT_BYTES | 1048576 | Largest body a script may return (bytes). |
TRANSFORM_SCRIPT_MAX_CONSOLE_LINES | 100 | console.* lines kept per run for the Transform Studio. |
TRANSFORM_SCRIPT_MAX_CHARS | 65536 | Largest script the engine compiles (characters). |
WEBHOOK_POOL_MAX_CONNECTIONS | 200 | Outgoing HTTP connection pool shared by deliveries and forwards (connections, seconds). |
WEBHOOK_POOL_PENDING_ACQUIRE_TIMEOUT_SECONDS | 10 | Outgoing HTTP connection pool shared by deliveries and forwards (connections, seconds). |
WEBHOOK_POOL_MAX_IDLE_TIME_SECONDS | 60 | 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_URL | http://localhost:8080 | Base URL for ingress URLs shown in the dashboard. |
WEBHOOK_INCOMING_MAX_PAYLOAD_SIZE_BYTES | 524288 | Largest incoming payload accepted (bytes). |
WEBHOOK_INCOMING_RATE_LIMIT_PER_SECOND | 100 | Default ingress limit for a source that sets none (requests/s); 0 disables the default. |
DLQ_MONITORING_INTERVAL_MS | 60000 | DLQ monitoring interval (ms). |
Ordering (FIFO delivery per endpoint)
| Змінна | Типово | Опис |
|---|---|---|
ORDERING_GAP_TIMEOUT_SECONDS | 60 | 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_SECONDS | 5 | Fallback poll for a Delivery parked behind a missing sequence (seconds). |
ORDERING_DELIVERED_SEQ_TTL_HOURS | 24 | TTL of delivered-sequence tracking in Redis (hours). |
ORDERING_BUFFER_TTL_MINUTES | 10 | TTL of the ordering buffer in Redis (minutes). |
ORDERING_BUFFER_GAUGE_RESYNC_MS | 30000 | How often the ordering buffer size gauge resyncs from Redis (ms). |
ORDERING_STRANDED_SEQUENCE_AFTER_SECONDS | 120 | 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_SIZE | 500 | 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_HOURS | 48 | How far back sequence reconciliation looks for active ordered endpoints (hours). |
ORDERING_SEQUENCE_RECONCILIATION_INTERVAL_MS | 900000 | Sequence reconciliation interval (ms). |
Event time machine (replay)
| Змінна | Типово | Опис |
|---|---|---|
REPLAY_BATCH_SIZE | 200 | Events read per replay batch. |
REPLAY_BATCH_DELAY_MS | 50 | Pause between replay batches (ms). |
REPLAY_MAX_EVENTS_PER_SESSION | 500000 | Most events one replay session may cover. |
WEBHOOK_RETRY_AFTER_MAX_SECONDS | 21600 | 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_ENABLED | true | 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_HOURS | 72 | Hours of failures without a success before disabling, at least 1. Shorter than DELIVERY_ESCALATION_HARD_CAP_HOURS on purpose. |
ENDPOINT_AUTO_DISABLE_MIN_FAILURES | 10 | Failed attempts that window must also contain, so an idle endpoint is not disabled. |
ENDPOINT_AUTO_DISABLE_INTERVAL_MS | 300000 | Sweep interval (ms) and targets checked per sweep. |
ENDPOINT_AUTO_DISABLE_BATCH_SIZE | 200 | Sweep interval (ms) and targets checked per sweep. |
Circuit breaker (Redis-backed, shared across worker pods)
| Змінна | Типово | Опис |
|---|---|---|
CIRCUIT_BREAKER_FAILURE_RATE_THRESHOLD | 50 | Failure rate that opens the circuit (percent, 0-100). |
CIRCUIT_BREAKER_MINIMUM_CALLS | 5 | Calls needed before the failure rate is evaluated. |
CIRCUIT_BREAKER_WAIT_DURATION_SECONDS | 30 | Seconds the circuit stays open before probing. |
CIRCUIT_BREAKER_WINDOW_TTL_SECONDS | 120 | Sliding window of the failure counters (seconds). |
CIRCUIT_BREAKER_SLOW_CALL_THRESHOLD_MS | 10000 | A call slower than this counts as slow, even with a 2xx (ms). |
CIRCUIT_BREAKER_SLOW_CALL_RATE_THRESHOLD | 80 | Slow call rate that opens the circuit (percent, 0-100). |
Stale delivery escalation (hard-cap auto-DLQ)
| Змінна | Типово | Опис |
|---|---|---|
DELIVERY_ESCALATION_HARD_CAP_HOURS | 96 | 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_SIZE | 100 | Deliveries per escalation batch. |
Stale forward escalation (hard-cap auto-DLQ, Incoming)
| Змінна | Типово | Опис |
|---|---|---|
FORWARD_ESCALATION_HARD_CAP_HOURS | 24 | 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_SIZE | 100 | 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_MS | 300000 | 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_MS | 300000 | Stale delivery check interval (ms). |
Queue depth metrics
| Змінна | Типово | Опис |
|---|---|---|
QUEUE_DEPTH_METRICS_INTERVAL_MS | 900000 | Queue depth gauge refresh interval (ms). |
QUEUE_DEPTH_METRICS_RETENTION_DAYS | 30 | 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_PROJECT | 10 | Test endpoints per project. |
TEST_ENDPOINT_MAX_TTL_HOURS | 72 | Longest test endpoint lifetime (hours). |
TEST_ENDPOINT_CLEANUP_INTERVAL_MS | 3600000 | Expired test endpoint cleanup interval (ms). |
Rules engine
| Змінна | Типово | Опис |
|---|---|---|
RULES_CACHE_REFRESH_MS | 30000 | Compiled rules cache refresh (ms). |
RULES_EXECUTION_LOG_RETENTION_DAYS | 7 | Rule execution log retention (days). |
Transformations
| Змінна | Типово | Опис |
|---|---|---|
TRANSFORMATION_HISTORY_LIMIT | 50 | Published versions kept per transformation (up to ~64 KB each); the one in use is never dropped. |
Workflow engine
| Змінна | Типово | Опис |
|---|---|---|
WORKFLOW_POOL_CORE_SIZE | 4 | Workflow executor threads and queue capacity. |
WORKFLOW_POOL_MAX_SIZE | 8 | Workflow executor threads and queue capacity. |
WORKFLOW_POOL_QUEUE_CAPACITY | 50 | Workflow executor threads and queue capacity. |
WORKFLOW_MAX_DURATION_SECONDS | 600 | Longest a workflow run may take (seconds). |
WORKFLOW_MAX_RECURSION_DEPTH | 3 | Deepest workflow → CreateEvent → workflow chain. |
WORKFLOW_STUCK_THRESHOLD_MINUTES | 15 | Stuck execution recovery: threshold (minutes) and check interval (ms). |
WORKFLOW_RECOVERY_INTERVAL_MS | 120000 | Stuck execution recovery: threshold (minutes) and check interval (ms). |
WORKFLOW_RESUME_INTERVAL_MS | 5000 | How often suspended delay nodes are checked for being due (ms); the resolution of a delay. |
WORKFLOW_RESUME_BATCH_SIZE | 50 | Due executions resumed per tick; the rest wait for the next tick. |
WORKFLOW_NODE_TIMEOUT_DEFAULT_SECONDS | 30 | Per-node timeouts (seconds) and the timeout thread pool size. |
WORKFLOW_NODE_TIMEOUT_HTTP_SECONDS | 60 | Per-node timeouts (seconds) and the timeout thread pool size. |
WORKFLOW_NODE_TIMEOUT_SLACK_SECONDS | 60 | Per-node timeouts (seconds) and the timeout thread pool size. |
WORKFLOW_NODE_TIMEOUT_CREATE_EVENT_SECONDS | 30 | Per-node timeouts (seconds) and the timeout thread pool size. |
WORKFLOW_NODE_TIMEOUT_POOL_SIZE | 16 | Per-node timeouts (seconds) and the timeout thread pool size. |
WORKFLOW_SHUTDOWN_AWAIT_SECONDS | 30 | Seconds to wait for in-flight workflows on shutdown. |
WORKFLOW_TRIGGER_OUTBOX_POLL_INTERVAL_MS | 2000 | Workflow trigger outbox: poll interval (ms), batch size, attempts per trigger. |
WORKFLOW_TRIGGER_OUTBOX_BATCH_SIZE | 50 | Workflow trigger outbox: poll interval (ms), batch size, attempts per trigger. |
WORKFLOW_TRIGGER_OUTBOX_MAX_ATTEMPTS | 3 | Workflow trigger outbox: poll interval (ms), batch size, attempts per trigger. |
WORKFLOW_TRIGGER_OUTBOX_MAX_PER_PROJECT | 5 | Triggers claimed per project per batch. |
WORKFLOW_TRIGGER_OUTBOX_MAX_CONCURRENT_PER_PROJECT | 3 | Concurrent workflow executions per project. |
WORKFLOW_TRIGGER_OUTBOX_STALLED_AFTER_MINUTES | 15 | 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_MS | 300000 | 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_MS | 300000 | Expired device code cleanup interval (ms). |
Email verification
| Змінна | Типово | Опис |
|---|---|---|
EMAIL_ENABLED | false | 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_FROM | noreply@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_ENABLED | false | Welcome and follow-up mail to new accounts, written for Railhook Cloud; keep off when self-hosting. |
CONTACT_DAILY_LIMIT | 30 | Contact form messages sent per UTC day, so the form cannot spend the mail quota verification needs. |
SMTP_HOST | localhost | SMTP relay, used when EMAIL_ENABLED=true. |
SMTP_PORT | 1025 | 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_AUTH | false | SMTP relay, used when EMAIL_ENABLED=true. |
SMTP_STARTTLS | false | SMTP relay, used when EMAIL_ENABLED=true. |
Alert notifications
| Змінна | Типово | Опис |
|---|---|---|
ALERTS_NOTIFICATIONS_ENABLED | false | Send alert notifications to Slack, webhooks and email (false logs them instead). |
ALERTS_EVALUATION_CRON | 0 * * * * * | Alert rule evaluation schedule (cron); how late an alert can be, not its window. |
Entitlements (limits when billing is off)
| Змінна | Типово | Опис |
|---|---|---|
ENTITLEMENT_DEFAULT_RATE_LIMIT | 100 | Rate limit (events/s) and fan-out applied when BILLING_ENABLED=false, instead of no limit. |
ENTITLEMENT_DEFAULT_MAX_FANOUT | 50 | 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_ENABLED | false | Enforce plan quotas (false = self-hosted, unlimited). In production it also requires EMAIL_ENABLED=true and CAPTCHA_SECRET_KEY. |
BILLING_DEFAULT_PROVIDER | noop | 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_CRON | 0 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_LOCALE | en | Build-time only: locale the public pages are prerendered in. |
Tunnel (CLI local webhook tunnels)
| Змінна | Типово | Опис |
|---|---|---|
TUNNEL_INGRESS_BASE_URL | http://localhost:8080 | Public base URL of incoming-source and tunnel URLs; defaults to APP_BASE_URL. |
TUNNEL_HEARTBEAT_TIMEOUT_SECONDS | 120 | Seconds without a heartbeat before a tunnel session is stale. |
TUNNEL_CLEANUP_INTERVAL_MS | 60000 | Stale session cleanup interval (ms). |
TUNNEL_REQUEST_LOG_RETENTION_DAYS | 7 | Tunnel request log retention (days), enforced by dropping weekly partitions. |
Mcp server (ai agents)
| Змінна | Типово | Опис |
|---|---|---|
MCP_ENABLED | true | Serve the MCP server at /mcp, authenticated with a project API key. |
MCP_OAUTH_ENABLED | true | 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_ORIGINS | http://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_LEVEL | INFO | TRACE | DEBUG | INFO | WARN | ERROR |
SWAGGER_ENABLED | false | 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_ENABLED | true | 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_REPLICAS | 1 | 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_USER | admin | Grafana admin login. |
GRAFANA_PORT | 3001 | 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_RETENTION | 15d | Prometheus retention time and disk budget. |
PROMETHEUS_RETENTION_SIZE | 4GB | 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_URL | http://localhost:9093 | Alertmanager's address in Slack and webhook payloads. |
Log aggregation (Loki)
| Змінна | Типово | Опис |
|---|---|---|
LOKI_RETENTION_PERIOD | 168h | 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_DAYS | 30 | Backup directory and retention (days) for `make backup-db` and the db-backup service. |
DB_BACKUP_INTERVAL_SECONDS | 86400 | Seconds between scheduled backups by the db-backup service. |
Жодна змінна не відповідає пошуку.