Installation
This page is about installing the control plane itself, the one piece of Flow you actually run a setup command for. Everything else, adding servers to deploy onto, connecting a Git provider, creating your first project, happens inside the dashboard afterward, not from the command line. So this is a short but important page: get through it once and you shouldn't need to touch a terminal on your Flow server again.
What you need first
A server with Docker and the Docker Compose plugin installed. That's genuinely it. Flow ships as a Docker image with everything it needs baked in, including the Go binaries for the node agent, so you don't need Node.js, Go, Postgres, or Redis installed on the host yourself, Docker Compose brings up Postgres and Redis as containers alongside Flow.
Any small VPS is enough to start, a single core with a couple of gigabytes of memory runs the control plane comfortably. You can run your bots and sites on that same box later, or add other servers as nodes once Flow is up, whichever you prefer.
If you don't already have Docker installed, the quickest way on most Linux distributions is Docker's own convenience script:
curl -fsSL https://get.docker.com | shThat installs both Docker and the Compose plugin together. Confirm it worked with docker compose version, if that prints a version number instead of an error, you're ready for the next step.
Installing Flow
git clone https://github.com/Noahtarp/flow.git
cd flow
./scripts/install.shThat's the whole install. Here's what actually happens when you run it, so it doesn't feel like a black box:
- It checks that Docker and the Compose plugin are actually there, and stops with a clear message if either is missing rather than failing halfway through.
- If there's no
.envfile yet, it generates one for you: a random Postgres password, a random encryption key (used to encrypt secrets and env vars at rest), a random token shared between the web service and its agent, and a default port. If you run the script again later, it leaves an existing.envalone rather than overwriting your secrets. - It runs
docker compose -f docker-compose.prod.yml --env-file .env up -d --build, which builds the Flow image and starts four containers: Postgres, Redis, the web service, and an agent, wired to the web service with a shared node token. - The moment the web container starts, it runs any database migrations that haven't been applied yet, automatically, before the server starts accepting requests. You never run a migrate command yourself, on this install or on any future upgrade.
- That agent container mounts the host's Docker socket and registers itself as a node the moment it starts. The server you just installed Flow on is already a working node before you've even created your account, there's no separate setup step for it.
First builds take a few minutes since Docker is compiling the Go agent and building the Next.js app from scratch. Watch it happen live with:
docker compose -f docker-compose.prod.yml logs -f webCreating your account
Once the web container is healthy, open http://<your-server>:3000/signup in a browser. This page only ever works once: the very first account created there becomes the instance's owner, and every signup attempt after that redirects straight to /login instead. There's no open registration, which is exactly what you want on something that manages your infrastructure. If you ever need to add more people afterward, that's a Team invite, not another signup, see Team and permissions.
The environment variables involved
Everything the production compose file needs lives in one small .env file at the repo root:
POSTGRES_PASSWORD: the password for Flow's own Postgres container. Only Flow talks to this database, so a generated random value is fine and preferable, you never need to type it in yourself.APP_ENCRYPTION_KEY: used to encrypt things like Git provider tokens and every environment variable you save on a project or service. Treat it like a master password. If you lose it, Flow can no longer decrypt anything that was encrypted with it, there is deliberately no recovery mechanism, so keep a backup of your.envfile somewhere safe.NODE_TOKEN: shared between the web service and the bundled agent container so the agent can authenticate itself as a node the moment it starts. You'll never type this in anywhere yourself either, it's purely how those two containers recognize each other.APP_URL: the public URL this instance is reached at, e.g.https://flow.example.com. Recommended once you put a domain in front of Flow (see below), since without it Flow falls back to whateverHostheader the incoming request carries for things like node-bootstrap and webhook URLs, which is only safe if this instance isn't directly reachable by untrusted clients.FLOW_LICENSE_API_URL: optional, only relevant if you're using Premium features. Leave it unset and this instance behaves exactly like one that never touches billing, see Premium and billing.WEB_PORT: which host port the dashboard is published on,3000by default. Change this if something else on the server already uses that port.
If you'd rather set these yourself instead of letting the script generate them, copy .env.prod.example to .env, fill in the blank values, and run the same compose command directly:
cp .env.prod.example .env
docker compose -f docker-compose.prod.yml up -d --buildPutting a domain in front of it
The install itself doesn't set up a public domain or TLS certificate for the dashboard, it just publishes the web container on the port you chose. That's intentional: how you expose your own control plane is up to you. The straightforward option is pointing a domain's DNS at the server and putting a reverse proxy like Caddy or Traefik in front of port 3000, which gets you a certificate with a couple of lines of config. You can also just access it over http://server-ip:3000 while you're trying Flow out, and add a domain later. Note this is only about reaching the dashboard itself, Flow configures routing and TLS automatically for whatever you deploy through it, see Architecture.
Updating Flow
Pull the latest code and run the install script again, it's the same command whether this is your first run or your fiftieth:
cd flow
git pull --ff-only
./scripts/install.shYour existing .env is left alone, the image rebuilds with whatever changed, and any new database migrations run automatically as the web container starts back up. Your Postgres and Redis data live in named Docker volumes, so they survive the rebuild untouched.
Backing up your data
Everything that matters, your projects, services, deploy history, encrypted secrets, lives in the Postgres volume. A simple, reliable backup is a periodic pg_dump from inside the container:
docker compose -f docker-compose.prod.yml exec postgres \
pg_dump -U flow flow > flow-backup-$(date +%F).sqlKeep a copy of your .env file alongside those backups. A database backup without the matching APP_ENCRYPTION_KEY is not very useful, since every secret in it was encrypted with that key.
If something goes wrong
- Port already in use: something else on the server is already listening on
3000. SetWEB_PORTin.envto something free and re-run the script. - Permission denied talking to Docker: your user isn't in the
dockergroup. Either run the install script withsudo, or add yourself to the group (sudo usermod -aG docker $USER) and log back in. - The web container keeps restarting: check its logs with the command from earlier in this page. The most common cause is Postgres or Redis not being marked healthy yet when the web container starts, compose is set up to wait for both, but a very slow or resource-starved server can still occasionally hit this. Give it a minute and it typically recovers on its own.
- You lost your
.envfile: there is no way to recover encrypted secrets without the originalAPP_ENCRYPTION_KEY. You'll need to reconnect Git providers and re-enter environment variables after generating a fresh one. This is the whole reason the backup section above exists.
Where to go from here
Installing Flow only ever needs to happen once, and the server you just installed it on is already a working node, so you can create a project and deploy to it right away without adding anything else. If you later want to spread services across more servers, that doesn't need this installer either, it's a few clicks inside the dashboard, see Adding a node. If you'd rather start with what you can actually build, jump to Projects and services.