---
sidebar_position: 2
question: How do I start the full Compose stack on one machine?
kind: task
via_web: na
via_cli: available
via_python: na
via_api: na
via_config: available
ref_cli: abi stack start
ref_config: docker-compose.yml
prereq: A project made by `abi new project`, and [Docker](https://docs.docker.com/get-docker/) with Compose v2 and 8 GB of RAM or more. See [Install and prerequisites](/user-guide/get-started/install).
next:
  - /capabilities/deploy/dokploy
  - /capabilities/deploy/production
  - /capabilities/deploy/add_secrets_to_production
---

# Deploy with Docker

`abi deploy local` writes a Docker Compose stack for your project, and `abi stack start` runs it. It is the way to run the full set of backing services (PostgreSQL, Fuseki, Qdrant, MinIO, Redis) on one machine: a laptop, a workstation, a single server. For a server with a domain and certificates, use [Dokploy](/user-guide/deploy/dokploy) or the [production guide](/user-guide/deploy/production).

`abi new project` already writes the stack, unless you passed `--without-local-deploy`. The stack's `abi` service runs with `ENV=local`, so it reads `config.local.yaml`: PostgreSQL for the document service, Fuseki for the triple store, Qdrant, MinIO and Redis. `config.yaml` is what `abi dev up` reads. See [Configuration](/user-guide/get-started/configuration#environment-files).

## Web UI

Not applicable. Nexus runs inside the stack, so it cannot write or start it. Use the CLI, or run the generated files with Docker Compose (Config).

## CLI

### Write the stack

From the root of the project:

```bash
abi deploy local                        # asks for the base domain: localhost by default
abi deploy local --regenerate           # re-render from the CLI's current templates
```

It writes `docker-compose.yml`, `.deploy/docker/` (Caddy, Postgres init scripts, the NATS broker's `nats.conf`) and the variables the stack needs in `.env`: generated passwords, `NATS_JWT_SECRET`, `NATS_ABI_PASSWORD`, `NATS_MODULE_PASSWORD`, the admin's password (`NEXUS_USER_ADMIN_EXAMPLE_COM_PASSWORD`) and `ABI_API_KEY`.

- A project with a `nats:` block in its config gets the **NATS stack**: a `nats` service the engine waits for, no Dagster, and RabbitMQ only behind the Compose profile `rabbitmq`.
- A project without one keeps the classic stack ([legacy](/user-guide/get-started/legacy-mode): Dagster, RabbitMQ), and `abi deploy local` adds the `naas-abi-core[dagster,rabbitmq]` extras to its `pyproject.toml`: commit the change.
- `--regenerate` backs the previous files up first (`--no-backup` skips it), keeps the values already in `.env`, and never touches `docker-compose.override.yml`, where [remote modules](/user-guide/build/sdk/build-a-remote-module) live. Regenerate after each CLI upgrade.
- Optional extras: `--coding` (Coder, Forgejo and Actions CI workspaces) and `--headscale` (a Headscale service).

### Start it

```bash
abi stack start
```

It writes the broker's passwords and signing secret to `.env` when they are missing, runs `docker compose up -d`, checks for containers that exited or are unhealthy (retrying up to twice, and printing the failing services' logs), then opens the Nexus sign-in page. It does not wait for every service to be ready: the first start pulls the images and builds `abi`, and the engine then loads every module and runs the Nexus migrations. Allow a few minutes.

### Check it

```bash
abi stack status                        # state of each service
abi stack logs abi                      # logs of one service (no argument: all)
abi stack tui                           # a live terminal view
```

`abi start`, `abi stop` and `abi logs` are shortcuts. `abi deploy local-up -d`, `abi deploy local-logs` and `abi deploy local-down [-v]` call `docker compose` with the files passed explicitly.

### Sign in

Open Nexus at `http://localhost:3042` and sign in as `admin@example.com` with the password from `.env`:

```bash
grep NEXUS_USER_ADMIN_EXAMPLE_COM_PASSWORD .env
```

### Stop it

```bash
abi stack stop                          # stop; -v also removes the volumes
```

## Python

Not applicable. There is no Python call that writes or starts the stack. Use the CLI, or Docker Compose (Config).

## REST API

Not applicable. The API runs inside the stack: it cannot start it. Use the CLI, or Docker Compose (Config).

## Config

The stack is plain Docker Compose. Once the files exist, you can edit them and run them with `docker compose` yourself. The first render still needs the CLI: `abi new project` or `abi deploy local`.

### Edit the files you own

| File | What it holds | Rewritten by `--regenerate` |
|---|---|---|
| `config.local.yaml` | The engine's services, modules and secrets for this stack | No |
| `.env` | Generated passwords and keys, and your own secrets | No (values are kept) |
| `docker-compose.override.yml` | Remote module services, and your own changes to any service | No |
| `docker-compose.yml`, `.deploy/docker/` | The services, Caddy, Postgres init, `nats.conf` | Yes |

Put your changes to a service in `docker-compose.override.yml`, not in `docker-compose.yml`:

```yaml title="docker-compose.override.yml"
services:
  abi:
    environment:
      - LOG_LEVEL=INFO
```

### Start the stack

```bash
docker compose up -d
```

Compose reads `docker-compose.yml` and merges `docker-compose.override.yml`, as `abi stack start` does. It does not write missing broker secrets: `abi deploy local` already put them in `.env`.

### Follow it

```bash
docker compose ps
docker compose logs -f abi
```

### Stop it

```bash
docker compose down                     # -v also removes the volumes
```

## Services

| Service | Where |
|---|---|
| Nexus web | http://localhost:3042 (or `nexus.<domain>` through Caddy) |
| API (Swagger at `/docs`) | http://localhost:9879 (or `api.<domain>`) |
| NATS monitoring | http://localhost:8222 (this machine only) |
| Fuseki (SPARQL) | http://localhost:3030 |
| MinIO console | http://localhost:9001 |
| MCP server | http://localhost:8000 (this machine only) |
| Service portal, YasGUI, Redis Commander | http://localhost:8080, 3000, 8082 |

The generated file publishes most of these ports on every interface of the host, for development. On a shared server, firewall them so that only Caddy (80, 443) is reachable. See [Security and compliance](/user-guide/deploy/security-compliance).

## Remote modules

`abi new module <name>` adds a service for the module to `docker-compose.override.yml` and its key to `.env` (`ABI_MODULE_KEY_<NAME>`), so `abi stack start` builds and runs it in its own container, next to the engine. Its agent shows up in Nexus once it logs `READY`.

## Models: Ollama on Linux

A stack that uses [Ollama](https://ollama.com) reaches the host through `host.docker.internal`. On Linux, Ollama listens on `127.0.0.1` only, which the Docker bridge cannot reach: bind it to an address the bridge can reach (`OLLAMA_HOST=0.0.0.0:11434` on a trusted network, or the bridge address and a firewall rule), then restart it. Docker Desktop on macOS needs nothing. To use an Ollama elsewhere, set `ABI_OLLAMA_BASE_URL`.

## Snapshots

```bash
abi stack snapshot create -m "before upgrade"
abi stack snapshot list
abi stack snapshot restore <id>         # destructive; takes a safety snapshot first
abi stack snapshot export <id> backup.tar.gz
abi stack snapshot import backup.tar.gz
abi stack snapshot prune --keep 5
```

A snapshot archives the data volumes (including `nats_data`) and `storage/`. See [High availability](/user-guide/deploy/high-availability#snapshots-of-the-docker-stack).

## Reset

```bash
abi stack stop -v                       # removes the volumes: the data is gone
```

:::tip Password refused after a reset?
If "Incorrect email or password" appears after a reset, read the password again from `.env`: it may have just been rotated.
:::
