create-flowdular 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/agent-template/.agents/skills/agent-tool-design/SKILL.md +1 -1
- package/agent-template/.agents/skills/auth-security-review/SKILL.md +1 -1
- package/agent-template/.agents/skills/database-adapter/SKILL.md +5 -5
- package/agent-template/.agents/skills/database-adapter/references/first-run-and-matrix.md +2 -2
- package/agent-template/.agents/skills/deploy-operate/SKILL.md +1 -1
- package/agent-template/.agents/skills/migration-authoring/SKILL.md +4 -4
- package/agent-template/.agents/skills/module-new/SKILL.md +1 -1
- package/agent-template/.agents/skills/test-hardening/SKILL.md +2 -2
- package/agent-template/.agents/skills/workflow-development/SKILL.md +95 -9
- package/agent-template/.ai/blueprints/add-migration/required-files.yaml +1 -1
- package/agent-template/.ai/blueprints/new-module/required-files.yaml +1 -1
- package/agent-template/.ai/platform-capabilities.md +7 -5
- package/agent-template/.ai/policies/capabilities.yaml +28 -12
- package/agent-template/.ai/skills/README.md +1 -1
- package/agent-template/.ai/skills/agent-tool-design/SKILL.md +1 -1
- package/agent-template/.ai/skills/auth-security-review/SKILL.md +1 -1
- package/agent-template/.ai/skills/database-adapter/SKILL.md +5 -5
- package/agent-template/.ai/skills/database-adapter/references/first-run-and-matrix.md +2 -2
- package/agent-template/.ai/skills/deploy-operate/SKILL.md +1 -1
- package/agent-template/.ai/skills/migration-authoring/SKILL.md +4 -4
- package/agent-template/.ai/skills/module-new/SKILL.md +1 -1
- package/agent-template/.ai/skills/test-hardening/SKILL.md +2 -2
- package/agent-template/.ai/skills/workflow-development/SKILL.md +96 -10
- package/agent-template/.claude/skills/agent-tool-design/SKILL.md +1 -1
- package/agent-template/.claude/skills/auth-security-review/SKILL.md +1 -1
- package/agent-template/.claude/skills/database-adapter/SKILL.md +5 -5
- package/agent-template/.claude/skills/database-adapter/references/first-run-and-matrix.md +2 -2
- package/agent-template/.claude/skills/deploy-operate/SKILL.md +1 -1
- package/agent-template/.claude/skills/migration-authoring/SKILL.md +4 -4
- package/agent-template/.claude/skills/module-new/SKILL.md +1 -1
- package/agent-template/.claude/skills/test-hardening/SKILL.md +2 -2
- package/agent-template/.claude/skills/workflow-development/SKILL.md +95 -9
- package/agent-template/docs/adr/0007-module-owned-agents.md +35 -1
- package/agent-template/docs/agent-contract.md +2 -2
- package/agent-template/docs/cli.md +24 -3
- package/agent-template/docs/configuration.md +32 -5
- package/agent-template/docs/database-adapters.md +20 -20
- package/agent-template/docs/design-system.md +1 -1
- package/agent-template/docs/getting-started.md +25 -32
- package/agent-template/docs/module-distribution.md +79 -86
- package/agent-template/docs/module-web-surfaces.md +9 -7
- package/agent-template/docs/modules.md +3 -1
- package/agent-template/platform/scripts/build.mjs +7 -0
- package/dist/bin.js +3 -6
- package/package.json +1 -1
- package/template/default/.env.example +3 -3
- package/template/default/.vercelignore +8 -0
- package/template/default/README.md +20 -11
- package/template/default/_gitignore +3 -2
- package/template/default/infra/README.md +86 -65
- package/template/default/infra/docker/.env.example +66 -0
- package/template/default/infra/docker/Dockerfile +24 -10
- package/template/default/infra/docker/app-entrypoint.mjs +5 -0
- package/template/default/infra/docker/compose.yaml +105 -58
- package/template/default/infra/docker/database-urls.mjs +28 -0
- package/template/default/infra/docker/pitr.sh +177 -0
- package/template/default/infra/docker/postgres/10-roles.sh +16 -12
- package/template/default/infra/docker/start.mjs +402 -0
- package/template/default/infra/kubernetes/database-secret.example.yaml +3 -3
- package/template/default/infra/vercel/README.md +262 -0
- package/template/default/infra/vercel/build.mjs +214 -0
- package/template/default/infra/vercel/handler.mjs +100 -0
- package/template/default/modules/example/migrations/0001_example_core.up.sql +2 -2
- package/template/default/modules/example/module.json +1 -1
- package/template/default/modules/example/package.json +3 -3
- package/template/default/modules/example/spec/module.yaml +1 -1
- package/template/default/modules/example/src/services/migration.ts +2 -2
- package/template/default/modules/example/tests/module.test.ts +1 -1
- package/template/default/package.json +2 -2
- package/template/default/platform/octane.config.ts +252 -156
- package/template/default/platform/package.json +5 -5
- package/template/default/platform/scripts/build.mjs +56 -0
- package/template/default/platform/scripts/dev.mjs +38 -0
- package/template/default/platform/src/generated/modules.server.ts +1 -0
- package/template/default/platform/src/server/database.ts +24 -0
- package/template/default/platform/src/server/runtime-role.ts +33 -0
- package/template/default/platform/src/server/setup/access.ts +160 -0
- package/template/default/platform/src/server/setup/adapters.ts +554 -0
- package/template/default/platform/src/server/setup/environment.ts +154 -0
- package/template/default/platform/src/server/setup/gate.ts +84 -0
- package/template/default/platform/src/server/setup/index.ts +181 -0
- package/template/default/platform/src/server/setup/modules.ts +123 -0
- package/template/default/platform/src/server/setup/page.ts +497 -0
- package/template/default/platform/src/server/setup/routes.ts +787 -0
- package/template/default/platform/src/server/setup/sanitize.ts +111 -0
- package/template/default/platform/src/server/setup/seed.ts +145 -0
- package/template/default/platform/src/server/setup/token.ts +79 -0
- package/template/default/platform/src/server/worker-tick.ts +193 -0
- package/template/default/platform/src/server/workspace-root.ts +16 -0
- package/template/default/render.yaml +70 -0
- package/template/default/vercel.json +5 -0
|
@@ -7,13 +7,15 @@ example module, and nothing else you have to configure.
|
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
9
|
pnpm install
|
|
10
|
-
pnpm flowdular setup
|
|
11
10
|
pnpm dev
|
|
12
11
|
```
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
On the first run, the server starts the setup page and `pnpm dev` opens it in
|
|
14
|
+
your browser. Enter the one-time token printed in the terminal, then choose
|
|
15
|
+
your workspace and owner account. The embedded database is already selected.
|
|
16
|
+
If a browser cannot open automatically, visit <http://localhost:4310/setup>.
|
|
17
|
+
Restart `pnpm dev` after setup, then sign in with the account you chose. Use
|
|
18
|
+
`pnpm dev -- --no-open` to leave the browser alone.
|
|
17
19
|
|
|
18
20
|
Local development runs on embedded PostgreSQL, so there is no database server to
|
|
19
21
|
install. Data lives under `.flowdular/data`.
|
|
@@ -25,7 +27,7 @@ install. Data lives under `.flowdular/data`.
|
|
|
25
27
|
| `platform` | The deployable composition root and the application shell |
|
|
26
28
|
| `modules/example` | A tenant-scoped record module: API, migration, screen, tests |
|
|
27
29
|
| `specs` | The platform spec of this application |
|
|
28
|
-
| `infra` |
|
|
30
|
+
| `infra` | Docker, Kubernetes and Vercel deployment assets |
|
|
29
31
|
| `flowdular.json` | Enabled modules and locales, owned by the CLI |
|
|
30
32
|
| `.env` | The keys generated for this app. Never commit it |
|
|
31
33
|
| `.env.example` | Every key a production deployment reads |
|
|
@@ -79,19 +81,26 @@ account access, then paste the token and the application address into the
|
|
|
79
81
|
connect screen.
|
|
80
82
|
|
|
81
83
|
```bash
|
|
82
|
-
pnpm flowdular sandbox grant --email
|
|
84
|
+
pnpm flowdular sandbox grant --email <your-owner-email> --tenant <your-workspace-slug> --apply
|
|
83
85
|
```
|
|
84
86
|
|
|
85
87
|
## Deploy
|
|
86
88
|
|
|
87
89
|
```bash
|
|
88
|
-
|
|
89
|
-
docker compose -f infra/docker/compose.yaml up --build
|
|
90
|
+
node infra/docker/start.mjs
|
|
90
91
|
```
|
|
91
92
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
The launcher creates `infra/docker/.env` with private database passwords and
|
|
94
|
+
keys, starts PostgreSQL and MinIO, then opens the setup page. Enter the token
|
|
95
|
+
shown in the terminal. The database step is already complete, so you start with
|
|
96
|
+
the workspace owner. `infra/README.md` covers the stack and deployments.
|
|
97
|
+
|
|
98
|
+
To deploy on Vercel, run `vercel login` and then
|
|
99
|
+
`pnpm flowdular deploy start vercel --apply`. It provisions Neon PostgreSQL, a
|
|
100
|
+
private Blob store and the stable keys, deploys, and prints a one-time token for
|
|
101
|
+
creating the first workspace at `/setup`; `infra/vercel/README.md` walks through
|
|
102
|
+
it and the manual path. Module workers run in a worker Function that Vercel Cron
|
|
103
|
+
and state-changing requests tick.
|
|
95
104
|
|
|
96
105
|
## Commands
|
|
97
106
|
|
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# Deployment
|
|
2
2
|
|
|
3
|
+
## Deployment targets
|
|
4
|
+
|
|
5
|
+
Run `pnpm flowdular deploy targets` to inspect the target contracts and
|
|
6
|
+
`pnpm flowdular deploy plan docker` before starting the local stack.
|
|
7
|
+
`pnpm flowdular deploy start docker --apply` starts Docker Compose and opens
|
|
8
|
+
first-run setup. It prints the setup token, so it requires a private
|
|
9
|
+
interactive terminal and refuses `--json` or redirected output.
|
|
10
|
+
|
|
11
|
+
The repository-root `render.yaml` is a Render Blueprint for an always-on
|
|
12
|
+
container. It needs external PostgreSQL with separate runtime, background and
|
|
13
|
+
migrator roles, verified TLS and an existing S3 bucket. The Blueprint prompts
|
|
14
|
+
for the database and storage values, derives its public HTTPS origin from the
|
|
15
|
+
Render service and generates encryption keys. Back up those keys separately.
|
|
16
|
+
If you add a custom domain, set its HTTPS origin in `render.yaml` so the next
|
|
17
|
+
Blueprint sync keeps it. It uses
|
|
18
|
+
`/api/health` during initial setup; verify
|
|
19
|
+
`/api/ready` after setup. See the main Flowdular deployment guide for details.
|
|
20
|
+
Render Blueprints can create a database, but `fromDatabase` gives its internal
|
|
21
|
+
URL, whose self-signed TLS certificate cannot satisfy Flowdular's production
|
|
22
|
+
`verify-full` requirement. The Blueprint also cannot declare the three
|
|
23
|
+
separate roles. Render can host MinIO, but this Blueprint does not initialize
|
|
24
|
+
its bucket or wire its credentials. For a store other than AWS S3, set
|
|
25
|
+
`FD_STORAGE_S3_ENDPOINT` and, if needed, `FD_STORAGE_S3_FORCE_PATH_STYLE` on
|
|
26
|
+
the Render service. See the [Render Postgres connection guide](https://render.com/docs/postgresql-creating-connecting)
|
|
27
|
+
and [MinIO guide](https://render.com/docs/deploy-minio).
|
|
28
|
+
After committing
|
|
29
|
+
`render.yaml` and `infra/docker/Dockerfile` and pushing the branch to a
|
|
30
|
+
credential-free Git origin, `deploy plan render --json` returns a Deploy to
|
|
31
|
+
Render URL when both files pass structural checks and match the pushed branch. The URL
|
|
32
|
+
selects that branch for Render, but the external PostgreSQL, storage and secret
|
|
33
|
+
prerequisites still require operator setup. Local Git tracking refs are not
|
|
34
|
+
live provider validation, so confirm that Render can access the branch.
|
|
35
|
+
|
|
36
|
+
The [Vercel artifact](vercel/README.md) packages the Octane handler and client
|
|
37
|
+
assets as a web Function and a worker Function. [Vercel Functions scale down to zero](https://vercel.com/docs/functions),
|
|
38
|
+
so module workers run only inside ticks from Vercel Cron and from
|
|
39
|
+
state-changing requests. `deploy plan vercel --json` checks its source and
|
|
40
|
+
returns an import URL for a pushed branch. `deploy start vercel --apply`
|
|
41
|
+
provisions Neon PostgreSQL, a private Blob store and the stable keys through the
|
|
42
|
+
Vercel CLI, deploys to Production and prints a one-time token for creating the
|
|
43
|
+
first workspace at `/setup`.
|
|
44
|
+
Cloudflare's Durable Object Container API can keep a process alive, but
|
|
45
|
+
Flowdular has no verified adapter for its restart, secret and rollout lifecycle.
|
|
46
|
+
|
|
3
47
|
The production artifact is the server built from `platform`. It runs as a
|
|
4
48
|
non-root user and serves two public probes from
|
|
5
49
|
`platform/src/server/health.ts`: `GET /api/health` answers as soon as the
|
|
@@ -11,73 +55,50 @@ background roles hold neither `SUPERUSER` nor `BYPASSRLS`, and answers 503 with
|
|
|
11
55
|
## Local container
|
|
12
56
|
|
|
13
57
|
```bash
|
|
14
|
-
|
|
15
|
-
docker compose -f infra/docker/compose.yaml up --build
|
|
58
|
+
node infra/docker/start.mjs
|
|
16
59
|
```
|
|
17
60
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
`
|
|
24
|
-
|
|
25
|
-
Compose
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
61
|
+
The launcher creates `infra/docker/.env` with owner-only permissions, generates
|
|
62
|
+
PostgreSQL passwords and platform keys once, and keeps them on later runs. It
|
|
63
|
+
starts PostgreSQL, a private MinIO bucket and the app. When the database is
|
|
64
|
+
empty, it opens the first-run setup in the workstation browser and prints the
|
|
65
|
+
one-time setup token in the terminal. Use `--no-open` on a headless host. The
|
|
66
|
+
normal address is `http://localhost:3000`; change `FD_PORT` in the Docker env
|
|
67
|
+
file to use another port. The container binds to `127.0.0.1` by default. A
|
|
68
|
+
generated Compose project name keeps this app's volumes separate from other
|
|
69
|
+
Flowdular projects on the same machine.
|
|
70
|
+
|
|
71
|
+
The database and object store are connected before the setup page appears, so
|
|
72
|
+
the wizard starts with workspace and owner details. After confirmation, Compose
|
|
73
|
+
restarts the app into the sign-in screen. AI models are optional and can be
|
|
74
|
+
connected in Providers after signing in. Mail remains off until the operator
|
|
75
|
+
sets `FD_AUTH_MAIL_TRANSPORT=smtp`, `FD_AUTH_SMTP_URL` and `FD_AUTH_MAIL_FROM`.
|
|
76
|
+
|
|
77
|
+
To run Compose directly, copy `infra/docker/.env.example` to
|
|
78
|
+
`infra/docker/.env`, fill every required secret, set
|
|
79
|
+
`FD_AUTH_SECURE_COOKIE=false` for local HTTP, and run
|
|
80
|
+
`docker compose --env-file infra/docker/.env -f infra/docker/compose.yaml up --build`.
|
|
81
|
+
The setup token is in the `app` container logs. Keep that token out of URLs and
|
|
82
|
+
shared logs. For remote access, configure a TLS proxy, `FD_AUTH_PUBLIC_ORIGIN`,
|
|
83
|
+
`FD_BIND_ADDRESS` and secure cookies.
|
|
84
|
+
|
|
85
|
+
Compose gives the PostgreSQL runtime and background roles neither `SUPERUSER`
|
|
86
|
+
nor `BYPASSRLS`, and the migrator owns the schema. Its TLS certificate is
|
|
87
|
+
created once and verified by the app. The image ships the bundled server and a
|
|
88
|
+
small entrypoint that URL-encodes database passwords before starting it.
|
|
89
|
+
|
|
90
|
+
Back up the PostgreSQL data and WAL volumes, the MinIO object volume, and
|
|
91
|
+
`infra/docker/.env` together. The env file holds the keys needed to decrypt
|
|
92
|
+
records and objects after restore. `infra/docker/pitr.sh` can create a base
|
|
93
|
+
backup and replay archived PostgreSQL WAL segments; run its `--help` before a
|
|
94
|
+
restore, which requires explicit confirmation and stops the app when requested.
|
|
42
95
|
|
|
43
96
|
## Migrations on rollout
|
|
44
97
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
the runtime role.
|
|
50
|
-
|
|
51
|
-
What a rollout should do is fail before the new image serves traffic when an
|
|
52
|
-
already applied migration no longer matches the code being deployed. That is the
|
|
53
|
-
one-shot `migration-check` service in `infra/docker/compose.yaml`: it runs
|
|
54
|
-
`flowdular migration status --json`, reports what is pending, and exits non-zero
|
|
55
|
-
on a checksum mismatch. `app` starts only after it completes successfully.
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
docker compose -f infra/docker/compose.yaml run --rm migration-check
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Outside compose, run the same check from a checkout with the deployment's
|
|
62
|
-
`FD_DATABASE_*` values in the environment. On Kubernetes it belongs in a
|
|
63
|
-
pre-upgrade Job or in the pipeline step ahead of `kubectl apply`. After the
|
|
64
|
-
rollout, `flowdular migration verify` should come back clean.
|
|
65
|
-
|
|
66
|
-
`flowdular migration apply` exists, but it is not part of a rollout. It takes one
|
|
67
|
-
module at a time (`--module <id> --apply`; there is no `--all` flag) and the
|
|
68
|
-
capability is local-only: the runner refuses it unless `FD_ENV` or `NODE_ENV` is
|
|
69
|
-
`development` or `test`. Use it on a workstation against a local database:
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
pnpm flowdular migration status # pending work, per module
|
|
73
|
-
pnpm flowdular migration apply --module example.core # dry run
|
|
74
|
-
pnpm flowdular migration apply --module example.core --apply
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Repeat the last two lines for each module `migration status` reports.
|
|
78
|
-
|
|
79
|
-
Applied migrations are immutable. To change schema, add a numbered migration;
|
|
80
|
-
never edit one the ledger already recorded.
|
|
98
|
+
Module migrations run through the migration role on first use. Applied
|
|
99
|
+
migrations are immutable: add a numbered migration rather than editing one
|
|
100
|
+
that is already in the ledger. Check migration status with the workspace CLI
|
|
101
|
+
before a production rollout, and verify it afterwards.
|
|
81
102
|
|
|
82
103
|
## Published image
|
|
83
104
|
|
|
@@ -93,9 +114,9 @@ kubectl create secret generic flowdular-secrets \
|
|
|
93
114
|
--from-literal=workflowsPayloadKey="$(openssl rand -base64 32)" \
|
|
94
115
|
--from-literal=workflowsCursorKey="$(openssl rand -base64 32)"
|
|
95
116
|
kubectl create secret generic flowdular-database \
|
|
96
|
-
--from-literal=migratorUrl='postgresql://
|
|
97
|
-
--from-literal=runtimeUrl='postgresql://
|
|
98
|
-
--from-literal=backgroundUrl='postgresql://
|
|
117
|
+
--from-literal=migratorUrl='postgresql://flowdular_migrator:...@postgres:5432/flowdular' \
|
|
118
|
+
--from-literal=runtimeUrl='postgresql://flowdular_runtime:...@postgres:5432/flowdular' \
|
|
119
|
+
--from-literal=backgroundUrl='postgresql://flowdular_background:...@postgres:5432/flowdular'
|
|
99
120
|
kubectl apply -k infra/kubernetes
|
|
100
121
|
```
|
|
101
122
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# node infra/docker/start.mjs creates infra/docker/.env automatically.
|
|
2
|
+
# To use docker compose directly, copy this file and fill every required secret.
|
|
3
|
+
# Never commit the copy. Generate encryption keys with: openssl rand -base64 32
|
|
4
|
+
# Set a different project name for each app so their named volumes cannot mix.
|
|
5
|
+
COMPOSE_PROJECT_NAME=
|
|
6
|
+
FD_AGENT_CREDENTIAL_KEY=
|
|
7
|
+
FD_AGENT_CREDENTIAL_KEY_PREVIOUS=
|
|
8
|
+
FD_AGENT_RUN_GRANT_KEY=
|
|
9
|
+
FD_AUTH_MFA_KEY=
|
|
10
|
+
FD_AUTH_MFA_KEY_PREVIOUS=
|
|
11
|
+
FD_APPROVAL_GRANT_KEY=
|
|
12
|
+
FD_APPROVAL_GRANT_KEY_PREVIOUS=
|
|
13
|
+
FD_AUTOMATIONS_CREDENTIAL_KEY=
|
|
14
|
+
FD_AUTOMATIONS_CREDENTIAL_KEY_PREVIOUS=
|
|
15
|
+
FD_NOTIFICATIONS_SECRET_KEY=
|
|
16
|
+
FD_NOTIFICATIONS_SECRET_KEY_PREVIOUS=
|
|
17
|
+
FD_WORKFLOWS_PAYLOAD_KEY=
|
|
18
|
+
FD_WORKFLOWS_PAYLOAD_KEY_PREVIOUS=
|
|
19
|
+
FD_WORKFLOWS_CURSOR_KEY=
|
|
20
|
+
FD_WORKFLOWS_CURSOR_KEY_PREVIOUS=
|
|
21
|
+
FD_STORAGE_ENCRYPTION_KEY=
|
|
22
|
+
FD_STORAGE_ENCRYPTION_KEY_PREVIOUS=
|
|
23
|
+
FD_CONNECTORS_SECRET_KEY=
|
|
24
|
+
FD_CONNECTORS_SECRET_KEY_PREVIOUS=
|
|
25
|
+
FD_AUDIT_ANCHOR_KEY=
|
|
26
|
+
FD_AUDIT_ANCHOR_KEY_PREVIOUS=
|
|
27
|
+
|
|
28
|
+
# The default S3-compatible store is the MinIO service in compose.yaml, with a
|
|
29
|
+
# private flowdular bucket. Override these values for an external S3 service.
|
|
30
|
+
# Back up the MinIO object volume with PostgreSQL and this .env file.
|
|
31
|
+
FD_MINIO_ROOT_PASSWORD=
|
|
32
|
+
FD_STORAGE_S3_BUCKET=
|
|
33
|
+
FD_STORAGE_S3_REGION=
|
|
34
|
+
FD_STORAGE_S3_ENDPOINT=
|
|
35
|
+
FD_STORAGE_S3_ACCESS_KEY_ID=
|
|
36
|
+
FD_STORAGE_S3_SECRET_ACCESS_KEY=
|
|
37
|
+
FD_STORAGE_S3_FORCE_PATH_STYLE=true
|
|
38
|
+
|
|
39
|
+
# PostgreSQL credentials. The superuser only bootstraps the cluster; the app
|
|
40
|
+
# connects as flowdular_runtime and migrates as flowdular_migrator. Newly created
|
|
41
|
+
# passwords are URL-safe hex. Existing passwords are kept as-is.
|
|
42
|
+
FD_POSTGRES_SUPERUSER_PASSWORD=
|
|
43
|
+
FD_DATABASE_MIGRATOR_PASSWORD=
|
|
44
|
+
FD_DATABASE_RUNTIME_PASSWORD=
|
|
45
|
+
FD_DATABASE_BACKGROUND_PASSWORD=
|
|
46
|
+
|
|
47
|
+
# Outgoing mail. With none, workspace invitations are refused and password reset
|
|
48
|
+
# messages are never delivered. Set smtp and both values below to send them; the
|
|
49
|
+
# URL carries the relay password, so treat this file as a secret.
|
|
50
|
+
FD_AUTH_MAIL_TRANSPORT=none
|
|
51
|
+
FD_AUTH_SMTP_URL=
|
|
52
|
+
FD_AUTH_MAIL_FROM=
|
|
53
|
+
|
|
54
|
+
# Host port for the published container port 3000.
|
|
55
|
+
FD_PORT=3000
|
|
56
|
+
FD_BIND_ADDRESS=127.0.0.1
|
|
57
|
+
FD_APPLICATION_PATH=/app
|
|
58
|
+
FD_AUTH_PUBLIC_ORIGIN=
|
|
59
|
+
|
|
60
|
+
# The local launcher writes false for HTTP on a workstation. For a deployment
|
|
61
|
+
# behind TLS, set true and set FD_AUTH_PUBLIC_ORIGIN to its HTTPS origin.
|
|
62
|
+
FD_AUTH_SECURE_COOKIE=
|
|
63
|
+
|
|
64
|
+
# Prometheus exposition on GET /api/metrics. Leave FD_METRICS unset to keep it off.
|
|
65
|
+
FD_METRICS=false
|
|
66
|
+
FD_METRICS_TOKEN=
|
|
@@ -7,9 +7,17 @@ WORKDIR /workspace
|
|
|
7
7
|
|
|
8
8
|
RUN corepack enable && corepack prepare pnpm@11.17.0 --activate
|
|
9
9
|
|
|
10
|
+
# The image only builds: tests and checks run in CI before a tag is cut. The
|
|
11
|
+
# package store is fetched from the lockfile alone, so this layer is reused
|
|
12
|
+
# until the lockfile changes.
|
|
13
|
+
COPY pnpm-lock.yaml pnpm-workspace.yaml ./
|
|
14
|
+
RUN pnpm fetch
|
|
10
15
|
COPY . .
|
|
11
|
-
RUN pnpm install --frozen-lockfile
|
|
12
|
-
RUN pnpm
|
|
16
|
+
RUN pnpm install --frozen-lockfile --offline
|
|
17
|
+
RUN pnpm build
|
|
18
|
+
RUN mkdir -p module-plans \
|
|
19
|
+
&& if [ ! -f flowdular.modules.lock.json ]; then printf '{"schemaVersion":1,"modules":[]}\n' > flowdular.modules.lock.json; fi \
|
|
20
|
+
&& if [ ! -f flowdular.module-sources.json ]; then printf '{"schemaVersion":1,"sources":[]}\n' > flowdular.module-sources.json; fi
|
|
13
21
|
|
|
14
22
|
FROM node:24-bookworm-slim AS runtime
|
|
15
23
|
|
|
@@ -17,21 +25,27 @@ ENV NODE_ENV=production
|
|
|
17
25
|
ENV PORT=3000
|
|
18
26
|
WORKDIR /app
|
|
19
27
|
|
|
20
|
-
RUN groupadd --system --gid 1001
|
|
21
|
-
&& useradd --system --uid 1001 --gid
|
|
28
|
+
RUN groupadd --system --gid 1001 octane \
|
|
29
|
+
&& useradd --system --uid 1001 --gid octane octane \
|
|
22
30
|
&& mkdir -p /data \
|
|
23
|
-
&& chown
|
|
31
|
+
&& chown octane:octane /data
|
|
24
32
|
|
|
25
33
|
# The server bundle is self-contained: platform/dist/server/entry.js imports
|
|
26
34
|
# only node:* built-ins, so no node_modules (and no devDependencies) ship.
|
|
27
|
-
COPY --from=builder --chown=
|
|
28
|
-
COPY --from=builder --chown=
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
COPY --from=builder --chown=octane:octane /workspace/platform/dist ./platform/dist
|
|
36
|
+
COPY --from=builder --chown=octane:octane /workspace/platform/package.json ./platform/package.json
|
|
37
|
+
COPY --chown=octane:octane infra/docker/app-entrypoint.mjs infra/docker/database-urls.mjs ./infra/docker/
|
|
38
|
+
COPY --from=builder --chown=octane:octane /workspace/flowdular.json ./flowdular.json
|
|
39
|
+
COPY --from=builder --chown=octane:octane /workspace/flowdular.modules.lock.json ./flowdular.modules.lock.json
|
|
40
|
+
COPY --from=builder --chown=octane:octane /workspace/flowdular.module-sources.json ./flowdular.module-sources.json
|
|
41
|
+
COPY --from=builder --chown=octane:octane /workspace/module-plans ./module-plans
|
|
42
|
+
COPY --from=builder --chown=octane:octane /workspace/modules ./modules
|
|
43
|
+
|
|
44
|
+
USER octane
|
|
31
45
|
EXPOSE 3000
|
|
32
46
|
VOLUME ["/data"]
|
|
33
47
|
|
|
34
48
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
|
|
35
49
|
CMD node -e "fetch('http://127.0.0.1:3000/api/health').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"
|
|
36
50
|
|
|
37
|
-
CMD ["node", "platform/dist/server/entry.js"]
|
|
51
|
+
CMD ["node", "--import", "./infra/docker/app-entrypoint.mjs", "platform/dist/server/entry.js"]
|
|
@@ -5,6 +5,7 @@ services:
|
|
|
5
5
|
volumes:
|
|
6
6
|
- ./postgres/tls-init.sh:/tls-init.sh:ro
|
|
7
7
|
- flowdular-postgres-tls:/tls
|
|
8
|
+
- flowdular-postgres-wal:/var/lib/postgresql/wal-archive
|
|
8
9
|
restart: 'no'
|
|
9
10
|
|
|
10
11
|
postgres:
|
|
@@ -14,10 +15,10 @@ services:
|
|
|
14
15
|
condition: service_completed_successfully
|
|
15
16
|
environment:
|
|
16
17
|
POSTGRES_DB: flowdular
|
|
17
|
-
POSTGRES_PASSWORD: ${FD_POSTGRES_SUPERUSER_PASSWORD:?
|
|
18
|
-
FD_DATABASE_MIGRATOR_PASSWORD: ${FD_DATABASE_MIGRATOR_PASSWORD:?
|
|
19
|
-
FD_DATABASE_RUNTIME_PASSWORD: ${FD_DATABASE_RUNTIME_PASSWORD:?
|
|
20
|
-
FD_DATABASE_BACKGROUND_PASSWORD: ${FD_DATABASE_BACKGROUND_PASSWORD:?
|
|
18
|
+
POSTGRES_PASSWORD: ${FD_POSTGRES_SUPERUSER_PASSWORD:?Run node infra/docker/start.mjs or set FD_POSTGRES_SUPERUSER_PASSWORD}
|
|
19
|
+
FD_DATABASE_MIGRATOR_PASSWORD: ${FD_DATABASE_MIGRATOR_PASSWORD:?Run node infra/docker/start.mjs or set FD_DATABASE_MIGRATOR_PASSWORD}
|
|
20
|
+
FD_DATABASE_RUNTIME_PASSWORD: ${FD_DATABASE_RUNTIME_PASSWORD:?Run node infra/docker/start.mjs or set FD_DATABASE_RUNTIME_PASSWORD}
|
|
21
|
+
FD_DATABASE_BACKGROUND_PASSWORD: ${FD_DATABASE_BACKGROUND_PASSWORD:?Run node infra/docker/start.mjs or set FD_DATABASE_BACKGROUND_PASSWORD}
|
|
21
22
|
command:
|
|
22
23
|
- postgres
|
|
23
24
|
- -c
|
|
@@ -26,8 +27,21 @@ services:
|
|
|
26
27
|
- ssl_cert_file=/tls/server.crt
|
|
27
28
|
- -c
|
|
28
29
|
- ssl_key_file=/tls/server.key
|
|
30
|
+
# Point-in-time recovery: every completed WAL segment is copied into the
|
|
31
|
+
# archive volume, and a quiet database still ships one every five
|
|
32
|
+
# minutes. See infra/README.md, "Backups and PITR", for the limits of a
|
|
33
|
+
# plain cp archive and for the base backup this needs.
|
|
34
|
+
- -c
|
|
35
|
+
- wal_level=replica
|
|
36
|
+
- -c
|
|
37
|
+
- archive_mode=on
|
|
38
|
+
- -c
|
|
39
|
+
- archive_timeout=300
|
|
40
|
+
- -c
|
|
41
|
+
- 'archive_command=test ! -f /var/lib/postgresql/wal-archive/%f && cp %p /var/lib/postgresql/wal-archive/%f'
|
|
29
42
|
volumes:
|
|
30
43
|
- flowdular-postgres:/var/lib/postgresql/data
|
|
44
|
+
- flowdular-postgres-wal:/var/lib/postgresql/wal-archive
|
|
31
45
|
- flowdular-postgres-tls:/tls:ro
|
|
32
46
|
- ./postgres/10-roles.sh:/docker-entrypoint-initdb.d/10-roles.sh:ro
|
|
33
47
|
healthcheck:
|
|
@@ -40,29 +54,40 @@ services:
|
|
|
40
54
|
- no-new-privileges:true
|
|
41
55
|
restart: unless-stopped
|
|
42
56
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
# matches the checksum of the code being deployed. It needs the workspace and
|
|
47
|
-
# the CLI, so it runs the builder stage rather than the runtime image.
|
|
48
|
-
migration-check:
|
|
49
|
-
build:
|
|
50
|
-
context: ../..
|
|
51
|
-
dockerfile: infra/docker/Dockerfile
|
|
52
|
-
target: builder
|
|
53
|
-
image: flowdular-app-builder:local
|
|
54
|
-
depends_on:
|
|
55
|
-
postgres:
|
|
56
|
-
condition: service_healthy
|
|
57
|
-
command: ['pnpm', 'flowdular', 'migration', 'status', '--json']
|
|
57
|
+
minio:
|
|
58
|
+
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
|
|
59
|
+
command: server /data --console-address :9001
|
|
58
60
|
environment:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
FD_DATABASE_MIGRATOR_URL: postgresql://coreloom_migrator:${FD_DATABASE_MIGRATOR_PASSWORD}@postgres:5432/flowdular
|
|
62
|
-
FD_DATABASE_TLS: verify-full
|
|
63
|
-
FD_DATABASE_TLS_CA_FILE: /tls/server.crt
|
|
61
|
+
MINIO_ROOT_USER: ${FD_MINIO_ROOT_USER:-flowdularlocal}
|
|
62
|
+
MINIO_ROOT_PASSWORD: ${FD_MINIO_ROOT_PASSWORD:?Run node infra/docker/start.mjs or set FD_MINIO_ROOT_PASSWORD}
|
|
64
63
|
volumes:
|
|
65
|
-
- flowdular-
|
|
64
|
+
- flowdular-objects:/data
|
|
65
|
+
security_opt:
|
|
66
|
+
- no-new-privileges:true
|
|
67
|
+
restart: unless-stopped
|
|
68
|
+
|
|
69
|
+
minio-init:
|
|
70
|
+
image: minio/mc:RELEASE.2025-08-13T08-35-41Z
|
|
71
|
+
entrypoint: /bin/sh
|
|
72
|
+
command:
|
|
73
|
+
- -ec
|
|
74
|
+
- |
|
|
75
|
+
for attempt in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30; do
|
|
76
|
+
if mc alias set local http://minio:9000 "$$MINIO_ROOT_USER" "$$MINIO_ROOT_PASSWORD" >/dev/null 2>&1; then
|
|
77
|
+
mc mb --ignore-existing "local/$$FD_STORAGE_S3_BUCKET"
|
|
78
|
+
exit 0
|
|
79
|
+
fi
|
|
80
|
+
sleep 2
|
|
81
|
+
done
|
|
82
|
+
echo 'MinIO did not become ready within 60 seconds.' >&2
|
|
83
|
+
exit 1
|
|
84
|
+
depends_on:
|
|
85
|
+
minio:
|
|
86
|
+
condition: service_started
|
|
87
|
+
environment:
|
|
88
|
+
MINIO_ROOT_USER: ${FD_MINIO_ROOT_USER:-flowdularlocal}
|
|
89
|
+
MINIO_ROOT_PASSWORD: ${FD_MINIO_ROOT_PASSWORD:?Run node infra/docker/start.mjs or set FD_MINIO_ROOT_PASSWORD}
|
|
90
|
+
FD_STORAGE_S3_BUCKET: ${FD_STORAGE_S3_BUCKET:-flowdular}
|
|
66
91
|
security_opt:
|
|
67
92
|
- no-new-privileges:true
|
|
68
93
|
restart: 'no'
|
|
@@ -71,11 +96,11 @@ services:
|
|
|
71
96
|
build:
|
|
72
97
|
context: ../..
|
|
73
98
|
dockerfile: infra/docker/Dockerfile
|
|
74
|
-
image: flowdular
|
|
99
|
+
image: flowdular:local
|
|
75
100
|
depends_on:
|
|
76
101
|
postgres:
|
|
77
102
|
condition: service_healthy
|
|
78
|
-
|
|
103
|
+
minio-init:
|
|
79
104
|
condition: service_completed_successfully
|
|
80
105
|
environment:
|
|
81
106
|
NODE_ENV: production
|
|
@@ -83,29 +108,56 @@ services:
|
|
|
83
108
|
# Every module reads and writes through the platform provider; the
|
|
84
109
|
# deployment has one database and no per-module files.
|
|
85
110
|
FD_DATABASE_ADAPTER: postgresql
|
|
86
|
-
|
|
87
|
-
|
|
111
|
+
# The image entrypoint encodes these passwords before making PostgreSQL
|
|
112
|
+
# URLs. Older deployments may have generated base64 values containing /.
|
|
113
|
+
FD_DATABASE_RUNTIME_PASSWORD: ${FD_DATABASE_RUNTIME_PASSWORD:?Run node infra/docker/start.mjs or set FD_DATABASE_RUNTIME_PASSWORD}
|
|
114
|
+
FD_DATABASE_MIGRATOR_PASSWORD: ${FD_DATABASE_MIGRATOR_PASSWORD:?Run node infra/docker/start.mjs or set FD_DATABASE_MIGRATOR_PASSWORD}
|
|
88
115
|
# Cross-tenant reads (the scheduler poll) run as this role. It carries no
|
|
89
116
|
# blanket grant: a migration hands it named columns under its own policy.
|
|
90
|
-
|
|
117
|
+
FD_DATABASE_BACKGROUND_PASSWORD: ${FD_DATABASE_BACKGROUND_PASSWORD:?Run node infra/docker/start.mjs or set FD_DATABASE_BACKGROUND_PASSWORD}
|
|
118
|
+
FD_DATABASE_URL: ${FD_DATABASE_URL:-}
|
|
119
|
+
FD_DATABASE_MIGRATOR_URL: ${FD_DATABASE_MIGRATOR_URL:-}
|
|
120
|
+
FD_DATABASE_BACKGROUND_URL: ${FD_DATABASE_BACKGROUND_URL:-}
|
|
91
121
|
FD_DATABASE_TLS: verify-full
|
|
92
122
|
FD_DATABASE_TLS_CA_FILE: /tls/server.crt
|
|
123
|
+
FD_AUTH_PUBLIC_ORIGIN: ${FD_AUTH_PUBLIC_ORIGIN:-http://localhost:${FD_PORT:-3000}}
|
|
124
|
+
FD_APPLICATION_PATH: ${FD_APPLICATION_PATH:-/app}
|
|
125
|
+
FD_SETUP_AUTO_RESTART: 'true'
|
|
93
126
|
FD_AUTH_ALLOW_SIGN_UP: 'false'
|
|
94
127
|
# TLS terminates in front of this container. Only a plain-HTTP run on a
|
|
95
128
|
# workstation may set FD_AUTH_SECURE_COOKIE=false in .env.
|
|
96
129
|
FD_AUTH_SECURE_COOKIE: ${FD_AUTH_SECURE_COOKIE:-true}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
#
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
130
|
+
FD_AUTH_MFA_KEY: ${FD_AUTH_MFA_KEY:?Run node infra/docker/start.mjs or set FD_AUTH_MFA_KEY}
|
|
131
|
+
FD_AUTH_MFA_KEY_PREVIOUS: ${FD_AUTH_MFA_KEY_PREVIOUS:-}
|
|
132
|
+
# Outgoing mail. none refuses invitations and delivers no password reset
|
|
133
|
+
# message; smtp requires the URL and the sender below.
|
|
134
|
+
FD_AUTH_MAIL_TRANSPORT: ${FD_AUTH_MAIL_TRANSPORT:-none}
|
|
135
|
+
FD_TRUST_PROXY: ${FD_TRUST_PROXY:-false}
|
|
136
|
+
FD_METRICS: ${FD_METRICS:-false}
|
|
137
|
+
FD_METRICS_TOKEN: ${FD_METRICS_TOKEN:-}
|
|
138
|
+
FD_AUTH_SMTP_URL: ${FD_AUTH_SMTP_URL:-}
|
|
139
|
+
FD_AUTH_MAIL_FROM: ${FD_AUTH_MAIL_FROM:-}
|
|
140
|
+
# start.mjs creates these once in infra/docker/.env. Existing values win.
|
|
141
|
+
FD_AGENT_CREDENTIAL_KEY: ${FD_AGENT_CREDENTIAL_KEY:?Run node infra/docker/start.mjs or set FD_AGENT_CREDENTIAL_KEY}
|
|
142
|
+
FD_AGENT_RUN_GRANT_KEY: ${FD_AGENT_RUN_GRANT_KEY:?Run node infra/docker/start.mjs or set FD_AGENT_RUN_GRANT_KEY}
|
|
143
|
+
FD_APPROVAL_GRANT_KEY: ${FD_APPROVAL_GRANT_KEY:?Run node infra/docker/start.mjs or set FD_APPROVAL_GRANT_KEY}
|
|
144
|
+
FD_AUTOMATIONS_CREDENTIAL_KEY: ${FD_AUTOMATIONS_CREDENTIAL_KEY:?Run node infra/docker/start.mjs or set FD_AUTOMATIONS_CREDENTIAL_KEY}
|
|
145
|
+
FD_NOTIFICATIONS_SECRET_KEY: ${FD_NOTIFICATIONS_SECRET_KEY:?Run node infra/docker/start.mjs or set FD_NOTIFICATIONS_SECRET_KEY}
|
|
146
|
+
FD_WORKFLOWS_PAYLOAD_KEY: ${FD_WORKFLOWS_PAYLOAD_KEY:?Run node infra/docker/start.mjs or set FD_WORKFLOWS_PAYLOAD_KEY}
|
|
147
|
+
FD_WORKFLOWS_CURSOR_KEY: ${FD_WORKFLOWS_CURSOR_KEY:?Run node infra/docker/start.mjs or set FD_WORKFLOWS_CURSOR_KEY}
|
|
148
|
+
FD_STORAGE_ENCRYPTION_KEY: ${FD_STORAGE_ENCRYPTION_KEY:?Run node infra/docker/start.mjs or set FD_STORAGE_ENCRYPTION_KEY}
|
|
149
|
+
FD_CONNECTORS_SECRET_KEY: ${FD_CONNECTORS_SECRET_KEY:?Run node infra/docker/start.mjs or set FD_CONNECTORS_SECRET_KEY}
|
|
150
|
+
FD_AUDIT_ANCHOR_KEY: ${FD_AUDIT_ANCHOR_KEY:?Run node infra/docker/start.mjs or set FD_AUDIT_ANCHOR_KEY}
|
|
151
|
+
# Previous keys are operator-managed during rotation and remain empty on a new install.
|
|
152
|
+
FD_AGENT_CREDENTIAL_KEY_PREVIOUS: ${FD_AGENT_CREDENTIAL_KEY_PREVIOUS:-}
|
|
153
|
+
FD_APPROVAL_GRANT_KEY_PREVIOUS: ${FD_APPROVAL_GRANT_KEY_PREVIOUS:-}
|
|
154
|
+
FD_AUTOMATIONS_CREDENTIAL_KEY_PREVIOUS: ${FD_AUTOMATIONS_CREDENTIAL_KEY_PREVIOUS:-}
|
|
155
|
+
FD_NOTIFICATIONS_SECRET_KEY_PREVIOUS: ${FD_NOTIFICATIONS_SECRET_KEY_PREVIOUS:-}
|
|
156
|
+
FD_WORKFLOWS_PAYLOAD_KEY_PREVIOUS: ${FD_WORKFLOWS_PAYLOAD_KEY_PREVIOUS:-}
|
|
157
|
+
FD_WORKFLOWS_CURSOR_KEY_PREVIOUS: ${FD_WORKFLOWS_CURSOR_KEY_PREVIOUS:-}
|
|
158
|
+
FD_STORAGE_ENCRYPTION_KEY_PREVIOUS: ${FD_STORAGE_ENCRYPTION_KEY_PREVIOUS:-}
|
|
159
|
+
FD_CONNECTORS_SECRET_KEY_PREVIOUS: ${FD_CONNECTORS_SECRET_KEY_PREVIOUS:-}
|
|
160
|
+
FD_AUDIT_ANCHOR_KEY_PREVIOUS: ${FD_AUDIT_ANCHOR_KEY_PREVIOUS:-}
|
|
109
161
|
# Object storage. Production refuses the local adapter, so the app writes
|
|
110
162
|
# to an S3-compatible bucket and encrypts every object under
|
|
111
163
|
# FD_STORAGE_ENCRYPTION_KEY before it leaves the process. The named volume
|
|
@@ -113,23 +165,14 @@ services:
|
|
|
113
165
|
# run outside production for a demonstration.
|
|
114
166
|
FD_STORAGE_ADAPTER: ${FD_STORAGE_ADAPTER:-s3}
|
|
115
167
|
FD_STORAGE_LOCAL_DIRECTORY: /var/lib/flowdular/storage
|
|
116
|
-
FD_STORAGE_S3_BUCKET: ${FD_STORAGE_S3_BUCKET:-}
|
|
117
|
-
FD_STORAGE_S3_REGION: ${FD_STORAGE_S3_REGION:-}
|
|
118
|
-
FD_STORAGE_S3_ENDPOINT: ${FD_STORAGE_S3_ENDPOINT
|
|
119
|
-
FD_STORAGE_S3_ACCESS_KEY_ID: ${FD_STORAGE_S3_ACCESS_KEY_ID:-}
|
|
120
|
-
FD_STORAGE_S3_SECRET_ACCESS_KEY: ${FD_STORAGE_S3_SECRET_ACCESS_KEY
|
|
121
|
-
FD_STORAGE_S3_FORCE_PATH_STYLE: ${FD_STORAGE_S3_FORCE_PATH_STYLE:-
|
|
122
|
-
# Optional: without it the app runs and only MFA enrollment is unavailable.
|
|
123
|
-
FD_AUTH_MFA_KEY: ${FD_AUTH_MFA_KEY:-}
|
|
124
|
-
# Outgoing mail. With none, invitations and password resets are refused.
|
|
125
|
-
FD_AUTH_MAIL_TRANSPORT: ${FD_AUTH_MAIL_TRANSPORT:-none}
|
|
126
|
-
FD_TRUST_PROXY: ${FD_TRUST_PROXY:-false}
|
|
127
|
-
FD_METRICS: ${FD_METRICS:-false}
|
|
128
|
-
FD_METRICS_TOKEN: ${FD_METRICS_TOKEN:-}
|
|
129
|
-
FD_AUTH_SMTP_URL: ${FD_AUTH_SMTP_URL:-}
|
|
130
|
-
FD_AUTH_MAIL_FROM: ${FD_AUTH_MAIL_FROM:-}
|
|
168
|
+
FD_STORAGE_S3_BUCKET: ${FD_STORAGE_S3_BUCKET:-flowdular}
|
|
169
|
+
FD_STORAGE_S3_REGION: ${FD_STORAGE_S3_REGION:-us-east-1}
|
|
170
|
+
FD_STORAGE_S3_ENDPOINT: ${FD_STORAGE_S3_ENDPOINT-}
|
|
171
|
+
FD_STORAGE_S3_ACCESS_KEY_ID: ${FD_STORAGE_S3_ACCESS_KEY_ID:-${FD_MINIO_ROOT_USER:-flowdularlocal}}
|
|
172
|
+
FD_STORAGE_S3_SECRET_ACCESS_KEY: ${FD_STORAGE_S3_SECRET_ACCESS_KEY:-${FD_MINIO_ROOT_PASSWORD:?Run node infra/docker/start.mjs or set FD_MINIO_ROOT_PASSWORD}}
|
|
173
|
+
FD_STORAGE_S3_FORCE_PATH_STYLE: ${FD_STORAGE_S3_FORCE_PATH_STYLE:-true}
|
|
131
174
|
ports:
|
|
132
|
-
- '${FD_PORT:-3000}:3000'
|
|
175
|
+
- '${FD_BIND_ADDRESS:-127.0.0.1}:${FD_PORT:-3000}:3000'
|
|
133
176
|
healthcheck:
|
|
134
177
|
test:
|
|
135
178
|
- CMD
|
|
@@ -153,6 +196,10 @@ services:
|
|
|
153
196
|
|
|
154
197
|
volumes:
|
|
155
198
|
flowdular-postgres:
|
|
199
|
+
# WAL segments and base backups for point-in-time recovery (infra/docker/pitr.sh).
|
|
200
|
+
flowdular-postgres-wal:
|
|
156
201
|
flowdular-postgres-tls:
|
|
157
202
|
# Only the local adapter writes here; a production run uses the S3 bucket.
|
|
158
203
|
flowdular-storage:
|
|
204
|
+
# Local S3-compatible storage; back up this volume alongside PostgreSQL.
|
|
205
|
+
flowdular-objects:
|