Installation
Install a self-hosted Future AGI instance with Docker Compose, as the Standalone setup (the default) or the Distributed setup, using the ./bin/install script.
This page covers installing with Docker Compose. For Kubernetes, see Helm. To pick between them, see Choose a setup.
In this page
Confirm your host meets the requirements first, then ./bin/install does five things:
- Creates
.envfrom.env.example, or on a re-run merges in new keys from.env.examplewithout changing your values. On a fresh install it generates the secrets and records the setup. - Checks the host ports, the Docker VM’s memory, CPUs and architecture, and that Docker can see the checkout.
- Pulls the images (about 800 MB for Standalone), or builds them with
--from-source. - Starts the stack with
docker compose up -d. - Waits until the API (and, in Standalone, the UI) answers, then creates the first account it asked you for. Before it asks, it shows what deployment telemetry sends and how to opt out.
It writes a log of the run to install-YYYYMMDD-HHMMSS.log in the repository root, and exits 1 when the stack came up but the first account could not be created.
Run git clone https://github.com/future-agi/future-agi.git && cd future-agi && ./bin/install, then open http://localhost:3000.
Install
Clone the repository and run the installer
git clone https://github.com/future-agi/future-agi.git
cd future-agi
./bin/installOn Windows, run .\bin\install.ps1 from PowerShell instead. If PowerShell answers that running scripts is disabled on this system, run powershell -ExecutionPolicy Bypass -File .\bin\install.ps1, which lifts the policy for that run only. It is the only script with a PowerShell version: bin/uninstall and bin/dev are bash only.
This installs Standalone: three containers, app (image futureagi/standalone), postgres and clickhouse, plus one per optional profile. For Distributed, one container per service, run ./bin/install --distributed instead. It records COMPOSE_FILE=docker-compose.distributed.yml in .env, so later runs of the installer and plain docker compose commands target Distributed. Distributed runs 31 containers: 22 services and 9 one-shot setup jobs.
Choose before you add data: an install cannot move to another setup with its data. See Switch setups.
You don’t need to edit .env for a local install. Only ./bin/install generates secrets, so let it create the file.
Create your first account
The installer asks for an email, a name and a password, entered twice. Press Enter at the email prompt to skip.
The password must be at least 8 characters, not all digits and not a common password. The installer checks only the length when you type it. A password that breaks another rule is rejected only when the installer creates the account, after the first boot: then create it with create_user as below.
To create the account later, run create_user in the app container. The service is app in Standalone and backend in Distributed:
docker compose exec app python manage.py create_user # Standalone
docker compose exec backend python manage.py create_user # DistributedIt asks for the same three values. Each account it creates owns a new organization, so invite teammates from the app instead. You can also sign up in the UI at http://localhost:3000. To script create_user, and for invites, see Users & sign-in.
Open the app
Open http://localhost:3000. The first boot sets up the databases and takes a few minutes; on a slow or busy host, its migrations alone can take over half an hour. Meanwhile, in Standalone, the page shows Future AGI is starting with the current phase, and the API answers 503 with {"status": "starting", "phase": "..."}.
On a fresh install the app then opens the first-run setup screen, which checks your services before the sign-in screen. It runs once per browser. Sign in with the account you created.
When the installer finishes, it prints these endpoints:
| Endpoint | URL |
|---|---|
| UI | http://localhost:3000 |
| API | http://localhost:8000 |
| Traces (OTLP/HTTP) | http://localhost:4318, on this machine only |
| LLM gateway | http://localhost:8090 |
Installer flags
bin/install and bin\install.ps1 take the same options, except --new-instance, which has no PowerShell equivalent. The installer never moves an install to another setup: --distributed is refused for a project that holds a Standalone install, even with --force.
| Bash | PowerShell | What it does |
|---|---|---|
--distributed | -Distributed | Install Distributed (docker-compose.distributed.yml). Recorded in .env, so later runs keep it |
--from-source | -FromSource | Build the images from this checkout instead of pulling them |
--force | -Force | Continue past a failed preflight check: Docker memory, path visibility, architecture, a local image that is not built yet, or a CH_PASSWORD that differs from the one the running ClickHouse uses. The last one changes ClickHouse’s password: see Secrets the installer generates |
--skip-user-creation | -SkipUserCreation | Skip the first-account prompt; create the account later with create_user |
--no-up | -NoUp | Write .env only, without starting the stack |
--wipe-volumes | -WipeVolumes | Stop this project, delete its volumes and install fresh. Deletes data. The setup stays the same unless you also pass --distributed |
--new-instance | none | Start an isolated copy (futureagi-2, …) instead. Acts only when this project’s volumes exist next to a fresh clone |
--no-telemetry | -NoTelemetry | Turn deployment telemetry off: writes FUTURE_AGI_TELEMETRY_DISABLED=true to .env before anything starts |
-y, --non-interactive | -NonInteractive | Run without prompts. Creates the first account from FAGI_ADMIN_EMAIL, FAGI_ADMIN_NAME and FAGI_ADMIN_PASSWORD when all three are set, and skips it otherwise |
-h, --help | Get-Help .\bin\install.ps1 -Detailed | Print the usage |
Note
Apple Silicon and arm64 hosts. Every Future AGI image is published for linux/arm64 as well as linux/amd64, so the stack runs native. Only the -gpu model-serving tags and Distributed’s voice simulation runner are linux/amd64 only. Platform compatibility has the details, including the linux/amd64-only backend image of releases before Standalone became the default.
Install without the script
The installer is a convenience wrapper, not a requirement. To run the stack by hand:
cp .env.example .env
docker compose up -d # Standalone
For Distributed, uncomment COMPOSE_FILE=docker-compose.distributed.yml in .env first, or pass -f docker-compose.distributed.yml to every command.
Warning
Only ./bin/install generates secrets. When you copy .env by hand, the stack runs on defaults that are published in the repository, and MINIO_ROOT_PASSWORD even arrives as the placeholder CHANGEME-set-by-bin-install. That is fine on a laptop, not on anything other people can reach: set the keys listed in Secrets the installer generates before the first docker compose up.
If you run ./bin/install on such an install later and it reports existing volumes next to the CHANGEME-* placeholders, choose k (keep): the data was set up with the values this .env holds, placeholders included, so it already matches. w (wipe) deletes all data.
Then create the first account:
docker compose exec app python manage.py create_user # Distributed: backend
Verify the stack
Check that every container is up before you sign in:
docker compose ps # every container should read "running" or "healthy"
docker compose logs -f app # Distributed: docker compose logs -f backend
curl http://localhost:8000/health/
In Standalone, docker compose logs -f app starts with a summary of the configuration: setup, version, URLs, LLM providers by name, email, telemetry, the code-eval sandbox and model serving. It never prints secret values. It ends with Future AGI is ready in ....
The instance is ready when /health/ returns OK. That’s the same check ./bin/install polls while it waits for the API. Troubleshooting covers anything that stays red.
Everyday operations
| To… | Run |
|---|---|
| Stop, keeping the data | docker compose down (or ./bin/uninstall) |
| Start again | docker compose up -d |
| Delete all data | ./bin/uninstall --wipe-data (or docker compose down -v) |
Remove the install: containers, volumes, .env and the Future AGI images it uses | ./bin/uninstall --purge |
Data lives in named Docker volumes and survives restarts and upgrades. bin/uninstall reads the setup and project name from .env, so the same commands work for both setups. Images built by --from-source are shared by every checkout on the machine, so --purge asks about them separately, and -y keeps them.
# Follow the logs
docker compose logs -f app # Distributed: docker compose logs -f backend worker
# Shell into a container
docker compose exec app bash # Distributed: docker compose exec backend bash
docker compose exec postgres psql -U futureagi -d futureagi
# Upgrade to the latest release: back up first, then
git pull && ./bin/install
Take a backup before you upgrade: migrations run on start, and a rollback does not reverse them. The full procedure, pinning and rollback are in Upgrades & rollback. On an install made before Standalone became the default, run ./bin/install after git pull, not a plain docker compose up -d, which would start the wrong stack: see Upgrading older installs.
To reset a password without email, see Reset a password.
Switch setups
There is no supported way to move an install, data included, from one setup to another. That includes growing Standalone into Distributed or Helm: the only way is a fresh install, so if you expect to outgrow one host, start on Distributed or Helm.
The installer never switches an install that has data. A re-run keeps the setup .env records, and --distributed stops with an error for a project that holds a Standalone install. An install made before Standalone became the default is kept on Distributed; see Upgrading older installs.
To switch, back up what you need, then start fresh:
# Standalone to Distributed
./bin/uninstall --wipe-data
./bin/install --distributed
# Distributed to Standalone
./bin/uninstall --wipe-data
# delete the COMPOSE_FILE= line from .env
./bin/install
--wipe-data keeps .env, so the new install reuses its secrets. To try the other setup without touching this one, run it as a separate project: a second checkout with another COMPOSE_PROJECT_NAME and other ports in its .env.
To move to Kubernetes, install the chart (see Helm), then remove the Compose install with ./bin/uninstall --wipe-data. The chart does not read .env: carry what you need over in the chart’s values.
Other ways to run it
| Mode | Command | Use it for |
|---|---|---|
| Distributed | ./bin/install --distributed | One container per service on one Docker host, for higher volume |
| Helm (Kubernetes) | See Helm | Running the Distributed setup on a Kubernetes cluster |
| Development | ./bin/dev | Contributing to Future AGI: Standalone with hot reload. Use ./bin/dev --distributed only for changes that need the Distributed stack. See Local development |
| Install a branch from source | git checkout dev, then ./bin/install --from-source | Running a branch other than main: the published images are built from main. The build wants an 8 GB Docker VM |
| Frontend only | VITE_HOST_API=https://api.example.com docker compose -f docker-compose.frontend.yml up -d | Pointing a local UI at a backend that runs elsewhere |
Warning
For a frontend-only deploy, set VITE_HOST_API in .env to the backend URL the browser can reach. The container takes it when it is created, so after a change run docker compose -f docker-compose.frontend.yml up -d again, which recreates it; no rebuild is needed. docker compose restart keeps the old value.
Dive deeper
Questions & Discussion