Sitelet https://github.com/varyform/environment-gate
Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

environment_gate

One shared password in front of a whole Rack app — for staging, demo and preview environments that should not be public but don't need real accounts.

  • Visitors see a minimal, self-contained password form (no asset pipeline).
  • The right password sets a cookie carrying an HMAC of the password, keyed by your secret — rotating the password invalidates every cookie at once.
  • Fail-closed: no configured password means nobody gets in.
  • Health check (/up) stays reachable; return_to only accepts same-origin paths.
  • Shareable links: https://staging.example/anything?gate_password=… sets the cookie and redirects to the same URL without the parameter — the secret doesn't linger in the address bar, history or screenshots.
  • Link previews work: a messenger's crawler fetching that link is served the page directly — it presented the password but can't keep a cookie — so the card shows the real title, description and image. A crawler is a known agent token (WhatsApp, Slack, iMessage's Facebot, Twitterbot, Discord…) or a request with no Accept-Language header (Telegram and Viber wear a plain Chrome agent; browsers always send the header). /og.png is open by default for the picture. Crawlers without the password see the form like anyone else.

Rails

# Gemfile
gem "environment_gate"

# config/environments/staging.rb — and demo.rb, preview.rb, …
config.environment_gate.enabled = true

The middleware is appended to the stack (after ActionDispatch::Static, so fingerprinted assets stay reachable). The password comes from ENVIRONMENT_GATE_PASSWORD, else Rails.application.credentials.environment_gate_password — one password per environment, or a single string shared by all of them:

# bin/rails credentials:edit
environment_gate_password:
  staging: …
  demo: …

The cookie key is secret_key_base. Password and key are read per request. The form's heading defaults to the environment name ("Staging environment").

Any option below can be set the same way, e.g. config.environment_gate.title = "Preview".

The link

bin/rails environment_gate:link                     # this environment
bin/rails environment_gate:link ENV=demo            # another environment's password
bin/rails environment_gate:link ENV=demo HOST=https://demo.example

prints https://host/?gate_password=… from that environment's credential and its host: HOST= if given, else the Kamal destination's proxy.host (config/deploy.<env>.yml — the one place the public name of another environment is written down), else the running environment's default_url_options.

Plain Rack

use EnvironmentGate::Middleware, password: ENV["ENVIRONMENT_GATE_PASSWORD"],
                                 secret: ENV["SECRET_KEY_BASE"]

password and secret may be strings or callables (resolved on every request).

Options

Option Default
cookie_name "environment_gate"
form_path "/environment-gate" where the form posts
param_name "gate_password" query parameter that unlocks on GET; nil disables
open_paths ["/up"] exact paths that bypass the gate
preview_paths ["/og.png"] open paths for link-card images
preview_agents WhatsApp, Telegram, Slack, Twitterbot, facebookexternalhit, Discordbot, LinkedInBot, Applebot, iMessage, Signal, Skype, Viber, Mastodon, Bluesky… User-Agent substrings served the page directly when the URL carries the right password; [] disables
title "Restricted environment" form heading (Rails: the environment name)

Tests

ruby -Ilib -Itest test/middleware_test.rb

History

Formerly staging_gate (config.staging_gate, STAGING_GATE_PASSWORD, credentials.staging_gate_password, cookie staging_gate, form /staging-gate). Renamed when a second gated environment arrived and the password became per-environment.

About

Shared-password gate in front of a whole Rack app — for staging, demo and preview environments.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages