Documentation / Deployment config

Configure production deploys without guessing.

This page collects the operator-facing configuration for self-hosted Logister: required secrets, optional services, S3-compatible archive storage, provider-managed files, and the checklist to run before you call a deployment healthy.

Process model

Run web traffic and background work as separate responsibilities.

The production app can be deployed on Fly, Kamal, Docker, or any platform that can run a Rails web process and a Sidekiq worker against PostgreSQL and Redis. Versioned release images are published to ghcr.io/taimoorq/logister and docker.io/taimoorq/logister after CI, Fly deploy, and Fly health checks pass; the workflow can also publish an optional quay.io/taimoorq/logister mirror when Quay credentials are configured.

ProcessPurposeTypical command
WebServes the UI, auth screens, project pages, public pages, health checks, and API ingestion endpoints../bin/rails server behind Puma/Thruster or your platform web command
WorkerRuns asynchronous jobs such as optional ClickHouse event/span ingestion, Action Mailer delivery, first-occurrence error alerts, digest scheduling, and operator-run archive/prune tasks.bundle exec sidekiq -C config/sidekiq.yml
Release or migration stepPrepares the database before the new web process handles traffic../bin/rails db:prepare

Planning note

Low-volume installs can start with one web process and one worker. As traffic grows, scale the web and worker process counts separately so ingestion and background jobs do not compete with user-facing requests.

Required secrets

These are the minimum variables for a production deployment.

VariablePurpose
RAILS_MASTER_KEYDecrypts the app credentials for self-hosted deploys.
DATABASE_URLConnects the Rails app to PostgreSQL for web and worker runtime traffic.
DATABASE_MIGRATION_URLOptional direct PostgreSQL URL used only by the release migration step when your provider separates runtime pooling from migration/admin connections.
REDIS_URLConnects Rails caching and Sidekiq workers to Redis.
LOGISTER_PUBLIC_URLCanonical public URL used for generated links in emails, sitemap, and metadata.
LOGISTER_ADMIN_EMAILSComma-separated email allow-list for operator/admin access.

Production also needs normal Rails platform settings such as RAILS_ENV=production, PORT when your host requires it, and HTTPS termination through your platform, load balancer, or reverse proxy.

Sample env reference

Use .env.sample as a map, then store real values in your provider.

Local development can copy .env.sample to .env. Production should use Fly secrets, Kamal secrets, Docker secrets, GitHub Actions secrets, Cloudflare Pages secrets, or another secret manager. Do not commit real credentials to a fork of this public repository.

EntryWhat it controlsWhat self-hosters should do
RAILS_ENVRails runtime mode.Use development locally and production in deployed environments. Most platforms set this through their app config.
RAILS_MAX_THREADSPuma thread count and Rails database pool sizing.Start with the sample value, then raise only when the database pool and host memory can support more concurrent requests.
RAILS_LOG_LEVELProduction logging verbosity.Use info by default. Temporarily use debug only when investigating issues because debug logs can include sensitive request context.
PORTPort Puma listens on.Set only when your platform requires a specific port. Fly uses 8080 through fly.toml; local Rails defaults to 3000.
WEB_CONCURRENCYOptional Puma worker process count.Leave unset for small installs. Raise only when the host has enough memory and PostgreSQL can support the extra connections.
RAILS_MASTER_KEYDecrypts Rails credentials in production.Generate or copy the master key for your deployment credentials, then store it in your provider secret manager. Never commit config/master.key.
DATABASE_URLPrimary PostgreSQL connection for web and worker runtime traffic.Provision PostgreSQL, then use the connection URL from the provider. For Fly, use Fly Postgres or Managed Postgres. For Prisma Postgres or pooled providers, use the pooled/runtime URL here.
DATABASE_MIGRATION_URLOptional direct PostgreSQL connection for release migrations.Set this only when the provider gives separate pooled and direct URLs. Use the direct/admin URL so db:prepare can run migrations reliably.
REDIS_URLRails cache and Sidekiq job queue backend.Provision Redis or Valkey. Use redis:// locally and rediss:// when your managed Redis provider requires TLS.
SIDEKIQ_CONCURRENCYNumber of jobs each Sidekiq worker process can run in parallel.Start with 5. Raise only when Redis, PostgreSQL, SMTP, and ClickHouse can tolerate more concurrent background work.
LOGISTER_PUBLIC_URLCanonical app URL used in emails, generated links, sitemap, and metadata.Set this after DNS and HTTPS are ready, for example https://logister.example.com. Avoid localhost in production or email links will be wrong.
LOGISTER_DOCS_URLBase URL for in-app documentation links and generated docs metadata.Use https://docs.logister.org for the canonical public docs, or point to your own Cloudflare Pages docs fork. Set the same value as a GitHub Actions variable when building the static docs so cloudflare-docs/sitemap.xml and cloudflare-docs/robots.txt use your docs host.
LOGISTER_ADMIN_EMAILSComma-separated allow-list for admin/operator access.Add the email addresses for trusted operators, using the same addresses they use to sign in.
LOGISTER_API_KEY_PREFIXPrefix for newly generated project ingestion tokens.Leave as logister unless your organization wants branded token prefixes. Changing it does not rotate existing tokens.
LOGISTER_PUBLIC_API_RATE_LIMIT_REQUESTSAccepted public API requests allowed per API token and endpoint in each window.Defaults to 1200. Raise only when Redis and PostgreSQL can absorb the extra ingestion traffic.
LOGISTER_PUBLIC_API_RATE_LIMIT_PERIOD_SECONDSPublic API rate-limit window length in seconds.Defaults to 60. Keep this aligned with client retry behavior.
LOGISTER_PUBLIC_API_AUTH_FAILURE_RATE_LIMIT_REQUESTSMissing, invalid, revoked, or archived-project token attempts allowed per source IP in each window.Defaults to 120. Lower it for exposed public instances that receive noisy unauthorized traffic.
Project-level public API overridesOptional per-project rate-limit overrides stored in the application database.Only app admins listed in LOGISTER_ADMIN_EMAILS can set these from project settings. Project owners and shared project members cannot change them.
LOGISTER_API_KEY, LOGISTER_ENDPOINT, LOGISTER_RELEASEOptional self-observability for the Logister app itself through logister-ruby.Use when you want this Logister instance to report its own app errors, rejected client submissions, ClickHouse ingest failures, digest scheduler failures, and scheduler check-ins to a Logister project. Generate the key from the destination project; using a separate project is usually cleaner than mixing operational telemetry with customer app events.
LOGISTER_CAPTURE_REQUEST_SPANS, LOGISTER_CAPTURE_DB_METRICS, LOGISTER_CAPTURE_WEB_REQUEST_TRANSACTIONSSelf-monitoring controls for request spans, slow SQL metrics, and slow Rails request transactions.Leave enabled for production diagnosis unless event volume becomes noisy. Tune with LOGISTER_DB_METRIC_MIN_DURATION_MS, LOGISTER_DB_METRIC_SAMPLE_RATE, LOGISTER_WEB_REQUEST_MIN_DURATION_MS, and LOGISTER_WEB_REQUEST_LOG_MIN_DURATION_MS.
LOGISTER_EMAIL_FROMSender address for auth mail, invitations, first-occurrence alerts, and digests.Use a mailbox on a domain you control, verify that sender or domain with your SMTP provider, and publish SPF, DKIM, and DMARC records.
SES_REGIONAmazon SES region used to derive the default SMTP hostname.Choose the region where you verified your SES identity, such as us-east-1.
SES_SMTP_USERNAME / SES_SMTP_PASSWORDSMTP credentials for Amazon SES delivery.Create SMTP credentials in the Amazon SES console, store them as secrets, and move the SES account out of sandbox mode before sending to arbitrary recipients.
SES_SMTP_ADDRESS, SES_SMTP_PORT, SES_SMTP_DOMAINOptional SMTP endpoint overrides.Leave unset for standard SES, or set them when using a different SMTP-compatible provider.
SES_SMTP_ENABLE_STARTTLS_AUTO, SES_SMTP_OPEN_TIMEOUT, SES_SMTP_READ_TIMEOUTSMTP TLS and timeout tuning.Keep the defaults unless your SMTP provider requires different transport settings.
SES_CONFIGURATION_SETOptional SES delivery-metrics tag for Logister mail.Create a configuration set in SES if you want bounce, complaint, open, or delivery metrics separated for Logister messages.
LOGISTER_CLICKHOUSE_ENABLEDTurns on optional ClickHouse writes.Keep false until PostgreSQL-only operation is not enough. Enable only after ClickHouse schema setup and worker verification.
LOGISTER_CLICKHOUSE_URL, LOGISTER_CLICKHOUSE_DATABASE, LOGISTER_CLICKHOUSE_EVENTS_TABLE, LOGISTER_CLICKHOUSE_SPANS_TABLEClickHouse endpoint, database, raw event table, and raw span table targets.Use values from your ClickHouse server or ClickHouse Cloud service. Load the schema from the ClickHouse guide before enabling writes, then verify readiness with bin/rails logister:clickhouse:schema:status or /health/clickhouse.
LOGISTER_CLICKHOUSE_USERNAME / LOGISTER_CLICKHOUSE_PASSWORDClickHouse credentials.Create a least-privilege ClickHouse user that can insert into and query the Logister event and span tables, then store the password as a secret.
LOGISTER_CLICKHOUSE_FAILURE_THROTTLE_SECONDSThrottle window for Logister self-monitoring when ClickHouse writes fail.Leave the default unless an operator wants more or fewer internal failure reports. Failures are reported through logister-ruby as logs and count metrics when self-observability is configured.
ACTIVE_STORAGE_SERVICEActive Storage service used by production file/archive writes.Use local for a simple private install with mounted disk, or amazon when using S3-compatible archive storage.
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_S3_BUCKETAmazon S3 credentials and bucket target for the built-in amazon Active Storage service.Create a private bucket and a least-privilege IAM user or role that can write only the archive prefix Logister needs. Store the key and secret in your provider secret manager.
AWS_S3_ENDPOINT, AWS_S3_FORCE_PATH_STYLEOptional S3-compatible provider settings.Set these only for non-AWS object stores such as MinIO, R2-compatible gateways, or providers that require a custom endpoint or path-style addressing.
LOGISTER_ARCHIVE_PREFIX, LOGISTER_ARCHIVE_STORAGE_SERVICETelemetry archive object prefix and optional storage-service override.Use a low-cardinality prefix such as telemetry. Leave the storage override blank to use ACTIVE_STORAGE_SERVICE, or set it when archives should use a different Active Storage service.
LOGISTER_TURNSTILE_ENABLEDEnables Cloudflare Turnstile on sign-in, sign-up, password, and confirmation forms.Turn on for public instances that need bot protection. Keep off for private/internal installs unless you want the extra challenge.
LOGISTER_TURNSTILE_SITE_KEY / LOGISTER_TURNSTILE_SECRET_KEYCloudflare Turnstile browser key and server verification secret.Create a Turnstile widget in Cloudflare, add your app domain, put the site key in config, and keep the secret key in your secret store.
LOGISTER_COOKIE_CONSENT_ENABLEDControls whether the cookie consent banner renders.Set false for private installs without optional analytics. Keep true when you run public product pages with analytics.
LOGISTER_ANALYTICS_ENABLEDAllows analytics tags outside production for verification.Leave false unless you need to test analytics in development or staging.
PROBO_COOKIE_BANNER_SCRIPT_URL, PROBO_COOKIE_BANNER_ID, PROBO_COOKIE_BANNER_BASE_URL, PROBO_COOKIE_BANNER_PROXY_ENABLED, PROBO_COOKIE_BANNER_POSITIONProbo Cookie Banner loader and banner configuration.Create or host a Probo-compatible banner configuration, then store the banner ID and upstream base URL in deployment config. The Rails app proxies the upstream by default so browser banner requests stay same-origin; set PROBO_COOKIE_BANNER_PROXY_ENABLED=false only when the upstream supports credentialed CORS for your app domain.
LOGISTER_ANALYTICS_COOKIE_CATEGORYConsent category slug required before analytics scripts load.Match this to the category slug configured in your consent banner, usually analytics.
GOOGLE_TAG_IDOptional Google Analytics measurement ID.Create a GA4 web data stream and use its G-... measurement ID. Use your own property for forks and self-hosted instances.
CLOUDFLARE_WEB_ANALYTICS_TOKENOptional Cloudflare Web Analytics token.Create a Cloudflare Web Analytics site token for your app domain. Use this instead of, or alongside, Google Analytics only when consent requirements are satisfied.
CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_PAGES_PROJECTCloudflare Pages deployment settings for the static docs.Set these in GitHub Actions when deploying cloudflare-docs/. The API token should be scoped to the Pages project. Use the optional LOGISTER_DOCS_URL and DOCS_SITEMAP_LASTMOD repository variables when you want the docs build step to generate fork-specific metadata.
DOCS_PROBO_COOKIE_BANNER_ID, DOCS_PROBO_COOKIE_BANNER_BASE_URL, DOCS_PROBO_COOKIE_BANNER_POSITION, DOCS_ANALYTICS_COOKIE_CATEGORYCloudflare Pages runtime consent-banner configuration.Set these as Cloudflare Pages secrets if you host your own docs site with consent-gated analytics.
DOCS_GOOGLE_TAG_ID, DOCS_CLOUDFLARE_WEB_ANALYTICS_TOKENCloudflare Pages docs analytics IDs.Use your own GA4 or Cloudflare Web Analytics values for your docs fork. These become browser-visible runtime config.

Keep secrets out of git

Values such as RAILS_MASTER_KEY, database passwords, Redis passwords, SES SMTP passwords, Turnstile secret keys, ClickHouse passwords, AWS access keys, S3-compatible storage secrets, and Cloudflare API tokens must live in a provider secret store. The sample file intentionally uses blanks or placeholders.

Scaling knobs

Use these variables when you need more throughput.

VariableDefaultUse when
RAILS_MAX_THREADS3You want each web process to handle more concurrent requests. Match database pool sizing to your thread count.
WEB_CONCURRENCY1You want multiple Puma workers per web machine. Use only when the host has enough CPU and memory.
SIDEKIQ_CONCURRENCY5You want each worker process to run more jobs in parallel. Raise carefully with Redis and database capacity in mind.
RAILS_LOG_LEVELinfoYou need more or less production log detail during operations.

Optional services

Enable additional integrations only when you need them.

ClickHouse

ClickHouse is optional. Keep it off until you need dedicated analytics storage or higher-volume event analysis. When you turn it on, set the ClickHouse variables in the ClickHouse guide, load the event/span schema, verify /health/clickhouse reports ready, and keep the worker running so queued writes can drain.

S3-compatible archive storage

Archive storage is optional. Use it when you want compressed JSONL exports of older hot telemetry before pruning high-volume non-error events from PostgreSQL. The built-in path uses Active Storage, so self-hosters can keep local disk for small private installs or swap to Amazon S3 and S3-compatible providers without changing app code.

shell
ACTIVE_STORAGE_SERVICE=amazon
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=us-east-1
AWS_S3_BUCKET=
LOGISTER_ARCHIVE_PREFIX=telemetry
# Optional for non-AWS S3-compatible providers:
# AWS_S3_ENDPOINT=
# AWS_S3_FORCE_PATH_STYLE=true
# LOGISTER_ARCHIVE_STORAGE_SERVICE=amazon

Export hot telemetry with bin/rails "logister:telemetry:archive[ingest_events,30]" or bin/rails "logister:telemetry:archive[trace_spans,30]". After the archive objects are verified, prune old non-error hot telemetry with CONFIRM=prune bin/rails "logister:telemetry:prune_hot[30]".

Email

Email is optional for a private single-user trial, but recommended for real users because account confirmation, password reset, first-occurrence project error alerts, and daily or weekly digest summaries depend on SMTP delivery.

  • LOGISTER_EMAIL_FROM sets the branded sender for auth, system mail, and project notifications.
  • SES_REGION selects the Amazon SES region, defaulting to us-east-1.
  • SES_SMTP_USERNAME and SES_SMTP_PASSWORD enable Amazon SES SMTP delivery in production.
  • SES_CONFIGURATION_SET optionally tags Logister notification mail for SES delivery metrics.
  • SES_SMTP_ADDRESS, SES_SMTP_PORT, SES_SMTP_DOMAIN, SES_SMTP_ENABLE_STARTTLS_AUTO, SES_SMTP_OPEN_TIMEOUT, and SES_SMTP_READ_TIMEOUT are available when your SMTP provider needs custom settings.
  • Verify the sender domain in SES and publish SPF, DKIM, and DMARC records so notification mail is less likely to be filtered as spam.

Cloudflare Turnstile

shell
LOGISTER_TURNSTILE_ENABLED=true
LOGISTER_TURNSTILE_SITE_KEY=
LOGISTER_TURNSTILE_SECRET_KEY=

The sign-in, sign-up, password, and confirmation flows validate Turnstile when enabled.

Consent-gated analytics

shell
LOGISTER_COOKIE_CONSENT_ENABLED=true
LOGISTER_ANALYTICS_ENABLED=true
PROBO_COOKIE_BANNER_SCRIPT_URL=https://cdn.jsdelivr.net/npm/@probo/cookie-banner/dist/cookie-banner.iife.js
PROBO_COOKIE_BANNER_ID=
PROBO_COOKIE_BANNER_BASE_URL=https://your-probo.example/api/cookie-banner/v1
PROBO_COOKIE_BANNER_PROXY_ENABLED=true
PROBO_COOKIE_BANNER_POSITION=bottom-left
LOGISTER_ANALYTICS_COOKIE_CATEGORY=analytics
GOOGLE_TAG_ID=G-XXXXXXXXXX
CLOUDFLARE_WEB_ANALYTICS_TOKEN=

Provider files

Keep deploy config in version control, but keep secrets out of the repo.

  • Dockerfile for production app images. The release workflow publishes ghcr.io/taimoorq/logister:<version> and docker.io/taimoorq/logister:<version>, plus latest and short-SHA tags in both registries. It also publishes quay.io/taimoorq/logister:<version>, latest, and short-SHA tags when QUAY_USERNAME and QUAY_TOKEN are configured. Run separate web and worker containers from the same image; see the Docker self-hosting option for the full shape.
  • fly.toml.example as the Fly.io template self-hosters can copy before setting their own app name, region, and scale.
  • fly.toml as the tracked production Fly.io config for this public instance, with separate app and worker processes.
  • config/deploy.yml as a Kamal-oriented starting point if you prefer a server-based Docker deployment.
  • docker-compose.yml for local PostgreSQL, Redis, and ClickHouse services. Treat its defaults as local/demo values, not production secrets.

Important

Keep secrets in your deploy provider or CI secret store, not in tracked config files.

Production checklist

Run this checklist before calling the rollout complete.

  1. Set the required secrets and connection URLs.
  2. Configure outbound email if you need system emails, confirmation emails, or project error notifications.
  3. Configure S3-compatible archive storage if you plan to export and prune older hot telemetry.
  4. Pick your deploy method and keep provider config tracked separately from secrets.
  5. Run migrations during deploy.
  6. Verify Sidekiq boots against the production Redis instance and that at least one worker process stays running.
  7. Only then turn on ClickHouse, Turnstile, or analytics tooling if you need them.

Deploy verification

Check the operator path, not just the web process.

Post-deploy verification
Admin user can sign in
Project creation succeeds
API key generation works and shows the token once
Background job processes can connect to Redis
One test event lands in the project inbox
First-occurrence alerts enqueue when a new error group is created
ClickHouse health reports ready if optional ClickHouse is enabled
Archive export task can write to object storage if optional archives are enabled