---
title: "Deploy Flowise · Quick Start"
description: "Visual AI agent builder with Postgres, a volume and a seeded admin"
category: "AI/ML"
url: https://railway.com/deploy/flowise-quick-start
---

# Deploy Flowise · Quick Start

Visual AI agent builder with Postgres, a volume and a seeded admin

**[Deploy Flowise · Quick Start on Railway](https://railway.com/template/flowise-quick-start)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/flowise-quick-start/manifest.json

- **Creator:** withSeismic
- **Category:** AI/ML

## Template content

### flowise

- **Image:** flowiseai/flowise:latest
- **Start command:** `node -e "const cp = require('child_process'), fs = require('fs'), path = require('path'); const env = process.env; const D = env.FLOWISE_DATA_DIR || '/home/node/.flowise'; const root = process.getuid() === 0; const log = (m) => console.log('[railway-bootstrap] ' + m); const own = (p) => { try { const s = fs.lstatSync(p); if (s.uid !== 1000) fs.lchownSync(p, 1000, 1000); if (s.isDirectory()) for (const f of fs.readdirSync(p)) own(path.join(p, f)); } catch (e) { log('chown ' + p + ': ' + e.message); } }; const run = (extra) => cp.spawn('flowise', ['start'], Object.assign({ stdio: 'inherit', env: Object.assign({}, env, { HOME: '/home/node' }, extra) }, root ? { uid: 1000, gid: 1000 } : {})); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); const stop = (ch) => new Promise((res) => { if (ch.exitCode !== null || ch.signalCode !== null) return res(); const t = setTimeout(() => ch.kill('SIGKILL'), 30000); ch.on('exit', () => { clearTimeout(t); res(); }); ch.kill('SIGTERM'); }); const orgCount = async () => { if ((env.DATABASE_TYPE || '') !== 'postgres') return -1; let pg = null; for (const p of ['/usr/local/lib/node_modules/flowise/node_modules/pg', '/usr/src/flowise/node_modules/pg', 'pg']) { try { pg = require(p); break; } catch (e) {} } if (!pg) return -1; const c = new pg.Client({ host: env.DATABASE_HOST, port: Number(env.DATABASE_PORT || 5432), user: env.DATABASE_USER, password: env.DATABASE_PASSWORD, database: env.DATABASE_NAME, ssl: env.DATABASE_SSL === 'true' ? { rejectUnauthorized: false } : false, connectionTimeoutMillis: 15000 }); try { await c.connect(); const r = await c.query('select count(*)::int as n from organization'); return r.rows[0].n; } catch (e) { return e.code === '42P01' ? 0 : -1; } finally { c.end().catch(() => {}); } }; const seed = async () => { const port = env.FLOWISE_BOOTSTRAP_PORT || '3999'; const base = 'http://127.0.0.1:' + port; log('no owner account yet: starting Flowise on 127.0.0.1:' + port + ' to create it before the public port opens'); const ch = run({ PORT: port, HOST: '127.0.0.1' }); try { for (let i = 0; ; i++) { if (ch.exitCode !== null || ch.signalCode !== null) throw new Error('Flowise exited during bootstrap'); if (i > 900) throw new Error('Flowise did not answer /api/v1/ping within 15 minutes'); try { const r = await fetch(base + '/api/v1/ping'); if (r.ok) break; } catch (e) {} await sleep(1000); } const body = JSON.stringify({ user: { name: env.FLOWISE_ADMIN_NAME || 'Admin', email: env.FLOWISE_ADMIN_EMAIL, credential: env.FLOWISE_ADMIN_PASSWORD } }); const r = await fetch(base + '/api/v1/account/register', { method: 'POST', headers: { 'content-type': 'application/json' }, body: body }); const t = await r.text(); if (r.status === 201) log('owner account created for ' + env.FLOWISE_ADMIN_EMAIL); else if (t.indexOf('one organization') >= 0) log('an owner account already exists; leaving it unchanged'); else throw new Error('owner registration failed: HTTP ' + r.status + ' ' + t); } finally { await stop(ch); } }; (async () => { for (const d of [D, path.join(D, 'storage'), path.join(D, 'logs')]) fs.mkdirSync(d, { recursive: true }); if (root) own(D); if (env.FLOWISE_ADMIN_EMAIL && env.FLOWISE_ADMIN_PASSWORD) { const n = await orgCount(); if (n > 0) log('owner account exists; starting Flowise'); else await seed(); } else { log('WARNING: FLOWISE_ADMIN_EMAIL or FLOWISE_ADMIN_PASSWORD is empty, so the first visitor can create the owner account'); } const ch = run({}); for (const s of ['SIGTERM', 'SIGINT']) process.on(s, () => ch.kill(s)); ch.on('exit', (code) => process.exit(code === null ? 1 : code)); })().catch((e) => { log('ERROR: ' + e.message + (e.code === 'EACCES' ? ' (the volume is owned by root: set RAILWAY_RUN_UID=0 on this service)' : '')); process.exit(1); });"`
- **Health check:** /api/v1/ping
- **Public domain:** Yes

### Postgres https://devicons.railway.app/i/postgresql.svg

- **Image:** ghcr.io/railwayapp-templates/postgres-ssl:18

## Documentation

# Deploy and Host Flowise on Railway

Flowise is an open-source visual builder for AI agents, chatbots and LLM workflows. You connect nodes on a canvas (models, prompts, tools, memory, document loaders, vector stores), test the result in the built-in chat, and call every flow over a REST API or an embeddable chat widget. It works with OpenAI, Anthropic, Google, Mistral, Ollama, OpenRouter and many other providers.

## About Hosting Flowise

This template deploys the latest official Flowise image with Railway Postgres and a volume. Flowise 3 no longer uses `FLOWISE_USERNAME`/`FLOWISE_PASSWORD`: on a fresh install, whoever opens the URL first can create the owner account. This template closes that gap:

- **No open first-run setup.** The owner account is created from `FLOWISE_ADMIN_EMAIL` and a generated `FLOWISE_ADMIN_PASSWORD` before Flowise opens its public port. Sign-up attempts after that are refused. If the account can't be created, the service stops instead of starting unprotected.
- **No default password.** The owner password is generated per deploy and shown in the flowise service's Variables tab.
- **Postgres, not SQLite.** Flows, users, API keys, chat history and document store metadata live in Railway Postgres over the private network.
- **Credentials survive redeploys.** `FLOWISE_SECRETKEY_OVERWRITE` (the key that encrypts the API keys you save in Flowise) and the login token secrets are generated variables, so redeploys don't log users out or make saved credentials unreadable.
- **Files on a volume.** Uploads, document store files and logs go to a Railway volume at `/home/node/.flowise`.
- **Healthcheck.** Railway waits for `/api/v1/ping` before sending traffic to a new deployment.

### Getting started

1. Deploy. Optionally change `FLOWISE_ADMIN_EMAIL` first; it is your login name.
2. Wait for the flowise service to turn green. The first boot takes a few minutes because Flowise starts twice: once on a private port to create the owner account, then normally.
3. Open the flowise service's public URL and log in with `FLOWISE_ADMIN_EMAIL` and the `FLOWISE_ADMIN_PASSWORD` value from the Variables tab.
4. Open **Credentials** and add your model provider key (for example an OpenAI API key).
5. Create a Chatflow or Agentflow, or start from one in **Marketplaces**, and test it in the chat panel.
6. To call a flow from your app, create a key under **API Keys**, assign it to the flow, and send `POST /api/v1/prediction/FLOW_ID` with `Authorization: Bearer YOUR_API_KEY`.

## Common Use Cases

- Customer-support and internal chatbots that answer from your own documents (RAG)
- AI agents with tools, MCP servers and human-in-the-loop steps, served as an API
- Embeddable chat widgets for websites
- Prototyping prompts and multi-step LLM pipelines with a team

## Dependencies for Flowise Hosting

- `flowiseai/flowise:latest` (official Flowise image)
- Railway Postgres 18 (`ghcr.io/railwayapp-templates/postgres-ssl:18`) with a volume
- A Railway volume at `/home/node/.flowise` for uploads, document store files and logs

### Deployment Dependencies

- [Flowise documentation](https://docs.flowiseai.com/)
- [Flowise environment variables](https://docs.flowiseai.com/configuration/environment-variables)
- [Flowise on GitHub](https://github.com/FlowiseAI/Flowise)
- [Flowise images on Docker Hub](https://hub.docker.com/r/flowiseai/flowise/tags)

### Implementation Details

Key variables on the flowise service:

| Variable | Value | Why |
|---|---|---|
| `FLOWISE_ADMIN_EMAIL` | `admin@example.com` | Login email of the owner account created on first boot |
| `FLOWISE_ADMIN_PASSWORD` | generated | Owner password, unique to each deploy |
| `FLOWISE_SECRETKEY_OVERWRITE` | generated | Encrypts saved credentials; never change it after the first deploy |
| `JWT_AUTH_TOKEN_SECRET`, `JWT_REFRESH_TOKEN_SECRET`, `EXPRESS_SESSION_SECRET`, `TOKEN_HASH_SECRET` | generated | Login, session and token signing secrets that stay the same across redeploys |
| `DATABASE_TYPE`, `DATABASE_HOST`, ... | `postgres`, `${{Postgres.PGHOST}}`, ... | Private-network Postgres connection |
| `BLOB_STORAGE_PATH`, `LOG_PATH`, `SECRETKEY_PATH` | under `/home/node/.flowise` | Files on the volume |
| `APP_URL` | `https://${{RAILWAY_PUBLIC_DOMAIN}}` | Links Flowise generates point at your domain |
| `RAILWAY_RUN_UID` | `0` | Lets the start command give the volume to the image's `node` user; Flowise itself runs as `node` |

The service's start command is a short Node script that creates the owner account on a loopback-only port when the database has no account yet, then starts Flowise normally. `FLOWISE_ADMIN_EMAIL` and `FLOWISE_ADMIN_PASSWORD` are only read at that point: editing them later does not change an existing login. Change the password from Flowise's account settings instead. Password-reset emails need Flowise's SMTP variables (`SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASSWORD`, `SENDER_EMAIL`).

A flow's prediction endpoint answers anyone who knows the flow ID until you assign an API key to that flow. Assign one before you share or embed it.

The image tracks `latest`, so every new deploy starts on the current Flowise release. To upgrade an existing install, redeploy the flowise service; database migrations run on boot. To hold a version, set the image to a specific [tag](https://hub.docker.com/r/flowiseai/flowise/tags). Flowise uses about 600 to 800 MB of memory at idle. The service runs as a single replica because the volume can only be attached to one.

## Why Deploy Flowise on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying Flowise on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.


## Similar templates

- [Chat Chat](https://railway.com/deploy/-WWW5r) — Chat Chat, your own unified chat and search to AI platform.
- [Weaviate](https://railway.com/deploy/weaviate-1) — Vector database with hybrid search and an API key-protected API
- [Möbius Personal AI OS](https://railway.com/deploy/mobius-v01-personal-ai-os) — Self-hosted AI agent that builds and runs apps for you, with memory.

Open this page in a browser: https://railway.com/deploy/flowise-quick-start
