Quickstart
From repo to running app with a read-only preflight check. No Kubernetes, no CI pipeline, no registry.
1. Install
Grab the prebuilt Linux or macOS binary (x86_64 or ARM64) from the releases page and put it on your PATH:
sudo mv meridian /usr/local/bin/
meridian --version(A one-line curl … | sh installer will be available once the landing site is live.)
If you build Meridian yourself with Crystal, the result is still a native binary, but it is not automatically fully standalone. Depending on your toolchain, additional shared libraries may be required.
2. Initialize
Change into your project and let Meridian detect the framework (Marten, Rails, Elixir, Node, Go):
cd my-app
meridian initFor Marten projects, Meridian recognizes the standard project layout, sets MARTEN_ENV=production, and reuses /health if you have defined that route.
Everything Meridian owns lives under a single .meridian/ directory, so your repo root stays uncluttered:
.meridian/
deploy.yml # your deploy config — commit this
hooks/ # optional deploy hooks
.gitignore # ignores secrets, cache/, tmp/This writes a .meridian/deploy.yml that you should review before the first deploy. Update at minimum the host address, public hostname, and image name:
service: my-app
image: ghcr.io/acme/my-app:latest
servers:
web:
hosts:
- prod-01.example.com
proxy:
host: my-app.example.com
ssl: true
app_port: 8000
transfer:
mode: stream # or 'incremental', or omit to pull from a registry
env:
clear:
MARTEN_ENV: production
secret:
- SECRET_KEY_BASE
- DATABASE_URLFor every available field, default, and validation rule, see the deploy.yml reference.
Set any remote secrets listed in env.secret before checking or deploying:
meridian secret gen SECRET_KEY_BASE
printf '%s' "$DATABASE_URL" | meridian secret set DATABASE_URL3. Plan, Check, And Deploy
Inspect the resolved deploy intent locally first - no SSH, no registry calls:
meridian planBefore the first deploy for a new project or host, run through the Pre-Flight Checklist. It catches DNS, image, app-port, and accessory issues that meridian check cannot fully infer.
Then probe the remote hosts, including same-host route collisions with any other Meridian service manifests, then deploy:
meridian check
meridian deployIf check or deploy fails here, start with Troubleshooting: local image missing, manifest collisions, healthcheck timeouts, and stale locks are the most common first-deploy failures.
What happens during deploy:
- You've already built the image locally (
podman build/docker build). Meridian does not build the image for you. - The image is transferred to the server - via
podman pullfrom a registry, or registry-free withtransfer.mode: stream(SSH + zstd) ortransfer.mode: incremental(OCI layout + rsync). - Meridian writes Quadlet units under
~/.config/containers/systemd/, including the sharedmeridian-proxynetwork for proxied services, anddaemon-reloads your user systemd. - kamal-proxy waits for the health check and atomically switches traffic from the old container color to the new one.
- The old color is stopped, service-scoped runtime state is recorded under
~/.local/state/meridian/services/<service>/, and unused images are pruned.
This typically takes 10-20 seconds for a small app.
Static assets
assets: is optional. When you declare it, the assets.command runs in your app image during the deploy, and the files it writes to assets.output_dir are copied into a deploy-managed volume as a fingerprinted release. Requests to assets.host are routed by kamal-proxy to a generated Caddy asset server that serves the current release. Typical small and medium Rails or Marten apps do not need separate asset infrastructure - object storage or a CDN - to reach production; see assets.
4. Rollback
Something went wrong? Switch back to the previous color:
meridian rollbackkamal-proxy switches traffic back without rebuilding any container.
Where To Go Next
- Guide overview - concepts and architecture
- Pre-Flight Checklist - what to verify before deploy
- Troubleshooting - common deploy failures and fixes
- Reference - all
deploy.ymloptions and CLI commands
