# Installation Problems

> Applies to: ChengOS v0.1.0+ ｜ Last verified: 2026-08-12 ｜ Source: `deploy/chengos.sh`, `deploy/.env.example`, `chengflow/docs/release-operations-guide.md`

Almost every failed ChengOS install is one of four things: a port already in use, a database
that will not connect, a placeholder secret left unchanged, or a path that means different things
to two processes. Work through the triage below before reading further.

## Triage

```bash
./chengos.sh status                      # processes, ports, version, health
curl http://127.0.0.1:19225/health        # is the API alive?
tail -n 100 deploy/logs/cheng-api.log    # why not?
```

`status` plus the API log identify the cause in most cases. Read the log from the **top** of the
startup attempt, not the bottom — the first error is the cause and everything after it is
consequence.

## The API will not start

### Port already in use

```bash
ss -tlnp | grep -E '19225|8080|5055|5432|6379|6333'
```

Either stop the conflicting process or change the port in `deploy/.env` (`PORT`/`API_PORT`,
`UI_PORT`, `APP_PORT`). Remember that `PORT` and `API_PORT` both exist and should agree.

### Database connection refused

```bash
pg_isready -h 127.0.0.1 -p 5432
```

Check in this order:

1. Are the databases running? `./chengos.sh status` reports them.
2. Does `DATABASE_URL` use the right **hostname for your mode**? `127.0.0.1` for native and
   `managed-process`; `postgres` / `redis` / `qdrant` for Docker; your own host for distributed.
   This one mistake accounts for most "works natively, fails in Docker" reports.
3. Does the password inside `DATABASE_URL` match `POSTGRES_PASSWORD`? They are separate variables
   and they must agree.
4. Do the discrete `DB_HOST` / `DB_PORT` / `DB_NAME` / `DB_USER` / `DB_PASSWORD` values agree with
   `DATABASE_URL`? Agent memory nodes read those instead of the URL, so a mismatch produces a
   system that starts fine and then fails only when a memory node runs.

### Placeholder secrets

An install that still has template values will not work correctly:

```bash
grep -E 'replace_with|change_this' deploy/.env
```

Generate real values:

```bash
openssl rand -hex 32   # CREDENTIAL_MASTER_KEY_1, JWT_SECRET
openssl rand -hex 16   # POSTGRES_PASSWORD, REDIS_PASSWORD
```

Changing `CREDENTIAL_MASTER_KEY_1` after credentials exist makes those credentials
**unreadable** — set it before you store anything, and treat it as unrecoverable afterwards.

### Migrations did not run

`RUN_MIGRATIONS=true` applies migrations at startup. If the schema looks empty, confirm it is set
and, importantly, that `CHENG_DEMO_MODE` is **not** `true` — demo mode ignores `RUN_MIGRATIONS`
entirely. A demo-mode install on a fresh database therefore has no schema and no way to create
one, which is why demo mode must always be enabled *after* a normal initialization.

## The UI loads but nothing works

The browser reaching the UI does not mean the UI can reach the API.

Open the browser console and network tab. Failing `/api/v1/*` requests point at:

- **CORS.** In production set `CORS_PERMISSIVE=false` and list real origins in
  `CORS_ALLOWED_ORIGINS`. A blocked request shows as a CORS error, not a 4xx.
- **Wrong API URL.** Check `UI_API_BASE_URL` and `UI_WS_URL` — normally `/api/v1` and `/ws`
  behind one reverse proxy.
- **`BIND_ADDRESS` inside Docker.** It must be `0.0.0.0`. Setting it to `127.0.0.1` inside the API
  container means the UI container cannot reach it — isolation comes from the host port binding,
  not from the bind address.
- **WebSocket not proxied.** Reverse proxies need explicit upgrade handling; REST working while
  live updates never arrive is the signature of this.

## First-run setup problems

On a fresh database, `GET /api/v1/auth/bootstrap-status` returns `needsSetup: true` and the UI
sends you to setup. If it does not:

- `needsSetup: false` on a database you believe is empty means you are pointed at a **different
  database** than you think.
- Registration refused means the deployment's registration policy or user limit applies.
- If demo mode is on, setup writes are blocked. Disable it, initialize, then re-enable.

## CLI cannot connect

| Symptom | Cause |
|---|---|
| Connection refused | Wrong `CHENG_SERVER_URL`, or the API is not running |
| `401` | Missing or wrong token — prefer `CHENG_TOKEN` |
| "CLI sessions unavailable" | **`CHENG_CLI_ALLOWED_ROOTS` is not set on the server.** CLI sessions are disabled entirely without it |
| Sandbox appears empty or missing | The CLI and API do not see that path in the same filesystem namespace — common with Docker |

Remember the CLI's precedence order — flags, then environment, then config file, then defaults. A
stale `~/.config/cheng/config.json` silently overriding your intent is a common surprise.

## Docker-specific

```bash
docker compose ps
docker compose logs api --tail=100
```

| Symptom | Cause |
|---|---|
| Container restart loop | Read the logs; usually database connection or a missing secret |
| API cannot reach the database | `DATABASE_URL` uses `127.0.0.1` instead of `postgres` |
| UI cannot reach the API | `BIND_ADDRESS` is not `0.0.0.0` inside the container |
| Images from different releases | A `CHENGOS_<SERVICE>_IMAGE` override is set; remove it and pin `CHENGOS_VERSION` |
| Update refuses to run | An override is set, which disables coordinated updates. `status` says so |

## Update and rollback failures

| Symptom | Action |
|---|---|
| Update failed, service down | The updater already restored the previous package. `./chengos.sh start`, then check `logs/cheng-api.log` |
| Automatic restore also failed | The backup is intact in `.chengos_backups/<version>-<timestamp>/`. Copy `shared/*` over the install root and `hybrid/*` over `hybrid/`, then start |
| Running version differs from the record | The package was replaced by hand. `./chengos.sh update --force` |
| `latest version unavailable` | Network or rate limit. **Not** a claim of being up to date — retry, or update offline with a local tarball |
| Rollback refused | The release declares an irreversible migration. Follow the manual recovery procedure in [upgrades and rollback](/docs/deploy-upgrade-rollback) |

## Missing optional features

Some things are absent by configuration, not broken:

| Missing | Enable with |
|---|---|
| Agent memory | `ENABLE_REDIS=true` and a working `REDIS_URL` |
| RAG / vector retrieval | `ENABLE_QDRANT=true` and a working `QDRANT_URL` |
| `/schedules` returns 404 | No scheduler configured — `SCHEDULER_ENABLED=true` |
| `/mcp/servers` returns 404 | MCP state unavailable — `MCP_ENABLED=true` |
| Password reset email | `EMAIL_ENABLED=true` plus SMTP settings |
| Python or JS code nodes | `CHENG_ENABLE_CODE_PYTHON` / `CHENG_ENABLE_CODE_JS` |
| Local model endpoint refused | `ALLOW_PRIVATE_LLM_ENDPOINTS=true` |

## Verifying a release archive

```bash
./scripts/verify-release-archive.sh --archive PATH --expect-version 1.2.0
./scripts/check-release-consistency.sh --tag v1.2.0
```

## Next steps

- [Execution failures](/docs/fix-execution-failures) — when the install is fine but a run is not.
- [Environment variable reference](/docs/config-env-reference) — every setting named above.
- [Upgrades and rollback](/docs/deploy-upgrade-rollback) — update mechanics.
