Agent (gisila-agent)
gisila-agent is a single compiled Dart binary at
/usr/local/bin/gisila-agent. It’s the only part of the panel that changes
the host. The worker (root) calls it for each step of a job. The API server
calls it without privileges only to read logs (logs), resource usage
(stat) and its version.
You normally never run it yourself. This page helps you read build logs and worker output, and debug a node.
Conventions
Section titled “Conventions”- Every subcommand is idempotent: re-running it converges on the same state.
- Arguments are validated before anything runs.
--usermust look likeapp_<id>,--work-dirmust be under the apps root, and git URLs, refs, versions, hostnames, runtimes and source types are checked against strict patterns. Commands reject|,&,;,$,<,>, backticks and control characters. Env var names must be identifiers. - Each run ends with one JSON status line on stdout:
{"ok": true, "command": "…", …}or{"ok": false, "command": "…", "error": "…"}. A few subcommands print their own JSON result instead (runtime,app-health,firewall,stat,version). - The agent is started with an allowlisted environment, so the panel’s
secrets in
/etc/gisila/.envnever reach builds or app processes.
Deployment subcommands
Section titled “Deployment subcommands”| Subcommand | Key options | Does |
|---|---|---|
provision |
--app-id --user --work-dir [--port] |
Creates the Linux user and the work-dir layout (current, releases, shared, tmp, logs, .env). |
build |
--app-id --user --work-dir --runtime --source-type [--git-url --git-branch --source-subdir --deploy-key-path --artifact-path --build-command --deploy-mode --<runtime>-version --env-json --no-cache --release-id --keep-release-ids] |
Fetches the source (git clone, unzip or binary install) and runs the runtime plugin’s build as the app’s user. Publishes releases/<id> and prunes releases outside --keep-release-ids. |
apply-unit |
--app-id --user --work-dir [--port] --runtime [--start-command --source-subdir --memory-mb --cpu-quota --tasks-max --env-json --expose-mode], plus Python, Gunicorn and Celery options |
Writes the env file, AppArmor profile and systemd unit(s), resolves the start command to an absolute path, and reloads systemd. |
apply-vhost |
--app-id --port [--hostname …] [--runtime --static-root --static-spa --media-root --protected-media --max-upload-mb] |
Renders the Nginx vhost, runs nginx -t and reloads. |
activate-release |
--work-dir --user --runtime --release-id |
Rollback: points the app back at a kept release and restores its executable, toolchain link and virtualenv. No fetch or build. |
restart, start, stop |
--user [--runtime] |
systemctl on the app’s unit(s). |
app-health |
--user --runtime [--port --health-path --expose-mode --timeout-sec (45) --settle-sec (5)] |
Post-restart readiness check. Prints {"healthy", "detail", "units", "logTail"}. |
expose-port, unexpose-port |
--port |
ufw allow / ufw delete allow <port>/tcp for tcp apps. Never closes an SSH port. |
issue-cert |
--hostname |
certbot --nginx -d <hostname>, then reloads Nginx. |
uninstall |
--user [--app-id --runtime --work-dir --hostname] |
Stops and disables the units, removes the unit, profile and vhost. |
Operations subcommands
Section titled “Operations subcommands”| Subcommand | Does |
|---|---|
logs --user [--work-dir --lines --runtime --follow] |
Reads the app’s journal (needs only the systemd-journal group). |
stat --user [--runtime] | --unit UNIT |
Resource usage as JSON. For Celery, sums every unit of the app. |
exec --user --work-dir --command [--runtime --timeout] |
Runs a console or cron command as the app’s user, with its env and toolchain. |
runtime install|remove|status --key RT [--version V] |
Manages runtime toolchains. status reports the versions actually on disk. Versioned runtimes require --version. |
service install|configure|start|stop|uninstall --type T [--config JSON] |
Managed services (Redis, Memcached, Mailpit, PgBouncer, pgAdmin, mongo-express, …). |
postgres <action> … |
Install, start, stop and uninstall clusters, create and drop databases, alter roles, configure settings, back up and restore. |
mongo <action> … |
The same for MongoDB. |
storage <action> … |
Install and manage Garage, create buckets and scoped keys. |
mail setup, mail sync --domains JSON --accounts JSON |
Installs Postfix, Dovecot and OpenDKIM, then syncs domains, DKIM keys and mailboxes. |
firewall status | apply --change-id N --op add|delete|enable|disable [--rule JSON --keep-ip IP --protect-port N --confirm-within S] | confirm --change-id N | rollback --change-id N |
ufw changes with a snapshot and an independent rollback timer. Refuses changes that would cut off SSH, 80, 443 or the requester. |
version |
Prints {"version", "commit", "builtAt"}. |
Runtime plugins
Section titled “Runtime plugins”Each runtime is a plugin registered in the agent. It owns its toolchain install and removal and its build step:
| Key | Mode | Versioned | Toolchain location |
|---|---|---|---|
dart |
build_execute |
yes | per-version SDK under /opt |
go |
build_execute |
yes | per-version prefix |
rust |
build_execute |
yes | rustup |
node |
build_execute |
yes | fnm |
bun |
build_execute |
yes | per-version prefix |
python |
direct_run |
yes | pyenv |
celery |
build_execute |
uses the app’s Python | |
zig |
build_execute |
no | |
binary |
direct_run |
no | none |
static |
static_publish |
no | none |
Debugging with the agent
Section titled “Debugging with the agent”The commands the worker ran appear in each deployment’s build log. To reproduce one by hand, run it as root with the same arguments:
sudo gisila-agent app-health --user app_ab12cd --runtime dart --port 4001 --health-path /healthzsudo gisila-agent logs --user app_ab12cd --lines 100gisila-agent versionRunning provision, build or apply-unit by hand changes the app outside
the panel’s records. Prefer redeploying from the panel.