A developer's switchyard: point local apps at any backend stand, keep servers and secrets at hand, build and deploy - from any directory.
Why
Working against several backend stands scatters the day: you cd into a folder to start a project, edit .env files across repositories to switch a stand, dig through notes for a password, and keep deploy paths in your head.
turnout keeps all of it in one place and works from any directory. What it is, on one screen: lacodda.github.io/turnout/what-is-turnout.
A day in the life
Point an app at a stand - the app keeps talking to localhost, and the gateway routes it there, with a cookie jar per app and stand so the switch does not log you out:
$ turnout use web staging
'web' now uses 'staging'.
The running gateway picks this up automatically.
'staging' is up: https://staging.example.com/health answered 200 in 84 ms.
Start working, from wherever you happen to be. The console stays quiet once the server is up - until something breaks:
$ cd ~/dev/web/src/components
$ turnout dev --open
[web] pnpm dev --port 5100
[web] http://web.localhost -> dev server port 5100
◇ web ready in 1.4s - http://web.localhost
Ship it - build, back up, upload as one archive, restart, and ask the stand whether it works:
$ turnout deploy web-prod-eu -b
[web] pnpm build
✓ Connected to deploy@prod-eu.example.com:22
✓ Backup 20260809-011500.tar.gz created in /var/www/web.backups
Uploaded 142 files (3.11 MiB) to prod-eu:/var/www/web
✓ Restarted: systemctl restart web
✓ Healthy: GET https://prod-eu.example.com/health - 200 in 38 ms
Deploy of 'web' to 'prod-eu' finished.
And see what has been going on:
$ turnout status
turnout 1.0.0 ~/.local/share/lacodda/turnout
Apps
api -> staging http://api.localhost spare :7101 (TURNOUT_GATEWAY_URL)
web -> prod-eu http://web.localhost spare :7100 (VITE_API_URL)
Gateway running · pid 24180 · up 2h 05m
! 'staging' answers 502 - the stand is down, not the app (3m)
Jobs 2 running - `turnout ps` shows the rest
Recent
3m ago deploy web -> prod-eu (142 files)
What you get
- A dev gateway. One address per app (
http://web.localhost), ports assigned for you, redirects and WebSockets proxied, a session per app and stand. Gateway - Servers, logins and paths, apart - joined into named targets, so
turnout deploy web-prodworks from any directory. Entities - A deploy that checks itself.
--diffbefore, a health check after and a rollback when it fails, a history of every deploy; Linux and Windows servers alike. deploy - Access set up, not just used. Secrets in the OS keyring,
key setupthat proves a key before switching to it, the SSH agent, and every server's host key checked. SSH access - A quiet console and jobs in the background. A loader instead of scrollback, the output on the spot when something fails,
--detachwith a desktop notification at the end. Quiet console - A doctor.
turnout doctorsays why it does not work, anddoctor --server prodwhere a deploy would stop - each with its fix. doctor - One window onto it all.
status,status --shortfor a prompt line,--jsonon every command that reports, an action journal of every change. - Portable settings.
exportandimportbetween machines, secrets sealed with a passphrase; a file from any release since 0.11 still imports.
The whole tour is on the documentation site.
Install
Or the one-line installers - PowerShell on Windows, sh on macOS and Linux:
irm https://raw.githubusercontent.com/lacodda/turnout/main/tools/install.ps1 | iex
|
Every way but cargo install also sets up the short alias tn. Archives for Windows x86_64, Linux x86_64 and arm64, and macOS arm64 are on the releases page; what each installer reads is in Getting started.
Quick start
Status
v1.0.0, the first stable release. The settings are a contract: an export written by any release since v0.11 imports into this one, and nothing in 1.x breaks it. Deploys are proven against real Linux and Windows servers on every push; what landed in each version is in the changelog.
Documentation
Commands, concepts and guides: lacodda.github.io/turnout. The site's source is in docs/, and architecture decision records are in docs/adr/.
License
MIT (c) Kirill Lakhtachev