Apps
An app belongs to a project environment and runs as a container on one of the team's nodes. Each
deploy makes a release; the last five builds are kept for rollbacks. See also:
the apps service.
Kinds
| Kind |
For |
Gets |
web |
HTTP services |
an address, a port, an optional health path |
worker |
queues, long-polling bots, anything without HTTP |
nothing public |
bot |
Telegram bots with webhooks |
https://bots.xvii.network/<app>, the webhook set for you |
cron |
scheduled jobs |
one-off runs on a schedule, output kept 30 days |
| database |
PostgreSQL, MariaDB, Valkey, Redis, MongoDB |
see Databases |
xvii apps create api --project shop --port 3000 --health /healthz
xvii apps create worker --project shop --kind worker
xvii apps create cleanup --project shop --kind cron --schedule "0 3 * * *"
Deploy
xvii apps deploy api --project shop --dir .
xvii apps deploy api --dir . --dockerfile docker/api.Dockerfile
The folder (files git doesn't ignore, up to 512 MB) is built on the node that runs the app, with its
Dockerfile or with Railpack. There is no registry in between, and one build runs at a time per node.
xvii apps deploy api --image ghcr.io/acme/api:1.3
Private images need a registry sign-in, see below.
xvii apps import --compose docker-compose.yml --project legacy --deploy
Services become apps, database services become managed databases that keep their passwords, named
volumes stay volumes.
A deploy starts the new container beside the live one and switches traffic once it is healthy. A release
has five minutes to come up (fifteen for an app's first one); if it fails, the app stays on its last live
release. Install production dependencies in the final image: a successful build doesn't mean the runtime
stage has everything it needs.
xvii apps rollback api # the release before
xvii apps rollback api 12 # release #12 again
xvii apps stop worker
xvii apps start worker
Health checks
For web apps, the node's agent requests the health path over the team network with the app's Host
header. Keep it cheap, independent of sign-in and of slow dependencies: a health check that fails during
a database migration rolls the deploy back.
Variables and files
An app gets the variables of its environment's set in env, resolved at deploy time, plus
its own:
- plain variables and sealed secrets on the app itself (names only in the panel);
- files from env, mounted read-only under
/run/xvii/files;
PORT for web apps, unless env sets it.
A change to variables applies on the next deploy.
Addresses
Production apps answer at https://<app>.apps.xvii.network, other environments at
https://<app>-<env>.apps.xvii.network (the project's slug is added when a name is taken). Attach your own
names in domains.
Logs and metrics
xvii apps logs api -n 50
xvii apps logs api -f --since 10m
The panel shows CPU, memory and restarts per minute for 30 days. A live container that restarts sends
app.crashed to notify.
Previews
xvii apps deploy web --dir . --preview mr-12 --ttl 7d
xvii apps previews web
xvii apps previews web --rm mr-12
A preview is a copy of the app with its own address, https://<app>-<name>.apps.xvii.network, in the
project's preview environment. It goes away after its TTL without deploys (7 days by default, up to 30).
Bots have no previews: they would share a token.
Bots
A bot app receives Telegram updates at https://bots.xvii.network/<app id>. When a release goes live,
apps calls setWebhook with BOT_TOKEN from env and a secret of its own, checks the secret on every
update and passes it to the bot's port. The bot gets PORT, WEBHOOK_SECRET and WEBHOOK_URL.
Cron
A cron app runs its release's image as a one-off container on schedule (five fields in UTC, or
@hourly, @daily). One run at a time, an hour's timeout by default; output, exit code and errors are
kept for 30 days; a failed run sends cron.failed. Run now is in the panel.
Volumes
An app can have named volumes. A volume keeps the app on its node, and its deploys stop the old
container before starting the new one (two containers can't share it safely).
Private registries
echo "$GHCR_TOKEN" | xvii apps registries --team acme --add ghcr.io --user acme-bot
xvii apps registries --team acme
xvii apps registries --team acme --rm ghcr.io
A read-only token is enough (GitHub read:packages, GitLab read_registry). Passwords are sealed and
never come back from the API; nodes use a temporary Docker config for each pull.
Templates
xvii apps templates
xvii apps install umami --project site --name stats
About fifty-five templates (n8n, Gitea, Forgejo, WordPress, Nextcloud, Directus, NocoDB, Baserow, Grafana,
Mattermost, Open WebUI, Keycloak, Paperless-ngx, Jellyfin…), each pinned to a real image tag. Installing
one creates its databases and apps; a first sign-in, when the application has one, is shown once.
Move to another node
xvii apps move fra1 --project shop --env production
Images are copied while the environment runs; then it stops, its volumes are copied, it starts on the new
node and is checked. If anything fails it starts again where it was; the source data is never touched.
Expect a minute or two of downtime. It needs an admin of the team, and the destination must fit the team's
quota.
Limits and events
Limits apps.apps, apps.memory, apps.cpu, apps.nodes. Events app.deployed, app.deploy_failed,
app.crashed, cron.failed, bot.webhook_failed, node.offline and more (Events).