skip to content
extensionsdocsgithub

// self-hosted · nothing hard-wired

completely pluggable.
completely yours_

skela is a deploy platform that runs on your server. every part of it is a plug: where apps run, how they build, where code comes from, who answers dns. keep the built-ins, swap any of them, or write your own. paste a repo and it's live.

 
+ yours

click a plug to swap it · dashed ones are extensions you'd write

skela.acme.shopexample workspace
Skela home with example acme and docs projects, four live services, connected GitHub and Cloudflare, and a shared activity log.

one prompt

paste a git url, pick a github repo or a docker image. it's built, it's live at a free url, and every push redeploys. no sidebar, no forty settings pages.

skela.acme.shop
› https://github.com/acme/web13:39youcreated acme/web from github.com/acme/web13:40railpackbuilding main@7be01f313:41skelaweb live → web-acme.203.0.113.7.sslip.io13:52githubpush main@b82d1c4 · redeploying

agents drive it too

a built-in mcp server with scoped tokens: read or full, every project or a few. your extensions' routes are tools as well, and everything lands in one log.

mcp · token agent
› deploy { id: svc_api }13:42agentapi · main@b82d1c4 · build started› rollback { deploymentId: dep_7be01f3 }13:44agentapi back on 7be01f3 · no rebuild› set_extension_projects { porkbun → acme }13:45agentporkbun runs for acme only

deploys that don't break

start-first: a release passes its health check before traffic moves, or the live one keeps serving. rollbacks reuse the image, no rebuild.

api · deploy b82d1c4
13:42skelaapi@b82d1c4 starts beside 7be01f313:42healthGET /health → 503 · waiting13:43healthGET /health → 20013:43traefiktraffic → api@b82d1c413:43dockerremoved api@7be01f3

yours, end to end

skela, its postgres, traefik and your apps run on your server, one box or a swarm. secrets are sealed with a key in /var/lib/skela: back up that folder and one volume, and you have all of it.

root@203.0.113.7
$ ls /var/lib/skelaextensions  vault.key$ ls /var/lib/skela/extensionsnotify  porkbun$ # yours, beside the ones skela ships

// under the prompt

almost everything
is an extension_

skela's core keeps projects, services, deploys and the log. the rest plugs in, and the built-ins use the same sdk you get: replace any of them, limit one to a few projects, or switch it off. drop a folder in your extensions dir and it loads; save a file and it reloads. no restart. pick one below to read its code.

extensions/notifyzsh
$ cat server.tsimport { defineExtension } from "@skela/sdk"import { Effect } from "effect"// a line in the log whenever a deploy goes liveexport default defineExtension({  id: "notify",  setup: (ctx) =>    ctx.hooks.deployment.register({      onStatus: ({ service, deployment, url }) =>        deployment.status === "live"          ? ctx.log(`${service.name} is live → ${url}`)          : Effect.void,    }),})$ # save it18:02extensionreloaded notify@0.1.018:04extensionweb is live → https://acme.shop
extension pointwhat it decidesships with