Skip to content

fix: persist Langflow database across container restarts#1208

Merged
mpawlow merged 7 commits intorelease-0.4.0from
mp/fix/0.4.0/GH-1127-langflow-flow-edits-not-persisted
Mar 23, 2026
Merged

fix: persist Langflow database across container restarts#1208
mpawlow merged 7 commits intorelease-0.4.0from
mp/fix/0.4.0/GH-1127-langflow-flow-edits-not-persisted

Conversation

@mpawlow
Copy link
Copy Markdown
Collaborator

@mpawlow mpawlow commented Mar 20, 2026

Issue

Reference Pull Request

@mpawlow mpawlow self-assigned this Mar 20, 2026
@github-actions github-actions bot added documentation 📘 Improvements or additions to documentation frontend 🟨 Issues related to the UI/UX backend 🔷 Issues related to backend services (OpenSearch, Langflow, APIs) ci ⬛ CI/CD, build, and infrastructure issues docker bug 🔴 Something isn't working. and removed documentation 📘 Improvements or additions to documentation labels Mar 20, 2026
@github-actions

This comment has been minimized.

JasonOA888 and others added 7 commits March 23, 2026 06:11
Fixes #1127 - Langflow flow edits no longer lost after restart

## Problem
Flow edits made in Langflow UI were being lost after container restart.
The langflow service only mounted /app/flows but Langflow stores its
SQLite database at /root/.langflow/ by default, which was ephemeral.

## Solution
1. Add persistent volume for Langflow data directory:
   - Mount ${LANGFLOW_DATA_PATH:-./langflow-data} to /root/.langflow
2. Explicitly set LANGFLOW_DATABASE_URL to ensure database location
3. Document the new LANGFLOW_DATA_PATH in .env.example

## Testing
- Verified volume mount configuration
- Database URL format: sqlite:////root/.langflow/langflow.db

Closes #1127
Issue

- #1127

Summary

- User-made edits to Langflow flows were silently discarded on every container restart.
- Two root causes were identified and corrected:
- (1) The Langflow data volume was mounted to the wrong path inside the container.
- (2) The LANGFLOW_LOAD_FLOWS_PATH mechanism performed a blind upsert of all flows on every startup, overwriting any changes made in the Langflow UI.

Docker / Infrastructure

- Corrected the Langflow data volume mount target from /root/.langflow to /app/langflow-data in docker-compose.yml
- Replaced LANGFLOW_LOAD_FLOWS_PATH env var with LANGFLOW_CONFIG_DIR=/app/langflow-data so Langflow resolves its config and database from the persisted volume
- Updated LANGFLOW_DATABASE_URL to reference the new path (sqlite:////app/langflow-data/langflow.db)
- Pre-created /app/langflow-data in Dockerfile.langflow during image build to ensure named Docker volumes are initialised with the correct ownership for the non-root container user
- Added langflow-data/ directory with a .gitkeep file; updated .gitignore to track the directory stub while ignoring its contents

Backend — Flow Bootstrapping

- Added FlowsService.ensure_flows_exist(): a create-only startup routine that checks each configured flow ID against the Langflow API and creates missing flows from their JSON files, without ever patching or
overwriting an existing flow
- Replaced the LANGFLOW_LOAD_FLOWS_PATH blind-upsert behaviour with a call to ensure_flows_exist() inside startup_tasks() in src/main.py

Makefile

- Extended the factory-reset target to remove the langflow-data/ directory alongside opensearch-data/ and config/

Code Cleanup

- Removed trailing whitespace throughout src/services/flows_service.py

Builds on #1129
Issue

- #1127

Summary

- Propagated LANGFLOW_DATA_PATH to all locations that reference OPENSEARCH_DATA_PATH

CI / Test Infrastructure

- Added langflow-data to the Docker container cleanup command in test-e2e.yml and test-integration.yml, ensuring CI runners start each run with a clean Langflow database
- Added LANGFLOW_DATA_PATH=./langflow-data to frontend/.env.test.example alongside the existing OPENSEARCH_DATA_PATH entry
- Added a langflow-data directory cleanup block to tests/conftest.py that mirrors the existing opensearch-data teardown, so integration tests run against a fresh Langflow DB

Documentation

- Added a LANGFLOW_DATA_PATH row to the Langflow settings table in docs/docs/reference/configuration.mdx, documenting the default value and that flow edits are lost without this volume

TUI — Configuration Fields

- Added a langflow_data_path ConfigField to the Langflow section in config_fields.py with a file picker placeholder and a default of $HOME/.openrag/data/langflow-data

TUI — Env Manager

- Added langflow_data_path field to the EnvConfig dataclass in env_manager.py
- Added "LANGFLOW_DATA_PATH": "langflow_data_path" entry to _env_attr_map() so the variable is loaded from and written to .env files
- Added LANGFLOW_DATA_PATH write in save_env_file() immediately after the OPENSEARCH_DATA_PATH write

TUI — Config Screen

- Added langflow_data_path to SPECIAL_FIELDS in config.py
- Added _render_langflow_data_path() renderer with a "Pick…" directory picker button, matching the _render_opensearch_data_path() pattern
- Added action_pick_langflow_data_path() action implementing the textual-fspicker directory picker flow
- Wired the pick-langflow-data-btn button in on_pressed and added the _langflow_data_pick_callback fallback handler in on_screen_dismissed
Issue

- #1127

Summary

- Fixed Langflow data directory persistence and bind-mount ownership across container restarts

Container & Entrypoint

- Added docker-entrypoint-langflow.sh that runs as root, chowns /app/langflow-data to uid=1000, then drops privileges and execs the main process — mirrors the pattern used by official database images
- Updated Dockerfile.langflow to switch to USER root, copy the entrypoint script, set it as ENTRYPOINT, and simplified the RUN layer
- Added # syntax=docker/dockerfile:1.4 directive to Dockerfile.langflow

Repository & Git Ignore

- Removed langflow-data/.gitkeep and replaced the selective .gitignore pattern (/langflow-data/* + !.gitkeep) with a blanket langflow-data/ ignore entry

Makefile

- Added ensure-langflow-data target that creates the langflow-data bind-mount directory on the host before Docker starts (prevents Docker from creating it as root)
- Added ensure-langflow-data as a prerequisite to dev, dev-cpu, dev-local, dev-local-cpu, dev-local-build-lf, dev-local-build-lf-cpu, dev-branch, dev-branch-cpu, restart-dev, test-ci, and test-ci-local
- Updated factory-reset to fully remove the langflow-data directory (rm -rf langflow-data) instead of only clearing its contents
Issue

- #1127

Summary

- Removed Langflow data directory cleanup from test setup

Test Infrastructure

- Removed the block in conftest.py that deleted the Langflow data directory (LANGFLOW_DATA_PATH) before tests ran, as this cleanup is no longer appropriate given that the Langflow database is now persisted
across container restarts.
Issue

- #1127

Summary

- Persisted Langflow database and flow configurations across container restarts by replacing the blind upsert startup mechanism with a create-only flow seeding approach.

Docker / Container Changes

- Removed the custom docker-entrypoint-langflow.sh entrypoint script, which ran chown as root before dropping to uid=1000; the base Langflow image already owns /app as uid=1000, so the privilege escalation was
unnecessary.
- Simplified Dockerfile.langflow by removing the USER root switch, entrypoint script copy, and the ENTRYPOINT override; the image now runs its default langflow run command directly.
- Updated docker-compose.yml to resolve LANGFLOW_DATABASE_URL from the environment with a SQLite fallback (${LANGFLOW_DATABASE_URL:-sqlite:////app/langflow-data/langflow.db}), allowing operators to substitute
a PostgreSQL URL without rebuilding the image.
- Added LANGFLOW_DATABASE_URL to .env.example with documentation on overriding for production PostgreSQL deployments.

Kubernetes / Helm Changes

- Replaced the LANGFLOW_LOAD_FLOWS_PATH env var with LANGFLOW_CONFIG_DIR in the Langflow Helm deployment template to align with the new startup flow seeding approach.

Backend: Flow Seeding & Reset Detection

- Updated FlowsService.ensure_flows_exist() to return a set[str] of flow type names that were newly created during the current startup, rather than returning None.
- Added handling for unexpected non-404 HTTP status codes when checking whether a flow exists; logs a warning and skips creation to avoid overwriting existing data.
- Updated startup_tasks() in src/main.py to capture the set of newly created flows from ensure_flows_exist().
- Filtered out newly seeded flows from the check_flows_reset() result so that freshly created flows (which match their JSON definition by design) are not incorrectly flagged as having been externally reset.
- Upgraded the log level for ensure_flows_exist() failures from warning to error to better surface critical startup failures.
Issue

- #1127

Summary

- Fixed Langflow data directory permissions for CI and E2E test environments

CI Test Pipeline (Makefile)

- Added chmod 777 langflow-data before the test run in both test-ci and test-ci-local targets to ensure the langflow-data directory is world-writable prior to container startup

E2E Test Setup (scripts/setup-e2e.sh)

- Added pre-creation of the langflow-data directory with world-writable permissions (777) before infrastructure starts, ensuring the Langflow container (UID 1000) and the CI runner (UID 1001) can both access it regardless of Docker's :U flag behavior
@mpawlow mpawlow force-pushed the mp/fix/0.4.0/GH-1127-langflow-flow-edits-not-persisted branch from 3a5b98b to 47cb992 Compare March 23, 2026 13:12
@github-actions github-actions bot added documentation 📘 Improvements or additions to documentation bug 🔴 Something isn't working. and removed bug 🔴 Something isn't working. documentation 📘 Improvements or additions to documentation labels Mar 23, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 23, 2026

Build successful! ✅
Deploying docs draft.
Deploy successful! View draft

@mpawlow mpawlow requested a review from lucaseduoli March 23, 2026 13:30
@github-actions github-actions bot added bug 🔴 Something isn't working. and removed bug 🔴 Something isn't working. labels Mar 23, 2026
@Wallgau Wallgau self-requested a review March 23, 2026 13:58
Copy link
Copy Markdown
Collaborator

@Wallgau Wallgau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changes were approved for main, so just origin branch here, LGTM

@github-actions github-actions bot added the lgtm label Mar 23, 2026
@mpawlow mpawlow merged commit b436a8a into release-0.4.0 Mar 23, 2026
12 checks passed
@github-actions github-actions bot deleted the mp/fix/0.4.0/GH-1127-langflow-flow-edits-not-persisted branch March 23, 2026 15:55
@mpawlow mpawlow linked an issue Mar 23, 2026 that may be closed by this pull request
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend 🔷 Issues related to backend services (OpenSearch, Langflow, APIs) bug 🔴 Something isn't working. ci ⬛ CI/CD, build, and infrastructure issues docker frontend 🟨 Issues related to the UI/UX lgtm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Langflow flow edits are not persisting after restart.

3 participants