git push deploys for SQLite apps, on your own server.

litehouse turns a $5 VPS into a push-to-deploy host: HTTPS subdomains, nightly S3 backups, and a one-command restore onto a fresh machine. GitHub Actions does the builds. Your server just runs things.

Install on a Linux host with wildcard DNS pointed at it:

curl -fsSL https://raw.githubusercontent.com/danbruder/litehouse/main/install.sh \ | sudo sh -s -- --domain lh.example.com

The whole workflow

Four commands, then just git push.

  1. 01
    install.sh --domain lh.example.com

    Sets up Caddy and the litehouse server container on your VPS. Prints an admin token once.

  2. 02
    lh connect https://admin.lh.example.com --token …

    Points the CLI on your laptop at the server. That's all the auth setup there is.

  3. 03
    lh create myapp --repo you/myapp

    Registers the app, commits a GitHub Actions workflow to your repo, and sets the deploy secret. You don't write any CI YAML.

  4. 04
    git push

    Actions builds the image and pushes it to GHCR. The server pulls it, swaps the container, and your app is live at myapp.lh.example.com.

Your repo needs a Dockerfile that listens on a port. That's the only requirement for the app itself.

What you get

The parts of a PaaS you actually use.

Push to deploy

GitHub Actions builds; the server pulls from GHCR and replaces the container. The server never runs docker build, so a 1 GB box is enough.

HTTPS subdomains

Caddy with Let's Encrypt. Every app gets {app}.{your-domain}. Add your own domains with lh domain add.

Nightly backups to S3

Consistent SQLite snapshots via VACUUM INTO, plus the server's own state. 14 days retained. Any S3-compatible bucket.

Incremental file backups

Write uploads to $LITEHOUSE_BLOB_PATH. Each file goes to S3 once and is never re-sent.

Restore onto a fresh box

Install, connect, lh restore --yes. Apps, env vars, deploy tokens, and data come back from S3 and GHCR.

Env, logs, lifecycle

lh env, lh logs -f, start / stop / restart. Health checks per app.

A small admin UI

Apps, deploy history, logs, metrics, backups. Served from the same binary, behind the same admin token.

An MCP server

lh mcp serve exposes deploys, logs, env, domains, and backups as tools for Claude Code or any MCP client.

Backups & recovery

Assume the server dies.

Nothing on the box is precious. Every night litehouse snapshots each app's SQLite data and its own state database to your S3 bucket. If the machine is gone, start a new one and run three commands.

# on a brand-new server
$ lh install --domain lh.example.com \
    --s3-bucket … --ghcr-token …

# from your laptop
$ lh connect https://admin.lh.example.com --token …
$ lh restore --yes

# state DB, images, volumes, blobs: back.
  • A backup only counts if every app backed up. One failure and the day isn't marked good. lh backup status --json tells you the last good date.
  • The full cycle is tested. Wipe, reinstall, and restore is an automated script (e2e/dr-drill.sh) that runs against a real droplet.
  • Plain files in your bucket. Backups are tar.gz archives of SQLite files. You can get your data back without litehouse.
  • A failed deploy doesn't take you down. If the new image can't be pulled, the old container keeps running.

For agents

Hand the deploy to your agent.

Claude Code, Codex, Cursor, anything that can run a shell. You do the one step that involves a secret; the agent does the rest and proves it worked.

  1. 01 You, once. Keeps the admin token out of the agent's transcript.

    curl -fsSL https://raw.githubusercontent.com/danbruder/litehouse/main/install-cli.sh | sh lh connect https://admin.lh.example.com --token <ADMIN_TOKEN>
  2. 02 Paste into your agent, from the app's repo.

    Deploy this repo to my litehouse server. 1. Run `lh agent-guide` and follow it exactly. 2. Pick an app name (lowercase letters, digits, hyphens) and make the app deployable: a Dockerfile at the repo root, listening on 0.0.0.0 with the port EXPOSEd, and the SQLite database and any other persistent files under /data. 3. Run `lh doctor --app <name>` and fix every FAIL. If the server connection or my GitHub token is the problem, stop and tell me what to run. Don't ask me for tokens. 4. Create the app, push, and confirm with `lh deploys <name> --wait --sha HEAD`. If it fails, read the build log or `lh logs`, fix it, and push again. 5. When it's live, give me the URL.
  3. 03 Optional: give it the MCP server too.

    claude mcp add litehouse -- lh mcp serve

Cloud agents and CI: skip step 1 and set LITEHOUSE_URL and LITEHOUSE_TOKEN as secrets instead.

$ lh doctor --app myapp
[ok  ] server      litehouse 0.3.0 at https://admin.lh.example.com/api, …
[FAIL] github      token for you is missing scope(s): workflow
                   fix: `gh auth refresh -h github.com -s workflow`
[ok  ] git_repo    origin is github.com/you/myapp
[ok  ] dockerfile  Dockerfile at the repo root
[ok  ] port        HTTPS traffic will go to port 8080 (lowest EXPOSEd TCP port)

$ git push
$ lh deploys myapp --wait --sha HEAD
…
GitHub Actions run for 4be91c02d1 failed (failure), so no deploy was registered.
Build log: https://github.com/you/myapp/actions/runs/…
$ echo $?
1
  • lh agent-guide The whole contract (Dockerfile, port, /data, deploy steps, what each failure means), built into the CLI so it always matches the version installed. Also served as llms.txt and the MCP agent_guide tool.
  • lh doctor Checks every prerequisite in one go (server, token scopes, GitHub origin, Dockerfile, port), and every failure comes with the command that fixes it.
  • --wait --sha HEAD Confirms that this commit is live, not the previous deploy. Exit 0 live, 1 failed, 2 timed out. A failed GitHub build is reported the moment it fails.
  • Everything is non-interactive. --json on read commands, exit codes that mean something, and nothing that waits for a keypress.

Cost

The price of a VPS.

No per-app, per-seat, or per-request pricing, because there's nobody to pay. The tenth app costs the same as the first.

litehousefree, open source
A VPS (handles a handful of small apps)~$5–6 / mo
Builds: GitHub Actions minutesfree tier
Images: GHCRfree tier
Backups: S3-compatible storagecents / mo
Typical total~$5–10 / mo

Fit

When not to use litehouse.

It's narrow on purpose. If any of these are true, pick something else.

  • You need Postgres or MySQL.It's built around SQLite on local disk. A managed PaaS will serve you better.
  • You need more than one server.Single host by design. No clustering, no horizontal scaling.
  • You want scale-to-zero.Apps are always on. That means no cold starts, but also no savings when idle.
  • You don't want to own a server.You'll need a VPS, a domain with wildcard DNS, an S3 bucket, and a GitHub repo.
  • Deploys can't have a gap.A deploy replaces the container. Caddy retries during the swap, but it isn't blue/green.
  • You don't have a Dockerfile.Framework auto-detection isn't supported yet.

Architecture

What's running, and where.

Builds happen on GitHub. Your server pulls images and runs them. Server state is itself a SQLite database, and it's backed up too. Written in Rust, shipped as one binary.

GitHub git push your repo GitHub Actions docker build GHCR image registry Your VPS litehouse-server API · deploy hook · admin UI backups · state (SQLite) app containers one per app SQLite in /data Caddy TLS · routing {app}.your-domain deploy hook pull image users HTTPS S3 your bucket nightly

Compared

Where it sits.

litehouseHosted PaaSSelf-hosted PaaS
Examples—Vercel, Render, RailwayCoolify, Dokku, Kamal
Runs onYour VPSTheir cloudYour VPS
PricingFlat VPS costMetered usageFlat VPS cost
DatabaseSQLite on local diskManaged Postgres, billed separatelyBring your own
Backups + restoreBuilt in, restore tested end to endVaries; usually database onlyPlugins or DIY
Builds run onGitHub ActionsTheir buildersUsually your server
ScopeSQLite apps, one boxAlmost anythingAlmost anything

If you need Postgres or several servers, Coolify and Kamal are good tools. litehouse does less, deliberately.

FAQ

Questions.

Does it work with any language?

Anything with a Dockerfile that listens on a port. Rails, Django, Go, Node, Rust, Phoenix, a static site.

Where does my SQLite file live?

In a Docker volume on the host, mounted at /data inside your container. Put your database there and it gets backed up. Put large uploads in $LITEHOUSE_BLOB_PATH for incremental backup.

What happens during a deploy?

The server pulls the new image, replaces the container, and updates Caddy. If the pull fails, the old container keeps running. Caddy retries requests during the swap, so the gap is short, but it's not a blue/green system.

Can I deploy without GitHub Actions?

Yes. lh deploy myapp --image <ref> deploys any image directly, using the same code path as the deploy hook. The generated workflow is the default, not the only way.

Private repos and images?

Yes. Give the server a GHCR read token with lh config ghcr set --token … (or pass --ghcr-token at install).

Why do my apps restart at night?

Every running app gets a fresh container once a night at 3am US Eastern: same image, clean process. Opt out per app with lh env <app> LITEHOUSE_SKIP_NIGHTLY_RESTART true.

Does it run on ARM?

Yes. x86_64 and aarch64 servers are both supported: Hetzner CAX, AWS Graviton, Oracle Ampere. lh create generates a workflow that builds your app's image for whatever CPU the server has, and a deploy refuses an image built for the wrong one instead of crashing your app.

How do I upgrade litehouse?

lh upgrade. It pulls the new binary and server image and restarts the server container. Your apps keep running.

Is it production-ready?

It runs real apps for its author, and the install and disaster-recovery flows are tested end to end against real servers. It's also young and maintained by one person. The backups are there so that mistakes (yours or ours) are recoverable.

One box. git push. Backed up every night.

curl -fsSL https://raw.githubusercontent.com/danbruder/litehouse/main/install.sh \ | sudo sh -s -- --domain lh.example.com