# Install

Jatevo is an MIT-licensed team gateway. Run it from the source code, install it on a Mac, or use Docker. The default installation connects to provider APIs without running subscription engines.

## Run from source

Requirements: Git and Node 24 or later. There are no npm dependencies or compilation steps.

```bash
git clone https://github.com/lucacadalora/open-gateway-jatevo.git
cd jatevo
cp .env.example .env
node --env-file-if-exists=.env cli.js init
node --env-file-if-exists=.env server.js
```

Open `http://127.0.0.1:8700/welcome`, create the team owner, and add provider connections in the console. Provider API usage is billed by the provider. Jatevo issues individual team keys in front of those connections.

For contributors, `npm test` runs the test suite and `npm run lint` checks the exported repository. Never commit `.env`, databases, provider credentials or your data directory.

## macOS installer

Requirements: macOS and Node 24 or later. Install Node from [nodejs.org](https://nodejs.org/en/download), then run this from your checkout:

```bash
bash scripts/install-macos.sh
```

The installer runs as your current user, without sudo. It copies the application, initializes persistent data, and loads a login LaunchAgent. It does not copy checkout secrets or modify your shell profile.

| Location | Contents |
| --- | --- |
| `~/Library/Application Support/Jatevo/app` | Installed application code |
| `~/Library/Application Support/Jatevo/data` | Database, generated secrets and provider credentials |
| `~/Library/Application Support/Jatevo/config.env` | Local configuration; preserved on upgrades |
| `~/Library/Application Support/Jatevo/logs` | Service output |
| `~/Library/LaunchAgents/io.jatevo.plist` | Login service |
| `~/.local/bin/jatevo` | Service controls and operator CLI |

```bash
~/.local/bin/jatevo status
~/.local/bin/jatevo restart
~/.local/bin/jatevo stop
~/.local/bin/jatevo start
~/.local/bin/jatevo uninstall
```

Uninstall preserves data, configuration and logs. Run the source installer again after pulling an update to replace only application files. `--dry-run` shows paths; `--no-start` writes and initializes files without loading launchd. `--prefix`, `--bin-dir`, `--launch-agent-dir` and `--node` accept absolute paths. `--port` applies to a new installation; edit `config.env` to change an existing installation's address and restart.

A macOS package can be built with `bash scripts/build-macos-pkg.sh`. It places **Jatevo Setup.app** in Applications; open that app to run the same user installer. The GitHub macOS workflow produces an **unsigned, unnotarized `.pkg` artifact**, and Node remains a prerequisite. This is not a signed release. See [macOS packaging](https://github.com/lucacadalora/open-gateway-jatevo/tree/main/deploy/macos).

The Mac service runs while the user is logged in. For a continuously available team gateway, use a server or dedicated hosting.

## Docker Compose

Requirements: Docker with Compose 2.24.4 or later.

```bash
git clone https://github.com/lucacadalora/open-gateway-jatevo.git
cd jatevo
cp .env.example .env
docker compose up --build -d
```

Initialization is automatic and idempotent. The console uses Docker's named `data` volume mounted at `/data`, rather than host `./data`. It publishes only `127.0.0.1:8700`. You can explicitly initialize without starting the server:

```bash
docker compose run --rm --no-deps console init
```

To expose it to teammates, put a TLS reverse proxy in front of the local port, then set `PUBLIC_BASE=https://your-gateway.example` and `TRUST_PROXY=1` in `.env`. Restart with `docker compose up -d`. Keep direct access to the service behind that trusted proxy. Claim the first owner account locally before exposing a fresh instance.

### Optional subscription engines

The engine override starts pinned codex-lb and CLIProxyAPI images for supported subscription connectors:

```bash
docker compose -f compose.yml -f compose.engines.yml up --build -d
```

A one-shot initializer creates the sidecar configuration and bootstrap credentials before either engine starts. The console shares the sidecar's network namespace so its management endpoint stays loopback-only. Engine API ports are not publicly exposed. The default API-only deployment needs neither engine.

Use the same file selection for every later command, including backup and upgrades. An alternative is to set `COMPOSE_FILE=compose.yml:compose.engines.yml` in your shell. `compose.dev.yml` is an additional development override that exposes engine ports on host loopback for inspection; do not use it for a public deployment.

Moving an existing 0.1.0 subscription installation to this version requires the engine override to keep its engines running. Existing named volumes remain in place. Back up before upgrading.

## Linux systemd

Create an unprivileged service user and put the checkout at `/opt/jatevo`, data at `/var/lib/jatevo` and your private environment file at `/etc/jatevo/console.env`. Set `DATA_DIR=/var/lib/jatevo`, `TEAM_MODE=1` and `ENGINES_ENABLED=0` for API-only operation.

```bash
sudo -u jatevo env DATA_DIR=/var/lib/jatevo node /opt/jatevo/cli.js init
sudo cp deploy/systemd/console.service /etc/systemd/system/jatevo.service
sudo systemctl enable --now jatevo
```

The sample unit assumes Node is at `/usr/bin/node`; update `ExecStart` if your installation differs. The service user needs read access to its environment file and write access to its data directory. The existing sidecar unit is optional.

## Configuration

| Variable | Purpose |
| --- | --- |
| `TEAM_MODE` | `1` enables the team gateway |
| `ENGINES_ENABLED` | `0` for API-only operation; `1` enables subscription engines |
| `PORT`, `LISTEN_HOST` | HTTP bind address; native installations default to loopback |
| `PUBLIC_BASE` | Address members use, including the HTTPS scheme when proxied |
| `DATA_DIR` | Persistent data path; never store only on an ephemeral container filesystem |
| `INVITES` | Enable owner-managed invitations |
| `PUBLIC_CONSOLE` | `0` keeps the sign-in and console links off the public pages; `/signin` and `/app` still answer by URL |
| `EARLY_ACCESS` | `1` puts an Early access button on the public pages and opens `/early-access`, where an invited email redeems its one-time code; needs `INVITES=1` |
| `TRUST_PROXY` | Trust client address headers only behind your own reverse proxy |
| `CODEXLB_URL`, `SIDECAR_URL` | Optional private engine endpoints |
| `HEALTH_ENFORCE` | Optional subscription account health enforcement |
| `HEARTBEAT_ENABLED` | Optional native quota checks; default per-account interval is 15 minutes |

See `.env.example` for the full configuration. All client inference must pass through Jatevo to apply team policies; do not expose a separate reverse-proxy route directly to an engine.
