Deploy Atuin

Searchable, synced shell history for every machine you work on

Deploy Atuin

/var/lib/postgresql/data

Deploy and Host Atuin Server on Railway

Atuin replaces the shell history in bash, zsh, fish and nushell with a searchable SQLite database that keeps far more than the command text — working directory, exit code, duration, hostname and session — then syncs it between every machine you work on. The sync half is a small Rust service, atuin-server, and self-hosting it keeps your command history on infrastructure you control. Deploy Atuin Server on Railway and you get that endpoint without a VPS, a reverse proxy or a TLS certificate.

This template runs two services. atuin is the sync API, built from the gridalpha/atuin-server-railway source repository on top of the official ghcr.io/atuinsh/atuin image; it is the only service with a public URL and it answers every request from your atuin CLI. Postgres is a Railway-managed PostgreSQL 18 instance on a persistent volume, reachable only over the private network, holding every account and synced record. History is encrypted on your laptop before upload, so what lands in Postgres is ciphertext the server cannot read.

Diagram of the Atuin sync server and Postgres services on Railway

Getting Started with Atuin Server on Railway

Deploy the template, pick a username, and let Railway generate the password. On first boot the service creates that account and then closes registration, so the public URL is never an open sign-up page. Open the generated Railway URL in a browser: a JSON body with a Terry Pratchett quotation and the server version is the fastest confirmation the deployment is live.

Everything else happens in your terminal. Install the client, point it at your new server, and log in with the username and password from the service variables:

curl --proto '=https' --tlsv1.2 -LsSf https://setup.atuin.sh | sh
echo 'sync_address = "https://your-app.up.railway.app"' >> ~/.config/atuin/config.toml
atuin login -u 
atuin import auto
atuin sync

atuin login asks for an encryption key. On your first machine leave it blank and Atuin generates one; after that, run atuin key on a machine already set up and paste the phrase it prints. Losing that phrase means losing the ability to read your own history, so keep it in a password manager. Once atuin sync reports records uploaded, press Ctrl-R in a new shell, then repeat the login on a second machine and watch the same commands appear.

Atuin record index showing synced history and kv counts Encrypted PASETO history records stored by the Atuin server Atuin server index endpoint reporting version 18.21.0

About Hosting Atuin Server

Shell history is one of the most useful datasets a developer owns and one of the worst-managed: capped at a few thousand lines, lost when a terminal crashes, stranded per-machine, holding nothing but the text you typed. Atuin fixes all four, and self-hosting the sync server keeps that dataset — full of hostnames, flags and internal service names — off a third party's infrastructure.

  • Full-text search over every command you have run, filtered by directory, host, exit code or session
  • End-to-end encryption: records are sealed client-side with PASETO v4; the server stores only ciphertext
  • Imports .bash_history, .zsh_history, fish history or histdb in one command
  • Syncs an encrypted key-value store and dotfile aliases alongside history
  • bash, zsh, fish and nushell, on macOS, Linux and WSL

The architecture is deliberately small. atuin is stateless — it authenticates requests, validates record indices and writes to Postgres — so a redeploy loses nothing. Postgres owns all durable state on its volume and is never exposed publicly. The server also publishes Prometheus metrics on a second port only reachable over the private network.

Why Deploy Atuin Server on Railway

Running the sync server yourself normally means a VM, a database and a TLS story.

  • HTTPS, certificates and renewals handled by Railway's edge
  • Managed PostgreSQL with backups, provisioned and wired up already
  • Your account is created at deploy time; registration stays closed by default
  • Private networking between API and database — no public database port
  • Redeploys are stateless, so upgrades are one click

Common Use Cases

  • One history across every machine — laptop, desktop and remote build boxes searching the same history.
  • Team-scale privacy — a team that will not put its commands or internal hostnames on a vendor's servers.
  • Recovery for muscle memory — a rebuilt machine restores years of commands with one atuin sync.
  • Finding what actually worked — exit codes and durations stored beside each command.

Dependencies for Atuin Server

  • atuinghcr.io/atuinsh/atuin:18.21, wrapped by gridalpha/atuin-server-railway. Serves the sync API on port 8888 and creates the first account at boot.
  • Postgres — Railway-managed PostgreSQL 18 on a volume, holding users, sessions and encrypted records. Atuin needs PostgreSQL 14+ and checks the version at startup.

Environment Variables Reference

VariablePurpose
ATUIN_DB_URIPostgreSQL connection string, wired to the Postgres service
ATUIN_BOOTSTRAP_USERNAMEAccount created at first boot; letters, digits, hyphens
ATUIN_BOOTSTRAP_PASSWORDPassword for that account; generated for you at deploy time
ATUIN_OPEN_REGISTRATIONfalse by default; true lets other people sign up
ATUIN_METRICS__ENABLEPrometheus exporter on the private network, on port 9001
ATUIN_MAX_RECORD_SIZELargest single record the server will accept, in bytes
PORTPort the API listens on; leave at 8888

Deployment Dependencies

  • Source repository:
  • Upstream project:
  • Container image: ghcr.io/atuinsh/atuin
  • Self-hosting docs:

Hardware Requirements for Self-Hosting Atuin Server

ResourceMinimumRecommended
CPU0.5 vCPU1 vCPU
RAM256 MB API, 256 MB PostgreSQL512 MB each
Storage1 GB volume5 GB volume, growing with history
RuntimePrebuilt Rust image, PostgreSQL 14+PostgreSQL 18

A single user with years of history usually stays under 100 MB in Postgres.

Self-Hosting Atuin Server

Outside Railway the smallest working setup is the official image plus a PostgreSQL container. The following is a Docker Compose file:

services:
  atuin:
    image: ghcr.io/atuinsh/atuin:18.21
    command: start
    ports: ["8888:8888"]
    environment:
      ATUIN_HOST: "0.0.0.0"
      ATUIN_OPEN_REGISTRATION: "true"
      ATUIN_DB_URI: postgres://atuin:atuin@db/atuin
    depends_on: [db]
  db:
    image: postgres:18
    volumes: ["./database:/var/lib/postgresql/"]
    environment:
      POSTGRES_USER: atuin
      POSTGRES_PASSWORD: atuin
      POSTGRES_DB: atuin

ATUIN_OPEN_REGISTRATION has to be true long enough to create your account and should be turned off afterwards; the Railway template does that for you. To build from source instead:

git clone https://github.com/atuinsh/atuin && cd atuin
cargo build --release --bin atuin-server
ATUIN_DB_URI="postgres://..." ./target/release/atuin-server start

How Much Does Atuin Cost to Self-Host?

Atuin is MIT-licensed and free, client and server alike, with no paid tier gating self-hosting and no seat count. The project also runs a hosted service, Atuin Hub, for people who would rather not operate a server; self-hosting is a first-class alternative, not a crippled one. On Railway you pay only for the compute and storage the two services use.

FAQ

What is Atuin? Atuin is an open-source replacement for shell history. It records every command into a local SQLite database with its directory, exit code and duration, gives you fuzzy search bound to Ctrl-R, and optionally syncs that history between machines with end-to-end encryption.

What does this Railway template deploy? Two services: atuin, the Rust sync API with a public HTTPS URL, and Postgres, a managed PostgreSQL 18 database on a volume holding accounts and encrypted records.

Why does the template include a PostgreSQL database? The sync server keeps no state on disk. Accounts, sessions and every uploaded record live in PostgreSQL, which is what makes the deployment durable and lets the API redeploy losing nothing.

Can other people register on my self-hosted Atuin server? Not unless you allow it — registration is closed once your account is created. Set ATUIN_OPEN_REGISTRATION to true to invite others, then set it back.

How do I connect the Atuin CLI to a self-hosted server? Set sync_address in ~/.config/atuin/config.toml to your Railway URL, then run atuin login -u . Use the same encryption key on every machine; atuin key prints it.

Can the server read my shell history? No. Records are encrypted with a key that never leaves your machines, and the server stores and returns opaque ciphertext — which is why losing that key is unrecoverable.

Which shells and platforms does self-hosted Atuin support? bash, zsh, fish and nushell on macOS, Linux and WSL, with prebuilt client binaries for x86_64 and aarch64.


Template Content

More templates in this category

View Template
Rocky Linux
Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀

codestorm
47
View Template
Foundry Virtual Tabletop
A Self-Hosted & Modern Roleplaying Platform

Lucas
71
View Template
Letta Code Remote
Run a Letta Code agent 24/7. No inbound ports, just deploy.

Letta
51