Deploy services
Run a project's code on your server: a website or an API, a Discord or Telegram bot, a nightly job, or a static site. Stavo builds it, starts it, keeps it running and keeps the last few releases so you can go back.
Turn it on (admins)
- Set up the developer platform first (server README, "Developer platform"): the platform sidecar is the one part of Stavo that talks to Docker.
- Rebuild the sidecar from this version and add the
apps-ingressnetwork (server README, "Deployed services"). Web apps are reached only through it, and only by the server. - Open Admin > Features and turn on Deployed services for everyone or selected people (it needs Projects).
- Set limits in Admin > Deployed services: services per person, memory and CPUs, builds, how many releases to keep.
# next to what you already have for the platform sidecar
networks:
apps-ingress:
name: stavo-apps-ingress
internal: true
labels:
stavo.platform.ingress: stavo
ipam:
config:
- subnet: 10.251.9.0/24Four kinds of service
- Web app: anything that answers HTTP, like an API, a Next.js site or a dashboard. It gets an address on your server.
- Worker: always on, no address. Discord and Telegram bots, queue workers, listeners.
- Cron job: runs on a schedule (cron syntax, in UTC), does its work and stops. Run it by hand any time.
- Static site: HTML, CSS and JavaScript, built with Vite (or anything else) or published as they are. Nothing keeps running.
Make one
Open the Developer app and click New service. Start from a template (Discord bot, Telegram bot, Hono or Express API, Next.js, Vite site, Python FastAPI, Go, a cron script or a plain site) and Stavowrites its files into your project and deploys it. Or start from your own code: a folder of a project, a Git repository on Forgejo, Gitea, GitHub or GitLab, or your computer with the stavo CLI.
It finds out how to build and run your code from what's in the folder: bun.lock means Bun,package.json means Node.js (npm, pnpm or yarn by lockfile), requirements.txt orpyproject.toml means Python, go.mod means Go, and an index.html alone is a static site. Change any command in the service's settings, or in a stavo.toml next to your code:
[service]
name = "shop-api"
type = "web"
install = "npm ci"
build = "npm run build"
start = "node dist/server.js"
port = 8080Addresses
A web app or static site lives at https://your-server/apps/<name>/. Your app gets that path as APP_BASE_PATH and should serve under it; the templates already do (Next.js uses it asbasePath, Vite as base). It also gets PORT to listen on (bind0.0.0.0) and APP_URL.
Pages under your server's own address run in a browser sandbox, so an app can never act as someone signed in toStavo: they can't read or set cookies from scripts or use local storage. For the full browser, give the service its own domain: in its Domain tab, add app.example.com and point a CNAME at your server. Deploy once more and the app is built for the root of that domain.
Deploys, rollbacks and logs
- Deploy builds a new release and switches without downtime: the new one starts next to the old one, has to pass its health check, then takes the traffic. If it doesn't, the old one keeps serving and the deploy says why.
- Bots switch the other way round (the old one stops first, so a bot never answers twice) and the old one comes back if the new one doesn't stay up.
- The build log streams live, in the Developer app, in Code (the Deploy button in the title bar) and in your terminal.
- Roll back to any kept release in seconds, no rebuild.
- Logs: follow, search and download. Metrics: CPU, memory, restarts, requests and response times.
- A crashed app is restarted with a growing delay, and you get a notification.
Environment, secrets and databases
Set variables and secrets per service (and per project, shared by all of its services). Secrets are encrypted and never shown again. Link a managed database and the app gets its connection string asDATABASE_URL (or a name you pick); it reaches the database on the database's own private network. Changes restart the app with them.
The network
Every service runs in its own locked down container: no special permissions, a read-only system, memory and CPU limits. Services can reach the internet (bots need to) but not your local network, the computer Stavoruns on, other containers or Stavo itself. That works on Docker Desktop for Mac too. Turn internet off for a service that doesn't need it. One honest limit: a public address that leads back into your home network (like your router's public IP) is as reachable as it is from anywhere on the internet.
Builds use pinned Node.js, Bun, Python and Go images and run behind the same walls. Your own Dockerfiles aren't supported yet: a Docker build's steps run where those walls can't reach.