K0

kield-01/deploy.me

Developer tools
0 stars 0 forks Quality 66 Trend 20MIT

Deploy your projects to your own servers over SSH: releases, Docker Compose, blue/green, rollbacks, live logs, and an MCP server for AI agents. Laravel 13 + Livewire 4. Made with Claude ❤️

Overview

🇬🇧 English · 🇺🇦 Українська Quick start · Install · User guide · MCP for AI agents · Architecture · Security is a local, Dockerized admin app that deploys your projects to . You run it on your Mac at https://deployme.localhost. - Servers come straight from your ~/.ssh/config. - Projects come from GitHub or from a local folder. - Every run is recorded with a live, redacted log. - It deploys with releases and an atomic switch, or in place. - It builds or pulls images, migrates, starts the new containers beside the old ones, and rolls back by itself when the health check says no. You don't need a PaaS, a cloud control plane or an agent on the server: just ssh, rsync and docker compose on the other end. deploy.me runs real production sites. Every feature below is built, tested, and in use. Added from ~/.ssh/config. Host keys are trusted on first use and pinned after that.

README

🇬🇧 English · 🇺🇦 Українська

Quick start · Install · User guide · MCP for AI agents · Architecture · Security


deploy.me is a local, Dockerized admin app that deploys your projects to your own servers over SSH. You run it on your Mac at https://deployme.localhost.

  • Servers come straight from your ~/.ssh/config.
  • Projects come from GitHub or from a local folder.
  • Every run is recorded with a live, redacted log.
  • It deploys with releases and an atomic switch, or in place.
  • It builds or pulls images, migrates, starts the new containers beside the old ones, and rolls back by itself when the health check says no.

You don’t need a PaaS, a cloud control plane or an agent on the server: just ssh, rsync and docker compose on the other end.

[!NOTE] deploy.me runs real production sites. Every feature below is built, tested, and in use.

✨ Features

Also included: 🔁 one-way folder mappings (Mac ↔ server, rsync, previews, capped deletes), 🔑 passkey or password sign-in (with optional authenticator codes), and 💾 nightly backups of deploy.me itself.

🚀 Quick start

All you need is Docker. deploy.me runs the same way on all three systems and brings its own PostgreSQL, Valkey and HTTPS edge, unless you already run a shared stack it can join.

🍎 macOS · 🐧 Linux

You need Docker Desktop or OrbStack on macOS, or Docker Engine with the Compose plugin on Linux. Then run this one line:

curl -fsSL https://raw.githubusercontent.com/KielD-01/deploy.me/main/install.sh | bash

It clones deploy.me into ~/deploy.me and runs bin/install. Read install.sh first if you like. To do the same by hand:

git clone https://github.com/KielD-01/deploy.me.git
cd deploy.me
bin/install

🪟 Windows

You need WSL2 and Docker Desktop with WSL integration turned on. Then, in PowerShell:

irm https://raw.githubusercontent.com/KielD-01/deploy.me/main/bin/install.ps1 | iex

bin/install does everything in one go:

  • checks the tools it needs;
  • describes your machine in .env (bin/configure);
  • pulls the ready-made PHP image from Docker Hub (amd64 and arm64), so nothing compiles, and starts the stack;
  • trusts the local CA in your browsers (macOS keychain, Linux NSS, Windows’ store);
  • prints a one-time link that sets up your passkey or a password.

The per-OS notes, the two stack modes and troubleshooting are in docs/install.md.

Open https://deployme.localhost, then:

  1. Servers → Add server. Pick a host from ~/.ssh/config, trust its key, choose a deploy path.
  2. Projects → Import project. Pick a GitHub repository or a local folder.
  3. Targets → Assign to server, then Prepare.
  4. Deploy 🎉

[!WARNING] Back up APP_KEY from src/api/.env. Stored tokens and env files are encrypted with it.

Want a safe playground first? make sandbox starts a local SSH + Docker server with the alias sandbox.

🤖 Talk to it

# Read-only: look, explain, plan, probe
claude mcp add deployme -- docker exec -i deployme-web php artisan deployme:mcp

# …or allow deploys, rollbacks and cancels too
claude mcp add deployme-ops -- docker exec -i deployme-web php artisan deployme:mcp --allow-deploys

💬 “What’s deployed where, and is anything unhealthy?”

💬 “Why did run #42 fail? Show me the step that broke.”

💬 “Is there a green build on main that isn’t live yet? Deploy it to staging and watch it.”

Setup for Claude Desktop, Cursor and VS Code, the full tool list and the safety model are in docs/mcp.md.

🗺️ How a deploy flows

flowchart TB
    A([🧑 You · 🤖 agent · 🟢 CI]) --> B[🎯 Resolve strategyGHCR · archive · rsync · git]
    B --> C[🔒 Preflightlock · disk · stack]
    C --> D[📤 Upload releaseor pull pinned images]
    D --> E[🧪 compose config]
    E --> F[💾 pg_dump]
    F --> G[🗃️ Migrate]
    G --> H[🔵🟢 Roll / recreateswitch current]
    H --> I{🩺 Health gate}
    I -- ✅ healthy --> J[🧹 Prune releases& images]
    I -- ❌ failing --> K[⏪ Auto-rollback]

    classDef start fill:#a78bf0,stroke:#6d4ac7,color:#0e1116
    classDef step fill:#2a5bd7,stroke:#1f45a8,color:#fff
    classDef gate fill:#6d4ac7,stroke:#4c3291,color:#fff
    classDef good fill:#0f766e,stroke:#0b5750,color:#fff
    classDef bad fill:#d97757,stroke:#b4573a,color:#fff
    class A start
    class B,C,D,E,F,G,H step
    class I gate
    class J good
    class K bad

🏗️ Architecture

flowchart LR
    subgraph mac["💻 Your Mac"]
        browser["🌐 Browserdeployme.localhost"]
        agent["🤖 MCP client"]
        subgraph app["deploy.me containers"]
            web["deployme-webFrankenPHP · Livewire"]
            worker["deployme-workerqueues · scheduler"]
            reverb["deployme-reverbwebsockets"]
        end
        subgraph infra["shared infra · proxy-network"]
            caddy["Caddy edge"]
            pg[("PostgreSQL")]
            valkey[("Valkey")]
        end
    end
    servers[("🖥️ Your servers")]
    github["🐙 GitHub · GHCR"]

    browser --> caddy --> web
    caddy --> reverb
    agent -- "stdio · docker exec" --> web
    web --> pg
    web --> valkey
    worker --> pg
    worker --> valkey
    worker -- "ssh · rsync" --> servers
    worker -- "API" --> github

    classDef c fill:#2a5bd7,stroke:#1f45a8,color:#fff
    classDef i fill:#0f766e,stroke:#0b5750,color:#fff
    classDef x fill:#6d4ac7,stroke:#4c3291,color:#fff
    class web,worker,reverb c
    class caddy,pg,valkey i
    class servers,github,agent,browser x
Service Role
deployme-web FrankenPHP serving the app. The shared edge routes deployme.localhost to it, and websocket requests on /app to Reverb
deployme-worker Supervisor: the queue workers (redis, redis-deploys, redis-probes) and the scheduler. The only container that mounts project folders read-write
deployme-reverb Reverb websockets: live logs, server status, CI updates
deployme-vite Vite dev server with HMR (dev profile only)
deployme-sshd-target A local sshd + Docker sandbox server (sandbox profile only)

🧰 Everyday commands

Command What it does
make up · make down · make restart Start, stop or restart the stack
make ps · make logs s=deployme-worker Status; follow logs (s= for one service)
make enroll A one-time link to set up a passkey or password (first run, or a lost way in)
make doctor Check infra, containers, TLS, websockets, every server alias and the GitHub tokens
make dev · make assets Vite with HMR · build the frontend
make test · make sandbox · make test-ssh The Pest suite · start the SSH sandbox · run the real-SSH tests against it
make backup · make backup-install · make backup-status Back up deploy.me’s database and APP_KEY
make artisan c="…" · make sh Artisan, or a shell, in the web container
make help Every target

🛡️ Security model

  • 🔑 Passkeys first, a password if you need one. The password needs at least 12 characters, is rate-limited, and can require an authenticator code. There’s one account: the first visit (or make enroll) creates it, then the page is gone, and the last way in can’t be removed. Trusting a host key, touching env files, deleting during a sync, adding or removing tokens, and changing how you sign in all ask you to confirm it’s you again.
  • 🤫 Secrets never go in argv or logs. Remote scripts receive them over stdin, git gets tokens only through GIT_ASKPASS, and the step logger redacts before anything is stored or broadcast.
  • 🔐 Encrypted at rest. GitHub tokens, env files and the Telegram token are encrypted with APP_KEY.
  • 📌 Pinned host keys. Trusted on first use and stored in the database. A changed key stops the connection.
  • 👀 The probe reads names and counters, never command lines. Its network sample runs read-only ss under sudo -n, and is skipped where sudo would ask for a password.
  • 🚧 Guard rails. Local imports stay inside the project roots, nothing is pushed into a reserved server path (/opt/infra), and the MCP server is read-only unless you say otherwise.

🧪 Tests

make test       # 480+ Pest tests, in the container, against deployme_test
make sandbox    # then:
make test-ssh   # the deploy scripts for real, against the local SSH sandbox

tests/Feature/Deploy/PipelineMatrixTest.php guards which steps run for each deploy mode × delivery strategy. tests/Feature/QueueConfigTest.php keeps every queue’s retry_after above its worker timeout.

❤️ Made together with Claude

deploy.me was designed and built by Roman Kozin together with Claude, Anthropic’s AI, working as a pair in Claude Code. They worked through the plan, the design canvas, the deploy engine and its bash scripts, the tests, the MCP server and this README, one commit at a time. Roman made the calls and Claude wrote most of the code with him. 🤝

📄 License

MIT © 2026 Roman Kozin. Use it, fork it, ship with it.

Built in Ukraine 🇺🇦 with ☕, 🐳 and a lot of ssh.

View this README on GitHub

Install

This server does not publish a one-line install command.

Open the repository installation guide