Start
How it fits together
The ideas behind the dashboard, so its behaviour is never a surprise.
Deploys, and what "zero downtime" means
A deploy starts the new version next to the old one and checks that it answers its health check. Only then does traffic move, and the old container is retired. If the new one never becomes healthy, nothing changes: the previous version keeps serving, and the deploy page shows the error, a plain-words explanation, and the container's own last output. With several replicas, they are replaced one at a time, so at least one is always serving.
Two ways to build
| Build on the server | DeployMate clones the repository (read-only deploy key), builds with your Dockerfile or with Railpack from a runtime you choose, and deploys the image. Simple; needs enough memory on the server for the build. |
|---|---|
| Prebuilt | GitHub Actions builds your app, DeployMate downloads the result and deploys it. The server never runs the build, so a small machine can run heavy apps. Currently for Java (Gradle or Maven) projects on GitHub. |
Setting up prebuilt mode
- On the app's Settings → Git, switch the deploy mode to Prebuilt (GitHub Actions).
- Create a fine-grained GitHub token limited to this one repository with Actions: Read-only, and paste it into the app. It is encrypted at rest and never shown again. Press Test connection.
- Copy the workflow the app page generates into
.github/workflows/deploymate.yml:
name: DeployMate build
on:
push:
branches: ["main"]
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with: { distribution: temurin, java-version: "21", cache: gradle }
- run: ./gradlew bootJar --no-daemon
- run: mkdir out && cp "$(ls build/libs/*.jar | grep -v -- -plain | head -n1)" out/app.jar
- run: cp deploymate.yml deploymate.*.yml out/ 2>/dev/null || true
- uses: actions/upload-artifact@v4
with:
name: "deploymate-app"
path: out/
retention-days: 1
if-no-files-found: error
- In the repository's webhook, tick Workflow runs. When the workflow finishes, DeployMate deploys that run's artifact. Or press Deploy latest run.
The artifact is checked against GitHub's digest before it is used. Artifacts expire after a day (retention-days: 1), so an old run can't be deployed later — press Run workflow now to build a fresh one (that needs the token to have Actions: Read and write).
Services and environments
A project groups apps with their databases and caches. Each app and each service belongs to an environment (dev, staging or production). An app receives the connection URLs of the services in its own project and environment, and only those. That is what keeps a staging app away from the production database.
Instead of clicking, put a deploymate.yml in your repository:
services: - postgres:16-alpine - redis:7-alpine
Each deploy creates what's missing and reuses what's there. A deploymate.staging.yml (or .dev, .production) replaces the list for that environment. In prebuilt mode the generated workflow ships these files inside the artifact, so the same manifest works there too.
Retry, redeploy, roll back, restart
| Retry | The last deploy failed (a flaky build, a service that was down). Runs the same commit again. Only the app's newest deploy can be retried. |
|---|---|
| Redeploy | You changed variables or settings. Restarts the current version with the new settings — no build, no new CI run. |
| Roll back | The new version is bad. Returns to a previous image; the last five are kept. |
| Restart | Restarts the same container. It keeps the environment it was created with, so changed variables need Redeploy. |
What the dashboard watches
- Health every 30 seconds per app, with unhealthy and recovered states on the app and the fleet board.
- Uptime probes per domain, and the real certificate state (valid until, expiring, untrusted, failed).
- Alerts to a webhook (Slack-compatible) for failed deploys, unhealthy apps, uptime changes, restarts, expiring certificates and more.
- CPU and memory every 5 seconds, and live logs.