# Local Installer Agent

FastAPI service that runs on each Linux client and listens on `127.0.0.1:5010`.

It accepts install, update, remove, task, log, installed-app, and service-control requests from `robot.installer`. It stores state in local SQLite and installs trusted `.deb` components downloaded from `robot.package`, allowlisted Ubuntu APT packages, plus Docker image components from allowed registries when Docker support is enabled.

## Development

```bash
cd agent
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --host 127.0.0.1 --port 5010
```

## Install script URL

Client machines should keep using the stable installer command:

```bash
curl -fsSL https://robot.package/install-agent.sh | sudo bash
```

The web server resolves `https://robot.package/packages/agent/latest.deb?arch=<dpkg-arch>`
to the newest uploaded `local-installer-agent_<version>_<arch>.deb`, so updating the Agent does not require editing the install command.

Agent packages are uploaded from the web server Admin page at `/agent`. The default storage folder is
`web-server/uploads/packages/agent`, and it can be changed with `AGENT_PACKAGE_DIR`.

## Important API

```text
GET  /health
GET  /system-info
GET  /apps/installed
POST /apps/install
POST /apps/update
POST /apps/remove
GET  /tasks/{taskId}
GET  /tasks/{taskId}/logs
GET  /tasks/{taskId}/components
POST /services/start
POST /services/stop
POST /services/restart
GET  /services/{serviceName}/status
```

`POST /apps/install` supports both:

```json
{
  "appId": "robot-suite",
  "version": "1.0.0"
}
```

and a direct single `.deb` payload:

```json
{
  "appId": "robot-web-app",
  "appName": "Robot Web App",
  "packageName": "robot-web-app",
  "serviceName": "robot-web-app.service",
  "version": "1.0.0",
  "downloadUrl": "https://robot.package/packages/robot-web-app_1.0.0_amd64.deb",
  "checksum": "sha256_hash_here"
}
```

For manifest mode, the Agent fetches:

```text
{ROBOT_PACKAGE_BASE_URL}/api/apps/{appId}/versions/{version}/manifest
```

Docker image components require Docker Engine on the client machine. By default `AUTO_INSTALL_DOCKER=true`, so the agent will install the trusted distro package `docker.io` with `apt-get` when a Docker app is installed and Docker is missing. Set `AUTO_INSTALL_DOCKER=false` if Docker must be provisioned by your own fleet policy. The agent validates `image` against `ALLOWED_DOCKER_REGISTRIES`, then runs a managed container using the manifest fields `containerName`, `restartPolicy`, `ports`, `volumes`, and `env`.

APT components use a fixed manifest contract and never accept shell commands:

```json
{
  "componentId": "postgresql",
  "type": "apt",
  "packageName": "postgresql",
  "version": "16"
}
```

The package name must be present in `ALLOWED_APT_PACKAGES` (default: `postgresql`). For PostgreSQL, the Agent refreshes the APT index, installs the distro package non-interactively, verifies `postgresql.service`, and waits for `pg_isready` before completing the task.
