From d6b90b947b91f22123bda4585fbe22586802dcc5 Mon Sep 17 00:00:00 2001 From: luohua13 Date: Tue, 7 Jul 2026 12:54:26 +0000 Subject: [PATCH 1/4] docs(langflow): rewrite for v1.10.1 community chart (chart-wrap) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting with Langflow v1.10.1 the platform ships an OLM OperatorBundle (chart-wrap of the upstream langflow-ai/langflow-helm-charts/langflow-ide chart) instead of a bespoke Alauda fork chart (aml/langflow v1.6.4). The config surface changed accordingly: - Install path: OperatorHub + Langflow custom resource, not Applications / Catalog form - Values paths shift: `langflow.foo` -> `spec.langflow.backend.foo` (wrap CR spec mirrors the upstream chart's values.yaml) - SQLite volume: `langflow.sqlite.volume.storageClassName` becomes `spec.langflow.backend.sqlite.volume.existingStorageClassName`, with the magic string `"default"` meaning "use cluster-default SC" - External DB: `langflow.externalDatabase` becomes `spec.langflow.backend.externalDatabase`; startup shim rewrites LANGFLOW_DATABASE_URL from the LF_CHART_EXTERNALDB_* env vars - Auth: the upstream chart has no structured `auth.enabled` block; use backend env vars (LANGFLOW_AUTO_LOGIN, LANGFLOW_SUPERUSER, LANGFLOW_SUPERUSER_PASSWORD, ...) instead - OAuth2 Proxy: not part of the upstream chart. Section removed; SSO now documented as "deploy an external OAuth2 Proxy in front of the Langflow Service" — same pattern as other chart-wrap components - External access: Gateway API (Envoy Gateway + HTTPRoute) is the recommended path; upstream chart Ingress is documented as fallback Prerequisites section added: cluster must have a default StorageClass (the chart's `sqlite.volume.existingStorageClassName: "default"` magic string relies on it). Every parameter in this rewrite was validated end-to-end on ACP 4.3 (business-1) against a real langflow-operator.v1.10.1-rc.8 install: - SQLite storage on default SC (sc-topolvm): rc.8 e2e smoke - Gateway API external access: rc.8 e2e smoke E probe (Envoy Gateway, NodePort 32423, hits /health_check successfully) - Runtime mode (backendOnly + frontend.enabled=false): dedicated probe I — frontend Deployment count 0, backend still serves - Flow CRUD (POST/GET/DELETE): smoke F probe on rc.8 - API key gate (create + valid=200 + wrong=403): smoke H probe on rc.8 - External PostgreSQL: fresh langflow-pg ns install; verified LANGFLOW_DATABASE_URL rewritten via chart shim, `/data/langflow.db` absent, 33 flows written into PostgreSQL, full Langflow schema created via Alembic - Auth env vars (AUTO_LOGIN=false + SUPERUSER creds): 403/200/401/ 200/403 probe on fresh langflow-auth ns - Global variables (LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT + plain env + secretKeyRef): GET /api/v1/variables/ returns both entries as type: Credential Both zh and en versions updated in parallel. --- .../How_to_install_and_use_Langflow.md | 518 +++++++++-------- .../How_to_install_and_use_Langflow.md | 524 ++++++++++-------- 2 files changed, 575 insertions(+), 467 deletions(-) diff --git a/docs/en/solutions/How_to_install_and_use_Langflow.md b/docs/en/solutions/How_to_install_and_use_Langflow.md index 061344fb2..640e330f7 100644 --- a/docs/en/solutions/How_to_install_and_use_Langflow.md +++ b/docs/en/solutions/How_to_install_and_use_Langflow.md @@ -37,76 +37,101 @@ This section provides detailed instructions on how to deploy Langflow to a Kuber ## Publishing -Download the Langflow installation file: `langflow.ALL.v1.6.4-1.tgz` +Download the Langflow installation file: `langflow-operator.alpha.ALL.v1.10.1.tgz` Use the violet command to publish to the platform repository: ```bash -violet push --platform-address=platform-access-address --platform-username=platform-admin --platform-password=platform-admin-password langflow.ALL.v1.6.4-1.tgz +violet push --platform-address=platform-access-address --platform-username=platform-admin --platform-password=platform-admin-password langflow-operator.alpha.ALL.v1.10.1.tgz ``` +Starting with v1.10.1, Langflow is packaged as an OLM `OperatorBundle` (chart-wrap of the upstream `langflow-ai/langflow-helm-charts/langflow-ide` chart), not a raw Helm chart. Installation goes through OperatorHub and a `Langflow` custom resource, not the Applications / Catalog picker. + +## Prerequisites + +Before installing Langflow, the target workload cluster must have: + +- **A default StorageClass** — Langflow's backend uses SQLite by default, backed by an RWO PVC that requests the cluster's default StorageClass. Without a default, `data-langflow-service-0` will stay `Pending` and the backend pod cannot schedule. Set one with: + + ```bash + kubectl get sc + kubectl patch sc -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' + ``` + + If you want to pin a specific StorageClass instead of relying on the cluster default, set `spec.langflow.backend.sqlite.volume.existingStorageClassName` on the `Langflow` custom resource (see [Configure Storage](#1-configure-storage)). + +- **(Optional, for Gateway API external access)** Envoy Gateway installed on the cluster with a `GatewayClass` whose `controllerName` contains `envoy`. Without one, users can only reach Langflow via `kubectl port-forward` or by opening a NodePort/LoadBalancer Service manually. + ## Deployment ### Prepare Storage -Langflow supports two database modes: -- **SQLite (Default)**: For development and testing, data is stored in persistent volumes -- **PostgreSQL (Recommended)**: For production environments, providing better performance and scalability - -The cluster needs to have CSI pre-installed or `PersistentVolume` pre-prepared. +Langflow uses SQLite by default with an RWO PVC (1Gi). For production, PostgreSQL is recommended (see [Configure Database](#2-configure-database)). The cluster must have a default StorageClass or the user must set `existingStorageClassName` explicitly. -### Prepare Database +### Prepare Database (Optional) #### Using SQLite (Default) -SQLite is Langflow's default database, suitable for development and testing environments: -- Data is stored in persistent volumes -- Simple configuration, no additional setup required -- Supports single-instance deployment - -#### Using PostgreSQL (Recommended) +SQLite is Langflow's default database: +- Data is stored in an RWO PVC (`data-langflow-service-0`, 1Gi default) +- Simple, no additional infrastructure +- Only supports single-instance backend (StatefulSet replicas = 1) -Production environments strongly recommend using PostgreSQL for better performance and scalability: +#### Using PostgreSQL (Recommended for production) -The `PostgreSQL operator` provided by `Data Services` can be used to create a `PostgreSQL cluster`. +Production environments strongly recommend PostgreSQL: -Check the access address and password in the `PostgreSQL` instance details in `Data Services`. +- Provision a PostgreSQL instance via `Data Services` PostgreSQL Operator, or use any external PostgreSQL reachable from the cluster. +- Create a dedicated database and user with `CREATE`/`CONNECT` privileges. The Langflow backend will run Alembic migrations against it at first startup. **Note**: - PostgreSQL version 12 or higher is recommended -- Need to create a separate database and user -- Ensure network connectivity +- Ensure network connectivity from the Langflow namespace to the PostgreSQL instance +- Store the password in a Kubernetes `Secret` and reference it via `secretKeyRef` (see [Configure Database](#2-configure-database)) -### Create Application +### Install Operator + Create Langflow -1. Go to the `Alauda Container Platform` view and select the namespace where Langflow will be deployed. +1. In `Alauda Container Platform`, open `OperatorHub` and search for `Langflow`. Install `Langflow` from the `platform` catalog source (defaults: channel `alpha`, install mode `AllNamespaces`). -2. In the left navigation, select `Applications` / `Applications`, then click the `Create` button on the right page. +2. Wait for the CSV `langflow-operator.v1.10.1` to reach `Succeeded`. -3. In the popup dialog, select `Create from Catalog`, then the page will jump to the `Catalog` view. +3. Create a namespace for the Langflow instance (default suggestion: `langflow-system`). -4. Find `3rdparty/chart-langflow` and click `Create` to create this application. +4. Apply a `Langflow` custom resource in that namespace. Minimal form: -5. On the `Catalog` / `Create langflow` form, fill in the `Name` (recommended as `langflow`) and `Custom` configuration in `Values`, then click the `Create` button to complete creation. The `Custom` content will be described below. It can also be modified after creation through the `Update` application method. + ```yaml + apiVersion: langflow-operator.alauda.io/v1 + kind: Langflow + metadata: + name: langflow + namespace: langflow-system + spec: {} + ``` + + Empty `spec: {}` uses the chart's defaults (SQLite on the cluster default StorageClass, IDE mode, ClusterIP Services, no Ingress). To customize, add fields under `spec.langflow.*` per the sections below — the wrap CR spec mirrors the upstream chart's `values.yaml` structure. See the upstream [`values.yaml`](https://github.com/langflow-ai/langflow-helm-charts/blob/langflow-ide-0.1.2/charts/langflow-ide/values.yaml) for the full field list. ## Configuration -Users can modify the `Custom Values` of the `Application` to adjust configuration. The main configurations to focus on are as follows: +Users can edit the `Langflow` custom resource's `spec.langflow.*` fields to customize the deployment. The wrap CR spec mirrors the upstream `langflow-ide` chart's `values.yaml` structure. The main configurations to focus on are as follows. ### 1. Configure Storage #### 1.1 Configure SQLite Storage (Default) -The storage class and size can be specified by adding the following configuration: +The StorageClass and volume size can be specified by adding the following configuration: ```yaml -langflow: - sqlite: - volume: - storageClassName: storage-class-name # Replace with the actual storage class name - size: 1Gi # Replace with the actual required space size +spec: + langflow: + backend: + sqlite: + volume: + existingStorageClassName: # Cluster StorageClass name; leave "default" to use the cluster default + size: 1Gi # PVC size ``` -**Note**: When using SQLite, only single-instance deployment (replicaCount = 1) is supported. +**Note**: +- `existingStorageClassName: "default"` is a magic string in the chart that means "use the cluster's default StorageClass" (i.e. the SC annotated `storageclass.kubernetes.io/is-default-class: "true"`). Set an explicit SC name to override. +- When using SQLite, only single-instance backend is supported (StatefulSet replicas = 1). ### 2. Configure Database @@ -115,168 +140,175 @@ langflow: PostgreSQL access information can be configured by setting the following fields: ```yaml -langflow: - externalDatabase: - enabled: true # Enable external database - driver: - value: "postgresql" - host: - value: postgres-host # PostgreSQL access address - port: - value: "5432" # PostgreSQL access port, default: 5432 - database: - value: langflow # Database name, note: database will be created automatically - user: - value: langflow # Database username - password: - valueFrom: - secretKeyRef: - name: postgres-secret # Secret name storing database access password - key: password # Secret key storing database access password +spec: + langflow: + backend: + externalDatabase: + enabled: true # Enable external database + driver: {value: "postgresql"} + host: {value: } # PostgreSQL host (Service DNS or external address) + port: {value: "5432"} + database: {value: langflow} # Target database (must exist before backend starts) + user: {value: langflow} + password: + valueFrom: + secretKeyRef: + name: postgres-secret # Secret holding the password + key: password ``` -**Note**: Due to temporary storage limitations, the current version temporarily does not support multi-instance deployment. Even with PostgreSQL database configured, only single-instance deployment (replicaCount = 1) is supported. +The chart runs a small startup shim inside the backend container that reads these `LF_CHART_EXTERNALDB_*` env vars and composes them into `LANGFLOW_DATABASE_URL=postgresql://:@:/`, overriding the sqlite default. Verified by connecting to the target PostgreSQL after backend startup: Langflow creates its full schema (`alembic_version`, `flow`, `apikey`, `folder`, `message`, etc.) via Alembic and populates it with the built-in starter projects. -### 3. Configure Access Method +**Note**: With SQLite, only single-instance backend is supported. Multi-instance backend requires PostgreSQL, but the current chart still ships `replicas: 1` for the backend StatefulSet — scale explicitly if you need HA. -By default, `LoadBalancer` is used to provide access address. +### 3. Configure External Access -#### 3.1 Modify Service Type +The upstream chart creates only two `ClusterIP` Services by default: -The `Service` type can be modified by setting the following fields: +- `langflow-service` on port 8080 — frontend (React IDE served by nginx) +- `langflow-service-backend` on port 7860 — backend (FastAPI + `/api/v1/*`) -```yaml -langflow: - service: - type: LoadBalancer # Can be changed to NodePort or ClusterIP - port: 7860 # Service port -``` +The frontend nginx also reverse-proxies `/api`, `/health` and `/health_check` to the backend, so **routing all external traffic to `langflow-service:8080` gives users both the SPA and the backend API through the same entry point**. + +**Recommended path: Gateway API (Envoy Gateway)** -#### 3.2 Enable Ingress +The chart-wrap ships an example under `components/langflow/examples/gateway-httproute.example.yaml` (in the `oss-operator-factory` repo). Cluster operators apply an `EnvoyProxy` + `Gateway` once per cluster; users add an `HTTPRoute` in the Langflow namespace pointing at `langflow-service:8080`. A single rule with one backend covers everything — no path-prefix split needed. -Ingress can be configured by setting the following fields. After enabling Ingress, the Service type is usually changed to ClusterIP: +Minimal HTTPRoute example (assuming a Gateway `langflow-gw` already exists): ```yaml -ingress: - enabled: true # Enable Ingress functionality - hosts: - - host: langflow.example.com # Access domain (must be DNS name, not IP address) - paths: - - path: / - tls: - - secretName: langflow-tls # Secret name storing TLS certificate - hosts: - - langflow.example.com +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: langflow + namespace: +spec: + parentRefs: + - {group: gateway.networking.k8s.io, kind: Gateway, name: langflow-gw, namespace: } + hostnames: [] + rules: + - matches: [{path: {type: PathPrefix, value: "/"}}] + backendRefs: + - {name: langflow-service, port: 8080} ``` -### 4. Configure Authentication and User Management (Optional) - -#### 4.1 Enable User Authentication +**Alternative: upstream chart Ingress** -User authentication can be enabled by setting the following fields: +The chart also exposes an Ingress block (default off). Enable via the wrap CR: ```yaml -langflow: - auth: - enabled: true # Enable authentication - superuser: - username: langflow # Superuser name - password: "" # Superuser password, auto-generated if not set - secretKey: "" # Secret key, auto-generated if not set - newUserActive: false # Whether new users need activation - enableSuperuserCLI: false # Whether to enable CLI superuser - accessTokenExpireSeconds: 3600 # Access token expiration time (seconds) - refreshTokenExpireSeconds: 604800 # Refresh token expiration time (seconds) +spec: + langflow: + ingress: + enabled: true + hosts: + - host: langflow.example.com + paths: [{path: /, pathType: Prefix}] + tls: + - {secretName: langflow-tls, hosts: [langflow.example.com]} ``` -After enabling authentication, by default: -- Login is required to access -- Superuser can be configured -- New users can only be added by superuser through `/admin` page (self-registration is not supported) -- New user account activation: If `newUserActive=true`, new user accounts are automatically activated; If `newUserActive=false` (default), superuser needs to manually activate +Notes: +- The chart's default `ingress.enabled: false` is intentional in the wrap — pre-opening Ingress would fail on clusters with no matching ingress class or DNS. +- OAuth2 Proxy is **not** part of the upstream chart. If SSO is required, deploy an OAuth2 Proxy (or platform SSO) as a separate Deployment in front of the Langflow Service; the wrap does not manage its lifecycle. This is the same pattern used for other chart-wrap components on the platform. +### 4. Configure Authentication and User Management (Optional) -### 5. Configure OAuth2 Proxy (Optional) - -OAuth2 proxy can be configured to provide single sign-on functionality by setting the following fields: +The upstream community chart does not expose a structured `auth` field. Instead, Langflow authentication is controlled by environment variables set on the backend container. Set them under `spec.langflow.backend.env`: ```yaml -oauth2_proxy: - enabled: true # Enable OAuth2 proxy - oidcIssuer: "https://x.x.x.com/dex" # OIDC Issuer address - oidcClientID: "your-client-id" # OIDC client ID - oidcClientSecret: "your-client-secret" # OIDC client secret (recommended to use Secret) +spec: + langflow: + backend: + env: + - name: LANGFLOW_AUTO_LOGIN + value: "false" # Disable auto-login (default: true) + - name: LANGFLOW_SUPERUSER + valueFrom: + secretKeyRef: {name: langflow-superuser, key: username} + - name: LANGFLOW_SUPERUSER_PASSWORD + valueFrom: + secretKeyRef: {name: langflow-superuser, key: password} + - name: LANGFLOW_NEW_USER_IS_ACTIVE + value: "false" # New users require superuser activation (default: false) + - name: LANGFLOW_ENABLE_SUPERUSER_CLI + value: "false" # Disable CLI superuser bootstrap ``` -To configure `Alauda Container Platform` as OIDC Provider, configure as follows: -- `oauth2_proxy.oidcIssuer` is the platform access address plus `/dex` -- `oauth2_proxy.oidcClientID` is fixed as `langflow` -- `oauth2_proxy.oidcClientSecret` is fixed as `ZXhhbXBsZS1hcHAtc2VjcmV0` +Verified behavior with `LANGFLOW_AUTO_LOGIN=false`: -Also create an OAuth2Client resource in the global cluster to configure Langflow's client information: +- `GET /api/v1/auto_login` returns **403** (auto-login disabled). +- `POST /api/v1/login` with the correct superuser credentials returns **200** with an `access_token`. +- `POST /api/v1/login` with wrong credentials returns **401**. +- Protected endpoints (e.g. `GET /api/v1/all`) return **200** with a valid Bearer token and **403** without. -```yaml -apiVersion: dex.coreos.com/v1 -kind: OAuth2Client -metadata: - name: nrqw4z3gnrxxps7sttsiiirdeu - namespace: cpaas-system -id: langflow # Consistent with oauth2_proxy.oidcClientID in values -name: Langflow -secret: ZXhhbXBsZS1hcHAtc2VjcmV0 # Consistent with oauth2_proxy.oidcClientSecret in values -redirectURIs: -- http://xxx.xxx.xxxx.xxx:xxxxx/* # OAuth2-Proxy access address, acquisition method described below - # If multiple Langflow instances are deployed, add multiple access addresses here -``` +Notes: +- With `LANGFLOW_AUTO_LOGIN=false`, self-registration is not supported. New users must be added by the superuser via `/admin`; if `LANGFLOW_NEW_USER_IS_ACTIVE=false`, the superuser must activate the account before login is allowed. +- The superuser credentials are only consumed on **first startup**. Once written into the database (SQLite or PostgreSQL), changing the env vars alone does not rotate them — the credential update must go through Langflow's admin UI or a DB migration. +- Access/refresh token expiration are controlled by `LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS` / `LANGFLOW_REFRESH_TOKEN_EXPIRE_SECONDS` (defaults are conservative; adjust only if required). -**Note**: OAuth2 Proxy access address can be obtained from the `-oauth2-proxy` Service, use the appropriate access method based on Service type. +### 5. Single Sign-On (SSO) -After enabling OAuth2 Proxy, it is recommended to: -- Set `langflow.service.type` to `ClusterIP`, allowing access only within the cluster. Users need to access Langflow through OAuth2 Proxy address. -- Set `langflow.auth.enabled` to `false`. Use OAuth2 Proxy to handle login authentication. - -Users can log out by accessing `/oauth2/sign_out`. +The upstream `langflow-ide` chart **does not include an OAuth2 Proxy sidecar or Deployment**. If SSO is required, deploy an OAuth2 Proxy (or the platform's existing SSO gateway) as a separate workload in front of the Langflow frontend Service — this is outside the wrap CR's control surface and follows the same pattern used by other chart-wrap components on the platform. Configure the OAuth2 Proxy to point at `langflow-service:8080` as its upstream, and set `LANGFLOW_AUTO_LOGIN=false` on the backend so the proxy is the sole authentication entry point. ### 6. Configure Runtime Mode (Backend-Only) -Runtime mode is the recommended deployment method for production environments, deploying only the Langflow backend API service without a visual interface. +Runtime mode drops the React IDE frontend and runs only the backend REST API. This is the recommended deployment shape for production API-serving scenarios. #### 6.1 Enable Runtime Mode -Runtime mode (backend-only) can be enabled by setting the following fields: +Two fields together enable full runtime mode: + +- `spec.langflow.backend.backendOnly: true` — starts the backend with `--backend-only` (backend is already the default in the current chart, but keep this explicit). +- `spec.langflow.frontend.enabled: false` — the chart skips the frontend Deployment entirely (verified: `kubectl get deploy -n ` returns 0 resources; only the backend StatefulSet remains). + +Optionally auto-import flows from a PVC or ConfigMap: ```yaml -langflow: - backendOnly: true # Enable backend-only mode - env: - - name: LANGFLOW_LOAD_FLOWS_PATH # Set the path to load Flows - value: "/app/flows" - volumes: - - name: flows # Load Flows content through volume - persistentVolumeClaim: # From PVC or other volumes - claimName: langflow-flows-pvc - volumeMounts: # Mount volume to specified path - - name: flows - mountPath: /app/flows +spec: + langflow: + backend: + backendOnly: true + env: + - name: LANGFLOW_LOAD_FLOWS_PATH + value: "/app/flows" + volumes: + - name: flows + persistentVolumeClaim: {claimName: langflow-flows-pvc} + volumeMounts: + - name: flows + mountPath: /app/flows + frontend: + enabled: false ``` -When enabling `LANGFLOW_LOAD_FLOWS_PATH`, authentication must be disabled, i.e., `langflow.auth.enabled` must be set to `false`. + +When enabling `LANGFLOW_LOAD_FLOWS_PATH`, keep `LANGFLOW_AUTO_LOGIN=true` (auto-login mode) — this is a Langflow constraint: user-owned auto-imported flows require the auto-login default user to be present. ## Access Address -### 1. Access via Service +### 1. Access via Gateway API (recommended) -`Langflow` provides external access through `Service`. Check its `Service` to get the access address. +When the Gateway API path from [Configure External Access](#3-configure-external-access) is applied, the assigned NodePort or LoadBalancer address of the Gateway's data-plane Service is the entry point. Example: -- If OAuth2 proxy is not enabled, Service name is: `` -- If OAuth2 proxy is enabled, Service name is: `-oauth2-proxy` +```bash +# Discover the envoy data-plane Service's NodePort (or LoadBalancer address) +kubectl get svc -A -l gateway.envoyproxy.io/owning-gateway-name=langflow-gw + +# Reach Langflow through any cluster node's IP + that NodePort +curl http://:/health_check +# Or open http://:/ in a browser to see the Langflow IDE +``` -If the `Service` type is `LoadBalancer` and the load balancer controller in the environment has assigned an access address, please access through that address. +### 2. Access via In-Cluster Port-Forward (development only) -If the `Service` type is `LoadBalancer` or `NodePort`, access is available through `node IP` with its `NodePort`. +```bash +kubectl port-forward -n svc/langflow-service 8080:8080 +# open http://localhost:8080/ +``` -### 2. Access via Ingress +### 3. Access via Ingress -If Ingress is enabled, please access through the configured domain name. +If Ingress was enabled via `spec.langflow.ingress.enabled=true`, use the configured hostname (DNS resolution and TLS certificate must be prepared by the cluster operator). # Langflow Quickstart @@ -305,27 +337,28 @@ data: ``` -### 1.2 Mount ConfigMap to Container +### 1.2 Mount ConfigMap to the backend container -In Langflow configuration, mount the ConfigMap to a specified directory in the container: +Add the ConfigMap as a volume and expose the mount path through `LANGFLOW_LOAD_FLOWS_PATH`. The upstream chart appends any user-provided volumes/volumeMounts to those it ships by default: ```yaml -langflow: - volumes: - - name: flows - configMap: - name: langflow-flows # ConfigMap name - volumeMounts: - - name: flows - mountPath: /app/flows # Mount path - env: - - name: LANGFLOW_LOAD_FLOWS_PATH # Set the path to load Flow files - value: /app/flows +spec: + langflow: + backend: + volumes: + - name: flows + configMap: {name: langflow-flows} + volumeMounts: + - name: flows + mountPath: /app/flows + env: + - name: LANGFLOW_LOAD_FLOWS_PATH + value: /app/flows ``` ### 1.3 Auto Import -After configuration, Langflow will automatically scan and import JSON files in the `LANGFLOW_LOAD_FLOWS_PATH` directory on startup. +After the backend restarts, Langflow scans `LANGFLOW_LOAD_FLOWS_PATH` and auto-imports every `*.json` file in it as a Flow. Since flow ownership is tied to a user, the auto-import mode requires `LANGFLOW_AUTO_LOGIN=true` (the default) — the imported flows are attached to the built-in default user. With authentication enabled (`LANGFLOW_AUTO_LOGIN=false`), user-owned imports are not supported by the upstream chart; use the REST API (`POST /api/v1/flows/` with a Bearer token) instead. ## 2. Using Models @@ -350,17 +383,18 @@ This approach is suitable for scenarios where: #### 2.2.1 Mount Model Files via Volume -Store model files in persistent volumes and provide them to the Langflow container through Volume mounts: +Store model files in persistent volumes and provide them to the Langflow backend container through additional volumes/volumeMounts: ```yaml -langflow: - volumes: - - name: models # Model storage volume - persistentVolumeClaim: - claimName: langflow-models-pvc - volumeMounts: # Mount model volume to specified path - - name: models - mountPath: /opt/models +spec: + langflow: + backend: + volumes: + - name: models + persistentVolumeClaim: {claimName: langflow-models-pvc} + volumeMounts: + - name: models + mountPath: /opt/models ``` #### 2.2.2 Upload Models @@ -381,20 +415,21 @@ In production environments, when using custom components, additional Python pack ### 3.1 Mount Dependencies via PVC -Mount a directory using PVC to store additional Python packages. +Mount a directory using PVC to store additional Python packages: ```yaml -langflow: - volumes: - - name: python-packages - persistentVolumeClaim: - claimName: langflow-packages-pvc # PVC name for storing additional Python packages - volumeMounts: - - name: python-packages - mountPath: /opt/python-packages # Mount path - env: - - name: PYTHONPATH # Set Python module search path - value: "/opt/python-packages" +spec: + langflow: + backend: + volumes: + - name: python-packages + persistentVolumeClaim: {claimName: langflow-packages-pvc} + volumeMounts: + - name: python-packages + mountPath: /opt/python-packages + env: + - name: PYTHONPATH + value: "/opt/python-packages" ``` ### 3.2 Install Dependencies @@ -415,27 +450,31 @@ Flow component configurations often need different values in different environme ### 4.1 Configure Environment Variables -Add environment variables in `Custom Values` as shown in the following example: +Add environment variables under `spec.langflow.backend.env` as shown: ```yaml -langflow: - env: - - name: LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT - value: VAR1,VAR2,VAR3 # List environment variable names that Langflow can automatically load, separated by commas - - name: VAR1 # Set environment variable value, environment variable name matches Langflow global variable name - value: xxx - - name: VAR2 # Can also load value from ConfigMap - valueFrom: - configMapKeyRef: - name: langflow-configs - key: var2 - - name: VAR3 # Sensitive information should be stored using Secret - valueFrom: - secretKeyRef: - name: langflow-secrets - key: var3 +spec: + langflow: + backend: + env: + - name: LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT + value: VAR1,VAR2,VAR3 # Comma-separated list of env-var names Langflow will surface as Global Variables + - name: VAR1 + value: xxx # Plain literal + - name: VAR2 + valueFrom: + configMapKeyRef: + name: langflow-configs + key: var2 # From ConfigMap + - name: VAR3 + valueFrom: + secretKeyRef: + name: langflow-secrets + key: var3 # From Secret (recommended for sensitive values) ``` +Verified: with `LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT=MY_PLAIN_VAR,MY_SECRET_KEY` on the wrap CR, `GET /api/v1/variables/` returns both entries with `type: Credential`, ready to be referenced from flow components. + ### 4.2 Use Global Variables in Flows In Langflow's flow editor: @@ -454,60 +493,75 @@ To improve performance, security, and stability in production environments, the Langflow collects usage data by default. In production environments, this feature can be disabled to protect privacy and reduce network requests: ```yaml -langflow: - env: - - name: DO_NOT_TRACK # Disable usage tracking - value: "true" +spec: + langflow: + backend: + env: + - name: DO_NOT_TRACK + value: "true" ``` ### 5.2 Disable Transaction Logs -During each request processing, Langflow records the input, output, and execution logs of each component to the database, which is the information shown in the Langflow IDE's Logs panel. -In production environments, this logging can be disabled to improve performance and reduce database pressure. +Langflow records the input, output, and execution log of each component to the database (visible in the IDE's Logs panel). Disabling reduces database write pressure: ```yaml -langflow: - env: - - name: LANGFLOW_TRANSACTIONS_STORAGE_ENABLED - value: "false" # Disable transaction logs +spec: + langflow: + backend: + env: + - name: LANGFLOW_TRANSACTIONS_STORAGE_ENABLED + value: "false" ``` ### 5.3 Set Worker Process Count ```yaml -langflow: - numWorkers: 1 # Set number of worker processes +spec: + langflow: + backend: + numWorkers: 1 # gunicorn worker count (default: 1) ``` ### 5.4 Configure Resource Limits -It is recommended to configure appropriate resource limits for the Langflow container. The following YAML is only an example; adjust the values according to actual requirements: +It is recommended to configure appropriate resource limits for the backend and frontend containers separately. Sample values (adjust to your workload): ```yaml -langflow: - resources: - requests: - cpu: "2" - memory: "4Gi" - limits: - cpu: "4" - memory: "8Gi" +spec: + langflow: + backend: + resources: + requests: {cpu: "2", memory: "4Gi"} + limits: {cpu: "4", memory: "8Gi"} + frontend: + resources: + requests: {cpu: "0.3", memory: "512Mi"} ``` -### 5.5 Set API Keys +### 5.5 Use API Keys -1. Go to the **Settings** page -2. In the **Langflow API Keys** section, add API keys -3. When making API requests, add the `x-api-key: ` header; otherwise, a 401 error (unauthorized request) will be returned +Langflow supports `x-api-key`-based authentication for REST requests. Two ways to create a key: -### 5.6 Disable UI +1. **Via the IDE (Settings → Langflow API Keys)**: click "Add New" and give the key a name; Langflow returns the key value once (store it immediately). +2. **Via REST**: `POST /api/v1/api_key/` with a Bearer token in `Authorization`: + ```bash + curl -X POST http:///api/v1/api_key/ \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{"name":"my-key"}' + ``` + The response body contains `api_key` — record it. -Runtime mode allows Langflow to run without a browser interface, suitable for API service scenarios in production environments. +Use the key by sending `x-api-key: ` on subsequent requests: +- Valid key → `200` +- Missing / wrong key → `403` -```yaml -langflow: - backendOnly: true # Enable backend-only mode -``` +Verified with the e2e smoke H probe on 4.3-x86: creating a key + hitting `/api/v1/all` with the valid key returns 200 with the full component catalog; hitting the same endpoint with a wrong key returns 403. + +### 5.6 Disable UI + +See [Configure Runtime Mode](#6-configure-runtime-mode-backend-only) — set both `backend.backendOnly=true` and `frontend.enabled=false` to actually drop the frontend Deployment. ### 5.7 Reference Official Documentation diff --git a/docs/zh/solutions/How_to_install_and_use_Langflow.md b/docs/zh/solutions/How_to_install_and_use_Langflow.md index 0dcb03d9a..2a26e2de1 100644 --- a/docs/zh/solutions/How_to_install_and_use_Langflow.md +++ b/docs/zh/solutions/How_to_install_and_use_Langflow.md @@ -40,253 +40,284 @@ Langflow 提供了一个拖放可视化界面,用于构建具有实时测试 ## 发布 -下载 Langflow 安装文件:`langflow.ALL.v1.6.4-1.tgz` +下载 Langflow 安装文件:`langflow-operator.alpha.ALL.v1.10.1.tgz` 使用 violet 命令发布到平台仓库: ```bash -violet push --platform-address=platform-access-address --platform-username=platform-admin --platform-password=platform-admin-password langflow.ALL.v1.6.4-1.tgz +violet push --platform-address=platform-access-address --platform-username=platform-admin --platform-password=platform-admin-password langflow-operator.alpha.ALL.v1.10.1.tgz ``` -## 部署 +自 v1.10.1 起,Langflow 以 OLM `OperatorBundle` 形式打包(chart-wrap 封装上游 `langflow-ai/langflow-helm-charts/langflow-ide` chart),不再是原始 Helm chart。安装走 OperatorHub + `Langflow` 自定义资源,而不是 Applications / Catalog 表单。 -### 准备存储 +## 前置条件 -Langflow 支持两种数据库模式: +安装 Langflow 前,目标业务集群必须满足: -- **SQLite(默认)**:用于开发和测试,数据存储在持久卷中 -- **PostgreSQL(推荐)**:用于生产环境,提供更好的性能和可扩展性 +- **存在默认 StorageClass** —— Langflow backend 默认走 SQLite,使用 RWO PVC 拉取集群的默认 StorageClass。若无默认 SC,`data-langflow-service-0` PVC 会永远 `Pending`、backend pod 无法调度。设置默认 SC: -集群需要预先安装 CSI 或预先准备 `PersistentVolume`。 + ```bash + kubectl get sc + kubectl patch sc -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' + ``` -### 准备数据库 + 若希望显式指定 SC 而非依赖集群默认,可在 `Langflow` 自定义资源上设 `spec.langflow.backend.sqlite.volume.existingStorageClassName`(见 [配置存储](#1-配置存储))。 -#### 使用 SQLite(默认) +- **(可选,用于 Gateway API 外部访问)** 集群已安装 Envoy Gateway,且存在一个 `controllerName` 中包含 `envoy` 的 `GatewayClass`。若无,用户只能通过 `kubectl port-forward` 或手动创建 NodePort/LoadBalancer Service 访问。 -SQLite 是 Langflow 的默认数据库,适合开发和测试环境: +## 部署 -- 数据存储在持久卷中 -- 配置简单,无需额外设置 -- 支持单实例部署 +### 准备存储 -#### 使用 PostgreSQL(推荐) +Langflow 默认使用 SQLite + RWO PVC (1Gi)。生产建议 PostgreSQL(见 [配置数据库](#2-配置数据库))。集群必须有默认 StorageClass,或用户显式设置 `existingStorageClassName`。 -强烈建议在生产环境中使用 PostgreSQL,以获得更好的性能和可扩展性: +### 准备数据库(可选) -可以使用 `Data Services` 提供的 `PostgreSQL operator` 创建 `PostgreSQL 集群`。 +#### 使用 SQLite(默认) -检查 `Data Services` 中 `PostgreSQL` 实例详细信息中的访问地址和密码。 +SQLite 是 Langflow 的默认数据库: + +- 数据存储在 RWO PVC(`data-langflow-service-0`,默认 1Gi) +- 无需额外基础设施 +- 仅支持单实例 backend(StatefulSet 副本数 = 1) + +#### 使用 PostgreSQL(生产推荐) + +生产环境强烈建议 PostgreSQL: + +- 可通过 `Data Services` 的 PostgreSQL Operator 部署,或使用集群可达的任意外部 PostgreSQL。 +- 需要预先创建独立的数据库和具备 `CREATE`/`CONNECT` 权限的用户。Langflow backend 首次启动时会通过 Alembic 建表。 **注意**: -- 推荐使用 PostgreSQL 版本 12 或更高 -- 需要创建单独的数据库和用户 -- 确保网络连接 +- 推荐 PostgreSQL 12 及以上 +- 确保 Langflow 命名空间到 PostgreSQL 实例的网络连通 +- 密码存 Kubernetes `Secret`,通过 `secretKeyRef` 引用(见 [配置数据库](#2-配置数据库)) + +### 安装 Operator 并创建 Langflow -### 创建应用程序 +1. 在 `Alauda Container Platform` 中打开 `OperatorHub`,搜索 `Langflow`。从 `platform` 目录源安装 `Langflow`(默认:channel `alpha`,安装模式 `AllNamespaces`)。 -1. 转到 `Alauda Container Platform` 视图,选择将要部署 Langflow 的命名空间。 +2. 等待 CSV `langflow-operator.v1.10.1` 达到 `Succeeded`。 -2. 在左侧导航中选择 `Applications` / `Applications`,然后点击右侧页面的 `Create` 按钮。 +3. 为 Langflow 实例创建一个命名空间(建议默认:`langflow-system`)。 -3. 在弹出对话框中选择 `Create from Catalog`,然后页面将跳转到 `Catalog` 视图。 +4. 在该命名空间下 apply 一个 `Langflow` 自定义资源。最简形式: -4. 找到 `3rdparty/chart-langflow` 并点击 `Create` 创建此应用程序。 + ```yaml + apiVersion: langflow-operator.alauda.io/v1 + kind: Langflow + metadata: + name: langflow + namespace: langflow-system + spec: {} + ``` -5. 在 `Catalog` / `Create langflow` 表单中,填写 `Name`(推荐为 `langflow`)和 `Values` 中的 `Custom` 配置,然后点击 `Create` 按钮完成创建。`Custom` 内容将在下面描述。创建后也可以通过 `Update` 应用程序方法进行修改。 + 空 `spec: {}` 走 chart 默认(SQLite on 集群默认 SC、IDE 模式、ClusterIP Services、Ingress 关)。如需自定义,按下文各段落把字段加到 `spec.langflow.*` —— wrap CR spec 与上游 chart `values.yaml` 结构镜像对应。完整字段清单见上游 [`values.yaml`](https://github.com/langflow-ai/langflow-helm-charts/blob/langflow-ide-0.1.2/charts/langflow-ide/values.yaml)。 ## 配置 -用户可以修改 `Application` 的 `Custom Values` 以调整配置。主要关注的配置如下: +用户通过编辑 `Langflow` 自定义资源的 `spec.langflow.*` 字段调整配置。Wrap CR spec 与上游 `langflow-ide` chart 的 `values.yaml` 结构镜像对应。主要关注的配置如下。 ### 1. 配置存储 #### 1.1 配置 SQLite 存储(默认) -可以通过添加以下配置来指定存储类和大小: +通过如下配置指定 StorageClass 和卷大小: ```yaml -langflow: - sqlite: - volume: - storageClassName: storage-class-name # 替换为实际的存储类名称 - size: 1Gi # 替换为实际所需空间大小 +spec: + langflow: + backend: + sqlite: + volume: + existingStorageClassName: # 集群 SC 名称;保留 "default" 表示使用集群默认 SC + size: 1Gi # PVC 大小 ``` -**注意**:使用 SQLite 时,仅支持单实例部署(replicaCount = 1)。 +**注意**: + +- `existingStorageClassName: "default"` 是 chart 里的**特殊字符串**,表示"使用集群默认 SC"(即标了 `storageclass.kubernetes.io/is-default-class: "true"` 的那个 SC)。填写显式 SC 名称即可覆盖。 +- 使用 SQLite 时仅支持单实例 backend(StatefulSet 副本数 = 1)。 ### 2. 配置数据库 #### 2.1 启用 PostgreSQL -可以通过设置以下字段配置 PostgreSQL 访问信息: +通过设置以下字段配置 PostgreSQL 访问信息: ```yaml -langflow: - externalDatabase: - enabled: true # 启用外部数据库 - driver: - value: "postgresql" - host: - value: postgres-host # PostgreSQL 访问地址 - port: - value: "5432" # PostgreSQL 访问端口,默认:5432 - database: - value: langflow # 数据库名称,注意:数据库将自动创建 - user: - value: langflow # 数据库用户名 - password: - valueFrom: - secretKeyRef: - name: postgres-secret # 存储数据库访问密码的秘密名称 - key: password # 存储数据库访问密码的秘密键 +spec: + langflow: + backend: + externalDatabase: + enabled: true # 启用外部数据库 + driver: {value: "postgresql"} + host: {value: } # PostgreSQL 主机(Service DNS 或外部地址) + port: {value: "5432"} + database: {value: langflow} # 目标数据库(backend 启动前必须存在) + user: {value: langflow} + password: + valueFrom: + secretKeyRef: + name: postgres-secret # 存密码的 Secret + key: password ``` -**注意**:由于临时存储限制,当前版本暂时不支持多实例部署。即使配置了 PostgreSQL 数据库,仅支持单实例部署(replicaCount = 1)。 +Chart 在 backend 容器启动时执行一个 shim,读取上述 `LF_CHART_EXTERNALDB_*` 环境变量并拼成 `LANGFLOW_DATABASE_URL=postgresql://:@:/`,覆盖默认的 sqlite URL。实测已验证:backend 启动后连接 PostgreSQL,通过 Alembic 建立完整 schema(`alembic_version`、`flow`、`apikey`、`folder`、`message` 等),并把内置 starter projects 写入。 -### 3. 配置访问方式 +**注意**:SQLite 场景仅支持单实例 backend。要多实例必须 PostgreSQL,但当前 chart 仍默认 backend StatefulSet 副本数 = 1 —— 如需 HA 请显式扩容。 -默认情况下,使用 `LoadBalancer` 提供访问地址。 +### 3. 配置外部访问 -#### 3.1 修改服务类型 +上游 chart 默认只创建两个 `ClusterIP` Service: -可以通过设置以下字段修改 `Service` 类型: +- `langflow-service` 端口 8080 —— frontend(React IDE,由 nginx serve) +- `langflow-service-backend` 端口 7860 —— backend(FastAPI + `/api/v1/*`) -```yaml -langflow: - service: - type: LoadBalancer # 可以更改为 NodePort 或 ClusterIP - port: 7860 # 服务端口 -``` +Frontend nginx 内部把 `/api`、`/health` 与 `/health_check` 反代到 backend,因此**只把外部流量路由到 `langflow-service:8080` 就同时覆盖 SPA 和后端 API**,无需按路径拆多条规则。 + +**推荐路径:Gateway API(Envoy Gateway)** -#### 3.2 启用 Ingress +chart-wrap 在 oss-operator-factory 仓库的 `components/langflow/examples/gateway-httproute.example.yaml` 提供示例。集群运维在每个集群上一次性挂 `EnvoyProxy` + `Gateway`;用户在 Langflow 命名空间里挂一条 `HTTPRoute` 指向 `langflow-service:8080`。单条 rule + 单个 backend 即可,无需按 path 拆规则。 -可以通过设置以下字段配置 Ingress。启用 Ingress 后,服务类型通常更改为 ClusterIP: +最简 HTTPRoute 示例(假设 Gateway `langflow-gw` 已存在): ```yaml -ingress: - enabled: true # 启用 Ingress 功能 - hosts: - - host: langflow.example.com # 访问域名(必须是 DNS 名称,而不是 IP 地址) - paths: - - path: / - tls: - - secretName: langflow-tls # 存储 TLS 证书的秘密名称 - hosts: - - langflow.example.com +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: langflow + namespace: +spec: + parentRefs: + - {group: gateway.networking.k8s.io, kind: Gateway, name: langflow-gw, namespace: } + hostnames: [] + rules: + - matches: [{path: {type: PathPrefix, value: "/"}}] + backendRefs: + - {name: langflow-service, port: 8080} ``` -### 4. 配置身份验证和用户管理(可选) - -#### 4.1 启用用户身份验证 +**备选:上游 chart 自带 Ingress** -可以通过设置以下字段启用用户身份验证: +Chart 也提供 Ingress 字段(默认关)。通过 wrap CR 打开: ```yaml -langflow: - auth: - enabled: true # 启用身份验证 - superuser: - username: langflow # 超级用户名称 - password: "" # 超级用户密码,未设置时自动生成 - secretKey: "" # 秘密密钥,未设置时自动生成 - newUserActive: false # 新用户是否需要激活 - enableSuperuserCLI: false # 是否启用 CLI 超级用户 - accessTokenExpireSeconds: 3600 # 访问令牌过期时间(秒) - refreshTokenExpireSeconds: 604800 # 刷新令牌过期时间(秒) +spec: + langflow: + ingress: + enabled: true + hosts: + - host: langflow.example.com + paths: [{path: /, pathType: Prefix}] + tls: + - {secretName: langflow-tls, hosts: [langflow.example.com]} ``` -启用身份验证后,默认情况下: +注意: -- 需要登录才能访问 -- 可以配置超级用户 -- 新用户只能通过超级用户在 `/admin` 页面添加(不支持自我注册) -- 新用户账户激活:如果 `newUserActive=true`,新用户账户将自动激活;如果 `newUserActive=false`(默认),超级用户需要手动激活 +- chart 默认 `ingress.enabled: false`,wrap 保持不动 —— 预开在无对应 ingress class / 域名的集群上会失败。 +- **OAuth2 Proxy 不在上游 chart 里**。如需 SSO,需要另外部署一个 OAuth2 Proxy(或平台已有的 SSO 网关)作为 Langflow Service 前置,wrap 不管这个生命周期。跟平台上其他 chart-wrap 组件同套路。 -### 5. 配置 OAuth2 代理(可选) +### 4. 配置身份验证和用户管理(可选) -可以通过设置以下字段配置 OAuth2 代理,以提供单点登录功能: +上游社区 chart **不提供** `auth` 结构化字段。Langflow 的鉴权通过 backend 容器的环境变量控制。在 `spec.langflow.backend.env` 下设置: ```yaml -oauth2_proxy: - enabled: true # 启用 OAuth2 代理 - oidcIssuer: "https://x.x.x.com/dex" # OIDC 发行者地址 - oidcClientID: "your-client-id" # OIDC 客户端 ID - oidcClientSecret: "your-client-secret" # OIDC 客户端密钥(建议使用 Secret) +spec: + langflow: + backend: + env: + - name: LANGFLOW_AUTO_LOGIN + value: "false" # 关闭自动登录(默认:true) + - name: LANGFLOW_SUPERUSER + valueFrom: + secretKeyRef: {name: langflow-superuser, key: username} + - name: LANGFLOW_SUPERUSER_PASSWORD + valueFrom: + secretKeyRef: {name: langflow-superuser, key: password} + - name: LANGFLOW_NEW_USER_IS_ACTIVE + value: "false" # 新用户需超级用户激活(默认:false) + - name: LANGFLOW_ENABLE_SUPERUSER_CLI + value: "false" # 关闭 CLI 超级用户引导 ``` -要将 `Alauda Container Platform` 配置为 OIDC 提供者,请按如下方式配置: +`LANGFLOW_AUTO_LOGIN=false` 已实测行为: -- `oauth2_proxy.oidcIssuer` 是平台访问地址加上 `/dex` -- `oauth2_proxy.oidcClientID` 固定为 `langflow` -- `oauth2_proxy.oidcClientSecret` 固定为 `ZXhhbXBsZS1hcHAtc2VjcmV0` +- `GET /api/v1/auto_login` 返回 **403**(自动登录已关)。 +- `POST /api/v1/login` 用正确超级用户凭据返回 **200**,带 `access_token`。 +- `POST /api/v1/login` 用错误密码返回 **401**。 +- 受保护接口(如 `GET /api/v1/all`)用有效 Bearer token 返回 **200**,无 token 返回 **403**。 -还需要在 global 集群中创建 OAuth2Client 资源以配置 Langflow 的客户端信息: +注意: -```yaml -apiVersion: dex.coreos.com/v1 -kind: OAuth2Client -metadata: - name: nrqw4z3gnrxxps7sttsiiirdeu - namespace: cpaas-system -id: langflow # 与 values 中的 oauth2_proxy.oidcClientID 一致 -name: Langflow -secret: ZXhhbXBsZS1hcHAtc2VjcmV0 # 与 values 中的 oauth2_proxy.oidcClientSecret 一致 -redirectURIs: -- http://xxx.xxx.xxxx.xxx:xxxxx/* # OAuth2-Proxy 访问地址,获取方法如下 - # 如果部署多个 Langflow 实例,请在此处添加多个访问地址 -``` +- `LANGFLOW_AUTO_LOGIN=false` 下不支持自注册。新用户必须由超级用户在 `/admin` 添加;如 `LANGFLOW_NEW_USER_IS_ACTIVE=false`,超级用户还需手动激活账户方可登录。 +- 超级用户凭据**只在首次启动**时消费。一旦写入数据库(SQLite 或 PostgreSQL),只改环境变量**不会**轮换凭据 —— 后续修改必须走 Langflow 管理界面或数据库迁移。 +- 访问/刷新 token 过期时间由 `LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS` / `LANGFLOW_REFRESH_TOKEN_EXPIRE_SECONDS` 控制(默认较保守,非必要不要动)。 -**注意**:OAuth2 代理访问地址可以从 `-oauth2-proxy` 服务中获取,根据服务类型使用适当的访问方法。 +### 5. 单点登录(SSO) -启用 OAuth2 代理后,建议: - -- 将 `langflow.service.type` 设置为 `ClusterIP`,仅允许在集群内访问。用户需要通过 OAuth2 代理地址访问 Langflow。 -- 将 `langflow.auth.enabled` 设置为 `false`。使用 OAuth2 代理处理登录身份验证。 - -用户可以通过访问 `/oauth2/sign_out` 登出。 +上游 `langflow-ide` chart **不包含 OAuth2 Proxy 边车或独立 Deployment**。如需 SSO,需要在 Langflow frontend Service 前面另外部署 OAuth2 Proxy(或平台已有的 SSO 网关)作为独立工作负载 —— wrap CR 不管这一段的生命周期,跟平台上其他 chart-wrap 组件同套路。将 OAuth2 Proxy 上游指向 `langflow-service:8080`,同时把 backend 的 `LANGFLOW_AUTO_LOGIN=false`,让 proxy 成为唯一的鉴权入口。 ### 6. 配置运行时模式(仅后端) -运行时模式是推荐的生产环境部署方法,仅部署 Langflow 后端 API 服务,而不提供可视化界面。 +运行时模式去掉 React IDE 前端,只跑 backend REST API,适合生产 API 服务场景。 #### 6.1 启用运行时模式 -可以通过设置以下字段启用运行时模式(仅后端): +需要同时设置两个字段才是完整的 runtime mode: + +- `spec.langflow.backend.backendOnly: true` —— backend 启动带 `--backend-only`(当前 chart 里默认已 true,保留显式声明)。 +- `spec.langflow.frontend.enabled: false` —— chart 会**跳过 frontend Deployment**(实测:`kubectl get deploy -n ` 返回 0 条,只剩 backend StatefulSet)。 + +可选:自动从 PVC 或 ConfigMap 导入 flow: ```yaml -langflow: - backendOnly: true # 启用仅后端模式 - env: - - name: LANGFLOW_LOAD_FLOWS_PATH # 设置加载 Flows 的路径 - value: "/app/flows" - volumes: - - name: flows # 通过卷加载 Flows 内容 - persistentVolumeClaim: # 从 PVC 或其他卷 - claimName: langflow-flows-pvc - volumeMounts: # 将卷挂载到指定路径 - - name: flows - mountPath: /app/flows +spec: + langflow: + backend: + backendOnly: true + env: + - name: LANGFLOW_LOAD_FLOWS_PATH + value: "/app/flows" + volumes: + - name: flows + persistentVolumeClaim: {claimName: langflow-flows-pvc} + volumeMounts: + - name: flows + mountPath: /app/flows + frontend: + enabled: false ``` -启用 `LANGFLOW_LOAD_FLOWS_PATH` 时,必须禁用身份验证,即 `langflow.auth.enabled` 必须设置为 `false`。 +启用 `LANGFLOW_LOAD_FLOWS_PATH` 时,需要保留 `LANGFLOW_AUTO_LOGIN=true`(自动登录模式)—— 这是 Langflow 的约束:用户所有的自动导入 flow 需要 auto-login 默认用户存在。 ## 访问地址 -### 1. 通过服务访问 +### 1. 通过 Gateway API 访问(推荐) -`Langflow` 通过 `Service` 提供外部访问。检查其 `Service` 以获取访问地址。 +按 [配置外部访问](#3-配置外部访问) 挂上 Gateway API 后,Gateway 数据面 Service 的 NodePort 或 LoadBalancer 地址就是入口。例如: -- 如果未启用 OAuth2 代理,服务名称为:`` -- 如果启用 OAuth2 代理,服务名称为:`-oauth2-proxy` +```bash +# 查 envoy 数据面 Service 分配到的 NodePort(或 LoadBalancer 地址) +kubectl get svc -A -l gateway.envoyproxy.io/owning-gateway-name=langflow-gw -如果 `Service` 类型为 `LoadBalancer`,并且环境中的负载均衡控制器已分配访问地址,请通过该地址访问。 +# 用任意集群节点 IP + 该 NodePort 访问 Langflow +curl http://:/health_check +# 或浏览器打开 http://:/ 就是 Langflow IDE +``` -如果 `Service` 类型为 `LoadBalancer` 或 `NodePort`,可以通过 `node IP` 及其 `NodePort` 进行访问。 +### 2. 通过集群内 port-forward 访问(仅开发) -### 2. 通过 Ingress 访问 +```bash +kubectl port-forward -n svc/langflow-service 8080:8080 +# 浏览器打开 http://localhost:8080/ +``` -如果启用了 Ingress,请通过配置的域名访问。 +### 3. 通过 Ingress 访问 + +若通过 `spec.langflow.ingress.enabled=true` 打开了 Ingress,请通过配置的域名访问(DNS 解析 + TLS 证书需集群运维准备)。 # Langflow 快速入门 @@ -315,27 +346,28 @@ data: ``` -### 1.2 将 ConfigMap 挂载到容器 +### 1.2 将 ConfigMap 挂载到 backend 容器 -在 Langflow 配置中,将 ConfigMap 挂载到容器中的指定目录: +把 ConfigMap 作为 volume 加进来,并通过 `LANGFLOW_LOAD_FLOWS_PATH` 暴露挂载路径。上游 chart 会把用户提供的 volumes/volumeMounts 追加到自带的 default 之后: ```yaml -langflow: - volumes: - - name: flows - configMap: - name: langflow-flows # ConfigMap 名称 - volumeMounts: - - name: flows - mountPath: /app/flows # 挂载路径 - env: - - name: LANGFLOW_LOAD_FLOWS_PATH # 设置加载流程文件的路径 - value: /app/flows +spec: + langflow: + backend: + volumes: + - name: flows + configMap: {name: langflow-flows} + volumeMounts: + - name: flows + mountPath: /app/flows + env: + - name: LANGFLOW_LOAD_FLOWS_PATH + value: /app/flows ``` ### 1.3 自动导入 -配置完成后,Langflow 将在启动时自动扫描并导入 `LANGFLOW_LOAD_FLOWS_PATH` 目录中的 JSON 文件。 +backend 重启后,Langflow 扫描 `LANGFLOW_LOAD_FLOWS_PATH` 并自动把里面每个 `*.json` 导入为 Flow。由于 flow 归属绑定用户,自动导入模式需要 `LANGFLOW_AUTO_LOGIN=true`(默认)—— 导入的 flow 会归到内置的默认用户。开鉴权后(`LANGFLOW_AUTO_LOGIN=false`),上游 chart 不支持用户归属的自动导入,请改用 REST API(`POST /api/v1/flows/` + Bearer token)。 ## 2. 使用模型 @@ -362,17 +394,18 @@ langflow: #### 2.2.1 通过卷挂载模型文件 -将模型文件存储在持久卷中,并通过卷挂载将其提供给 Langflow 容器: +将模型文件存到持久卷,通过附加 volume/volumeMount 挂给 Langflow backend 容器: ```yaml -langflow: - volumes: - - name: models # 模型存储卷 - persistentVolumeClaim: - claimName: langflow-models-pvc - volumeMounts: # 将模型卷挂载到指定路径 - - name: models - mountPath: /opt/models +spec: + langflow: + backend: + volumes: + - name: models + persistentVolumeClaim: {claimName: langflow-models-pvc} + volumeMounts: + - name: models + mountPath: /opt/models ``` #### 2.2.2 上传模型 @@ -393,20 +426,21 @@ kubectl cp -n :/opt/m ### 3.1 通过 PVC 挂载依赖 -使用 PVC 挂载一个目录以存储额外的 Python 包。 +用 PVC 挂载一个目录存放额外的 Python 包: ```yaml -langflow: - volumes: - - name: python-packages - persistentVolumeClaim: - claimName: langflow-packages-pvc # 存储额外 Python 包的 PVC 名称 - volumeMounts: - - name: python-packages - mountPath: /opt/python-packages # 挂载路径 - env: - - name: PYTHONPATH # 设置 Python 模块搜索路径 - value: "/opt/python-packages" +spec: + langflow: + backend: + volumes: + - name: python-packages + persistentVolumeClaim: {claimName: langflow-packages-pvc} + volumeMounts: + - name: python-packages + mountPath: /opt/python-packages + env: + - name: PYTHONPATH + value: "/opt/python-packages" ``` ### 3.2 安装依赖 @@ -427,27 +461,31 @@ pip install --target /opt/python-packages -r requirements.txt ### 4.1 配置环境变量 -在 `Custom Values` 中添加环境变量,如下所示: +在 `spec.langflow.backend.env` 下添加环境变量: ```yaml -langflow: - env: - - name: LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT - value: VAR1,VAR2,VAR3 # 列出 Langflow 可以自动加载的环境变量名称,以逗号分隔 - - name: VAR1 # 设置环境变量值,环境变量名称与 Langflow 全局变量名称匹配 - value: xxx - - name: VAR2 # 也可以从 ConfigMap 加载值 - valueFrom: - configMapKeyRef: - name: langflow-configs - key: var2 - - name: VAR3 # 敏感信息应使用 Secret 存储 - valueFrom: - secretKeyRef: - name: langflow-secrets - key: var3 +spec: + langflow: + backend: + env: + - name: LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT + value: VAR1,VAR2,VAR3 # 逗号分隔,列出会被 Langflow 变成全局变量的 env 名字 + - name: VAR1 + value: xxx # 明文值 + - name: VAR2 + valueFrom: + configMapKeyRef: + name: langflow-configs + key: var2 # 从 ConfigMap + - name: VAR3 + valueFrom: + secretKeyRef: + name: langflow-secrets + key: var3 # 从 Secret(敏感值推荐用这个) ``` +实测已验证:wrap CR 上 `LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT=MY_PLAIN_VAR,MY_SECRET_KEY` + 对应的 env 定义,backend 启动后 `GET /api/v1/variables/` 返回两条 `type: Credential` 的条目,可直接被 flow 组件引用。 + ### 4.2 在流程中使用全局变量 在 Langflow 的流程编辑器中: @@ -466,60 +504,76 @@ langflow: Langflow 默认收集使用数据。在生产环境中,可以禁用此功能以保护隐私并减少网络请求: ```yaml -langflow: - env: - - name: DO_NOT_TRACK # 禁用使用跟踪 - value: "true" +spec: + langflow: + backend: + env: + - name: DO_NOT_TRACK + value: "true" ``` ### 5.2 禁用事务日志 -在每次请求处理期间,Langflow 会将每个组件的输入、输出和执行日志记录到数据库中,这些信息显示在 Langflow IDE 的日志面板中。 -在生产环境中,可以禁用此日志记录以提高性能并减少数据库压力。 +Langflow 每次处理请求都会把每个组件的输入、输出、执行日志写到数据库(IDE Logs 面板可看)。关掉能减少数据库写压力: ```yaml -langflow: - env: - - name: LANGFLOW_TRANSACTIONS_STORAGE_ENABLED - value: "false" # 禁用事务日志 +spec: + langflow: + backend: + env: + - name: LANGFLOW_TRANSACTIONS_STORAGE_ENABLED + value: "false" ``` ### 5.3 设置工作进程数量 ```yaml -langflow: - numWorkers: 1 # 设置工作进程数量 +spec: + langflow: + backend: + numWorkers: 1 # gunicorn worker 数(默认:1) ``` ### 5.4 配置资源限制 -建议为 Langflow 容器配置适当的资源限制。以下 YAML 仅为示例;根据实际需求调整值: +建议分别为 backend 和 frontend 容器配置资源限制。以下示例仅供参考,按实际负载调整: ```yaml -langflow: - resources: - requests: - cpu: "2" - memory: "4Gi" - limits: - cpu: "4" - memory: "8Gi" +spec: + langflow: + backend: + resources: + requests: {cpu: "2", memory: "4Gi"} + limits: {cpu: "4", memory: "8Gi"} + frontend: + resources: + requests: {cpu: "0.3", memory: "512Mi"} ``` -### 5.5 设置 API 密钥 +### 5.5 使用 API 密钥 -1. 转到 **设置** 页面 -2. 在 **Langflow API 密钥** 部分,添加 API 密钥 -3. 在进行 API 请求时,添加 `x-api-key: ` 头;否则将返回 401 错误(未经授权的请求) +Langflow 支持 REST 请求走 `x-api-key` 鉴权。两种方式建 key: -### 5.6 禁用 UI +1. **在 IDE 内**(Settings → Langflow API Keys):点击 "Add New" 给 key 起个名字,Langflow 只显示一次密钥值,请立即记录。 +2. **走 REST**:`POST /api/v1/api_key/` 带 Bearer token: + ```bash + curl -X POST http:///api/v1/api_key/ \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{"name":"my-key"}' + ``` + 响应体里的 `api_key` 就是要记录的 key。 -运行时模式允许 Langflow 在没有浏览器界面的情况下运行,适合生产环境中的 API 服务场景。 +后续请求带 `x-api-key: ` header: -```yaml -langflow: - backendOnly: true # 启用仅后端模式 -``` +- 有效 key → `200` +- 缺 / 错 → `403` + +e2e smoke H 探针在 4.3-x86 上已实测:建 key + 用有效 key 打 `/api/v1/all` 返回 200(含完整组件目录);用错误 key 打同接口返回 403。 + +### 5.6 禁用 UI + +参考 [配置运行时模式](#6-配置运行时模式仅后端) —— 同时设置 `backend.backendOnly=true` 和 `frontend.enabled=false` 才能真正跳过 frontend Deployment。 ### 5.7 参考官方文档 From f9c9565f7e27d48cc008b0640d7ff43bafb771af Mon Sep 17 00:00:00 2001 From: luohua13 Date: Tue, 7 Jul 2026 14:56:31 +0000 Subject: [PATCH 2/4] docs(langflow): every parameter re-validated on 4.3, drop SSO + zh + Ingress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer asked for every parameter to be verified against a live install before it lands in the doc. Ran a fresh langflow-batch install on business-1 (ACP 4.3) exercising the full Production Recommendations surface at once: - §5.3 numWorkers=2 → LANGFLOW_NUM_WORKERS=2 env set correctly - §5.4 resources → pod containers[0].resources matches CR (requests cpu:500m/mem:1Gi, limits cpu:2/mem:4Gi) - §5.1 DO_NOT_TRACK=true → env visible in container - §5.2 LANGFLOW_TRANSACTIONS_STORAGE_ENABLED=false → /monitor/transactions returns {"items":[],"total":0} - ConfigMap flow auto-import via LANGFLOW_LOAD_FLOWS_PATH → after backend restart, GET /api/v1/flows returns 34 (33 starter + 1 imported hello-world) - Python deps via PVC + PYTHONPATH → env set, /opt/python-packages mounted writable Also caught a real trap during validation and made it a top-level warning in Configuration section: `spec.langflow.backend.volumes` (and volumeMounts) REPLACE the chart-default emptyDirs (tmp/data/db/flows) instead of appending. Adding a custom volume without re-declaring the defaults crashes the backend at startup: FileNotFoundError: [Errno 2] No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp', '/app'] (Langflow's entrypoint imports dill, which calls tempfile.gettempdir(); readOnlyRootFilesystem: true means /tmp must be a writable volume.) Every sample YAML that customizes volumes/volumeMounts (ConfigMap flow import, local models, Python deps, runtime mode) now includes the four required chart-default entries as boilerplate. This trap was caught live on ACP 4.3. Per reviewer feedback: - Delete Chinese doc (auto-translated, we only maintain English). - Delete Ingress content (platform standardises on Gateway API for chart- wrap components; Ingress is not the supported external-access path). - Delete SSO section entirely (upstream chart has no OAuth2 Proxy; users needing SSO should deploy their own gateway outside the wrap). Filename verified against real GA artifacts: langflow-operator.alpha.ALL.v1.10.1.tgz matches minio://packages/langflow-operator/v1.10/ path. --- .../How_to_install_and_use_Langflow.md | 119 ++-- .../How_to_install_and_use_Langflow.md | 583 ------------------ 2 files changed, 79 insertions(+), 623 deletions(-) delete mode 100644 docs/zh/solutions/How_to_install_and_use_Langflow.md diff --git a/docs/en/solutions/How_to_install_and_use_Langflow.md b/docs/en/solutions/How_to_install_and_use_Langflow.md index 640e330f7..dac04bf31 100644 --- a/docs/en/solutions/How_to_install_and_use_Langflow.md +++ b/docs/en/solutions/How_to_install_and_use_Langflow.md @@ -107,12 +107,37 @@ Production environments strongly recommend PostgreSQL: spec: {} ``` - Empty `spec: {}` uses the chart's defaults (SQLite on the cluster default StorageClass, IDE mode, ClusterIP Services, no Ingress). To customize, add fields under `spec.langflow.*` per the sections below — the wrap CR spec mirrors the upstream chart's `values.yaml` structure. See the upstream [`values.yaml`](https://github.com/langflow-ai/langflow-helm-charts/blob/langflow-ide-0.1.2/charts/langflow-ide/values.yaml) for the full field list. + Empty `spec: {}` uses the chart's defaults (SQLite on the cluster default StorageClass, IDE mode, ClusterIP Services only). To customize, add fields under `spec.langflow.*` per the sections below — the wrap CR spec mirrors the upstream chart's `values.yaml` structure. See the upstream [`values.yaml`](https://github.com/langflow-ai/langflow-helm-charts/blob/langflow-ide-0.1.2/charts/langflow-ide/values.yaml) for the full field list. ## Configuration Users can edit the `Langflow` custom resource's `spec.langflow.*` fields to customize the deployment. The wrap CR spec mirrors the upstream `langflow-ide` chart's `values.yaml` structure. The main configurations to focus on are as follows. +> **⚠ Array fields REPLACE chart defaults, they do not append.** +> When you set `spec.langflow.backend.volumes` (or `.volumeMounts`), the chart drops its own default `tmp` / `data` / `db` / `flows` `emptyDir` volumes and uses only what you provide. If you add a custom volume without re-declaring the defaults, the backend container will crash on startup with `FileNotFoundError: No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp', '/app']` (the Langflow entrypoint imports `dill`, which calls `tempfile.gettempdir()` — `readOnlyRootFilesystem: true` means `/tmp` must be a writable volume). +> +> If you customize `volumes` or `volumeMounts`, keep the four chart-default entries alongside your additions. Suggested minimal boilerplate: +> +> ```yaml +> spec: +> langflow: +> backend: +> volumes: +> - {name: langflow-tmp, emptyDir: {}} # /tmp — required (readOnly root FS) +> - {name: app-data, emptyDir: {}} # /app/data — chart default +> - {name: app-db, emptyDir: {}} # /app/db — chart default +> - {name: app-flows, emptyDir: {}} # /app/flows — chart default +> # ... your additions below +> volumeMounts: +> - {name: langflow-tmp, mountPath: /tmp} +> - {name: app-data, mountPath: /app/data} +> - {name: app-db, mountPath: /app/db} +> - {name: app-flows, mountPath: /app/flows} +> # ... your additions below +> ``` +> +> Sections below that add custom `volumes` (ConfigMap flow import, local models, Python deps) omit this boilerplate for brevity — remember to include it. This trap was caught live on ACP 4.3 during doc validation. + ### 1. Configure Storage #### 1.1 Configure SQLite Storage (Default) @@ -192,25 +217,8 @@ spec: - {name: langflow-service, port: 8080} ``` -**Alternative: upstream chart Ingress** - -The chart also exposes an Ingress block (default off). Enable via the wrap CR: - -```yaml -spec: - langflow: - ingress: - enabled: true - hosts: - - host: langflow.example.com - paths: [{path: /, pathType: Prefix}] - tls: - - {secretName: langflow-tls, hosts: [langflow.example.com]} -``` - Notes: -- The chart's default `ingress.enabled: false` is intentional in the wrap — pre-opening Ingress would fail on clusters with no matching ingress class or DNS. -- OAuth2 Proxy is **not** part of the upstream chart. If SSO is required, deploy an OAuth2 Proxy (or platform SSO) as a separate Deployment in front of the Langflow Service; the wrap does not manage its lifecycle. This is the same pattern used for other chart-wrap components on the platform. +- The chart also ships an Ingress block (default off), but the platform standardises on Gateway API for chart-wrap components — Ingress is not the supported external-access path for Langflow and is not covered by this document. ### 4. Configure Authentication and User Management (Optional) @@ -247,22 +255,18 @@ Notes: - The superuser credentials are only consumed on **first startup**. Once written into the database (SQLite or PostgreSQL), changing the env vars alone does not rotate them — the credential update must go through Langflow's admin UI or a DB migration. - Access/refresh token expiration are controlled by `LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS` / `LANGFLOW_REFRESH_TOKEN_EXPIRE_SECONDS` (defaults are conservative; adjust only if required). -### 5. Single Sign-On (SSO) - -The upstream `langflow-ide` chart **does not include an OAuth2 Proxy sidecar or Deployment**. If SSO is required, deploy an OAuth2 Proxy (or the platform's existing SSO gateway) as a separate workload in front of the Langflow frontend Service — this is outside the wrap CR's control surface and follows the same pattern used by other chart-wrap components on the platform. Configure the OAuth2 Proxy to point at `langflow-service:8080` as its upstream, and set `LANGFLOW_AUTO_LOGIN=false` on the backend so the proxy is the sole authentication entry point. - -### 6. Configure Runtime Mode (Backend-Only) +### 5. Configure Runtime Mode (Backend-Only) Runtime mode drops the React IDE frontend and runs only the backend REST API. This is the recommended deployment shape for production API-serving scenarios. -#### 6.1 Enable Runtime Mode +#### 5.1 Enable Runtime Mode Two fields together enable full runtime mode: - `spec.langflow.backend.backendOnly: true` — starts the backend with `--backend-only` (backend is already the default in the current chart, but keep this explicit). - `spec.langflow.frontend.enabled: false` — the chart skips the frontend Deployment entirely (verified: `kubectl get deploy -n ` returns 0 resources; only the backend StatefulSet remains). -Optionally auto-import flows from a PVC or ConfigMap: +Optionally auto-import flows from a PVC or ConfigMap. **Remember the [chart-defaults boilerplate](#configuration)** — mount the flows source under a distinct path (`/app/loaded-flows`) so it doesn't collide with the chart's own `/app/flows` `emptyDir`: ```yaml spec: @@ -271,13 +275,21 @@ spec: backendOnly: true env: - name: LANGFLOW_LOAD_FLOWS_PATH - value: "/app/flows" + value: "/app/loaded-flows" volumes: - - name: flows + - {name: langflow-tmp, emptyDir: {}} + - {name: app-data, emptyDir: {}} + - {name: app-db, emptyDir: {}} + - {name: app-flows, emptyDir: {}} + - name: loaded-flows persistentVolumeClaim: {claimName: langflow-flows-pvc} volumeMounts: - - name: flows - mountPath: /app/flows + - {name: langflow-tmp, mountPath: /tmp} + - {name: app-data, mountPath: /app/data} + - {name: app-db, mountPath: /app/db} + - {name: app-flows, mountPath: /app/flows} + - name: loaded-flows + mountPath: /app/loaded-flows frontend: enabled: false ``` @@ -306,9 +318,6 @@ kubectl port-forward -n svc/langflow-service 8080:8080 # open http://localhost:8080/ ``` -### 3. Access via Ingress - -If Ingress was enabled via `spec.langflow.ingress.enabled=true`, use the configured hostname (DNS resolution and TLS certificate must be prepared by the cluster operator). # Langflow Quickstart @@ -339,23 +348,35 @@ data: ### 1.2 Mount ConfigMap to the backend container -Add the ConfigMap as a volume and expose the mount path through `LANGFLOW_LOAD_FLOWS_PATH`. The upstream chart appends any user-provided volumes/volumeMounts to those it ships by default: +Add the ConfigMap as a volume and expose the mount path through `LANGFLOW_LOAD_FLOWS_PATH`. **Remember the "array replaces defaults" rule** — the four chart-default entries (`langflow-tmp` / `app-data` / `app-db` / `app-flows`) below the custom ConfigMap entry must stay in place: ```yaml spec: langflow: backend: volumes: - - name: flows + # chart defaults — required, do not omit + - {name: langflow-tmp, emptyDir: {}} + - {name: app-data, emptyDir: {}} + - {name: app-db, emptyDir: {}} + - {name: app-flows, emptyDir: {}} + # additional flows source + - name: loaded-flows configMap: {name: langflow-flows} volumeMounts: - - name: flows - mountPath: /app/flows + - {name: langflow-tmp, mountPath: /tmp} + - {name: app-data, mountPath: /app/data} + - {name: app-db, mountPath: /app/db} + - {name: app-flows, mountPath: /app/flows} + - name: loaded-flows + mountPath: /app/loaded-flows env: - name: LANGFLOW_LOAD_FLOWS_PATH - value: /app/flows + value: /app/loaded-flows ``` +Verified on ACP 4.3: with the above CR, restarting the backend caused Langflow to auto-import the `hello-world.json` file from the ConfigMap; `GET /api/v1/flows/` returns 34 flows (33 built-in starter projects + 1 imported). + ### 1.3 Auto Import After the backend restarts, Langflow scans `LANGFLOW_LOAD_FLOWS_PATH` and auto-imports every `*.json` file in it as a Flow. Since flow ownership is tied to a user, the auto-import mode requires `LANGFLOW_AUTO_LOGIN=true` (the default) — the imported flows are attached to the built-in default user. With authentication enabled (`LANGFLOW_AUTO_LOGIN=false`), user-owned imports are not supported by the upstream chart; use the REST API (`POST /api/v1/flows/` with a Bearer token) instead. @@ -383,16 +404,24 @@ This approach is suitable for scenarios where: #### 2.2.1 Mount Model Files via Volume -Store model files in persistent volumes and provide them to the Langflow backend container through additional volumes/volumeMounts: +Store model files in persistent volumes and provide them to the Langflow backend container through additional volumes/volumeMounts. **Remember the [chart-defaults boilerplate](#configuration)** — the four `emptyDir` entries must be included: ```yaml spec: langflow: backend: volumes: + - {name: langflow-tmp, emptyDir: {}} + - {name: app-data, emptyDir: {}} + - {name: app-db, emptyDir: {}} + - {name: app-flows, emptyDir: {}} - name: models persistentVolumeClaim: {claimName: langflow-models-pvc} volumeMounts: + - {name: langflow-tmp, mountPath: /tmp} + - {name: app-data, mountPath: /app/data} + - {name: app-db, mountPath: /app/db} + - {name: app-flows, mountPath: /app/flows} - name: models mountPath: /opt/models ``` @@ -415,16 +444,24 @@ In production environments, when using custom components, additional Python pack ### 3.1 Mount Dependencies via PVC -Mount a directory using PVC to store additional Python packages: +Mount a directory using PVC to store additional Python packages. **Remember the [chart-defaults boilerplate](#configuration)**: ```yaml spec: langflow: backend: volumes: + - {name: langflow-tmp, emptyDir: {}} + - {name: app-data, emptyDir: {}} + - {name: app-db, emptyDir: {}} + - {name: app-flows, emptyDir: {}} - name: python-packages persistentVolumeClaim: {claimName: langflow-packages-pvc} volumeMounts: + - {name: langflow-tmp, mountPath: /tmp} + - {name: app-data, mountPath: /app/data} + - {name: app-db, mountPath: /app/db} + - {name: app-flows, mountPath: /app/flows} - name: python-packages mountPath: /opt/python-packages env: @@ -432,6 +469,8 @@ spec: value: "/opt/python-packages" ``` +Verified on ACP 4.3: pod is Ready, `env` shows `PYTHONPATH=/opt/python-packages`, mount visible at that path. + ### 3.2 Install Dependencies When installing dependency packages, use the `pip --target` parameter to install packages to the PVC-mounted directory: diff --git a/docs/zh/solutions/How_to_install_and_use_Langflow.md b/docs/zh/solutions/How_to_install_and_use_Langflow.md deleted file mode 100644 index 2a26e2de1..000000000 --- a/docs/zh/solutions/How_to_install_and_use_Langflow.md +++ /dev/null @@ -1,583 +0,0 @@ ---- -products: - - Alauda AI -kind: - - Solution -ProductsVersion: - - 4.x -id: KB1762309013-4C37 -sourceSHA: de62ac771d9db6c326ce6a20a4713807868944f71427b629c6aa91caeef42adb ---- - -# Langflow - -## 概述 - -Langflow 是一个开源低代码工具,用于可视化构建和部署 AI 代理和工作流。它提供了一个拖放编辑器,可以快速创建、测试和迭代 AI 应用程序。Langflow 基于 Python 构建,包含一个 FastAPI 后端和一个基于 React 的可视化编辑器。它默认支持 SQLite,并建议在生产环境中使用 PostgreSQL。 - -它包含以下主要组件: - -- **前端界面**:基于 React 的可视化编辑器,支持拖放流程构建和实时测试 -- **后端服务**:基于 FastAPI 的网络服务,提供 REST API 和 MCP(模型上下文协议)支持 -- **数据库**:支持 SQLite(默认)和 PostgreSQL(推荐用于生产) - -## 核心概念 - -Langflow 是围绕几个核心概念构建的:**流程**(组织 AI 逻辑的可视化工作流)、**组件**(可重用的功能单元)、**代理**(具有工具调用和推理能力的智能代理)和 **API/MCP** 集成(支持 REST API 和模型上下文协议)。 - -Langflow 提供了一个拖放可视化界面,用于构建具有实时测试功能的 AI 应用程序,并拥有丰富的模板库。它支持多个 LLM 提供商、嵌入模型和向量数据库,能够实现灵活的多模型配置。该平台提供开发的 IDE 模式和生产部署的运行时模式,适合实验和企业使用。 - -有关核心概念、功能和使用的详细信息,请参阅 [官方文档](https://docs.langflow.org/)。 - -## 文档和参考 - -- **官方文档**: -- **GitHub 仓库**: - -# Langflow 部署指南 - -本节提供有关如何将 Langflow 部署到 Kubernetes 集群的详细说明和常见配置参数。 - -## 发布 - -下载 Langflow 安装文件:`langflow-operator.alpha.ALL.v1.10.1.tgz` - -使用 violet 命令发布到平台仓库: - -```bash -violet push --platform-address=platform-access-address --platform-username=platform-admin --platform-password=platform-admin-password langflow-operator.alpha.ALL.v1.10.1.tgz -``` - -自 v1.10.1 起,Langflow 以 OLM `OperatorBundle` 形式打包(chart-wrap 封装上游 `langflow-ai/langflow-helm-charts/langflow-ide` chart),不再是原始 Helm chart。安装走 OperatorHub + `Langflow` 自定义资源,而不是 Applications / Catalog 表单。 - -## 前置条件 - -安装 Langflow 前,目标业务集群必须满足: - -- **存在默认 StorageClass** —— Langflow backend 默认走 SQLite,使用 RWO PVC 拉取集群的默认 StorageClass。若无默认 SC,`data-langflow-service-0` PVC 会永远 `Pending`、backend pod 无法调度。设置默认 SC: - - ```bash - kubectl get sc - kubectl patch sc -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' - ``` - - 若希望显式指定 SC 而非依赖集群默认,可在 `Langflow` 自定义资源上设 `spec.langflow.backend.sqlite.volume.existingStorageClassName`(见 [配置存储](#1-配置存储))。 - -- **(可选,用于 Gateway API 外部访问)** 集群已安装 Envoy Gateway,且存在一个 `controllerName` 中包含 `envoy` 的 `GatewayClass`。若无,用户只能通过 `kubectl port-forward` 或手动创建 NodePort/LoadBalancer Service 访问。 - -## 部署 - -### 准备存储 - -Langflow 默认使用 SQLite + RWO PVC (1Gi)。生产建议 PostgreSQL(见 [配置数据库](#2-配置数据库))。集群必须有默认 StorageClass,或用户显式设置 `existingStorageClassName`。 - -### 准备数据库(可选) - -#### 使用 SQLite(默认) - -SQLite 是 Langflow 的默认数据库: - -- 数据存储在 RWO PVC(`data-langflow-service-0`,默认 1Gi) -- 无需额外基础设施 -- 仅支持单实例 backend(StatefulSet 副本数 = 1) - -#### 使用 PostgreSQL(生产推荐) - -生产环境强烈建议 PostgreSQL: - -- 可通过 `Data Services` 的 PostgreSQL Operator 部署,或使用集群可达的任意外部 PostgreSQL。 -- 需要预先创建独立的数据库和具备 `CREATE`/`CONNECT` 权限的用户。Langflow backend 首次启动时会通过 Alembic 建表。 - -**注意**: - -- 推荐 PostgreSQL 12 及以上 -- 确保 Langflow 命名空间到 PostgreSQL 实例的网络连通 -- 密码存 Kubernetes `Secret`,通过 `secretKeyRef` 引用(见 [配置数据库](#2-配置数据库)) - -### 安装 Operator 并创建 Langflow - -1. 在 `Alauda Container Platform` 中打开 `OperatorHub`,搜索 `Langflow`。从 `platform` 目录源安装 `Langflow`(默认:channel `alpha`,安装模式 `AllNamespaces`)。 - -2. 等待 CSV `langflow-operator.v1.10.1` 达到 `Succeeded`。 - -3. 为 Langflow 实例创建一个命名空间(建议默认:`langflow-system`)。 - -4. 在该命名空间下 apply 一个 `Langflow` 自定义资源。最简形式: - - ```yaml - apiVersion: langflow-operator.alauda.io/v1 - kind: Langflow - metadata: - name: langflow - namespace: langflow-system - spec: {} - ``` - - 空 `spec: {}` 走 chart 默认(SQLite on 集群默认 SC、IDE 模式、ClusterIP Services、Ingress 关)。如需自定义,按下文各段落把字段加到 `spec.langflow.*` —— wrap CR spec 与上游 chart `values.yaml` 结构镜像对应。完整字段清单见上游 [`values.yaml`](https://github.com/langflow-ai/langflow-helm-charts/blob/langflow-ide-0.1.2/charts/langflow-ide/values.yaml)。 - -## 配置 - -用户通过编辑 `Langflow` 自定义资源的 `spec.langflow.*` 字段调整配置。Wrap CR spec 与上游 `langflow-ide` chart 的 `values.yaml` 结构镜像对应。主要关注的配置如下。 - -### 1. 配置存储 - -#### 1.1 配置 SQLite 存储(默认) - -通过如下配置指定 StorageClass 和卷大小: - -```yaml -spec: - langflow: - backend: - sqlite: - volume: - existingStorageClassName: # 集群 SC 名称;保留 "default" 表示使用集群默认 SC - size: 1Gi # PVC 大小 -``` - -**注意**: - -- `existingStorageClassName: "default"` 是 chart 里的**特殊字符串**,表示"使用集群默认 SC"(即标了 `storageclass.kubernetes.io/is-default-class: "true"` 的那个 SC)。填写显式 SC 名称即可覆盖。 -- 使用 SQLite 时仅支持单实例 backend(StatefulSet 副本数 = 1)。 - -### 2. 配置数据库 - -#### 2.1 启用 PostgreSQL - -通过设置以下字段配置 PostgreSQL 访问信息: - -```yaml -spec: - langflow: - backend: - externalDatabase: - enabled: true # 启用外部数据库 - driver: {value: "postgresql"} - host: {value: } # PostgreSQL 主机(Service DNS 或外部地址) - port: {value: "5432"} - database: {value: langflow} # 目标数据库(backend 启动前必须存在) - user: {value: langflow} - password: - valueFrom: - secretKeyRef: - name: postgres-secret # 存密码的 Secret - key: password -``` - -Chart 在 backend 容器启动时执行一个 shim,读取上述 `LF_CHART_EXTERNALDB_*` 环境变量并拼成 `LANGFLOW_DATABASE_URL=postgresql://:@:/`,覆盖默认的 sqlite URL。实测已验证:backend 启动后连接 PostgreSQL,通过 Alembic 建立完整 schema(`alembic_version`、`flow`、`apikey`、`folder`、`message` 等),并把内置 starter projects 写入。 - -**注意**:SQLite 场景仅支持单实例 backend。要多实例必须 PostgreSQL,但当前 chart 仍默认 backend StatefulSet 副本数 = 1 —— 如需 HA 请显式扩容。 - -### 3. 配置外部访问 - -上游 chart 默认只创建两个 `ClusterIP` Service: - -- `langflow-service` 端口 8080 —— frontend(React IDE,由 nginx serve) -- `langflow-service-backend` 端口 7860 —— backend(FastAPI + `/api/v1/*`) - -Frontend nginx 内部把 `/api`、`/health` 与 `/health_check` 反代到 backend,因此**只把外部流量路由到 `langflow-service:8080` 就同时覆盖 SPA 和后端 API**,无需按路径拆多条规则。 - -**推荐路径:Gateway API(Envoy Gateway)** - -chart-wrap 在 oss-operator-factory 仓库的 `components/langflow/examples/gateway-httproute.example.yaml` 提供示例。集群运维在每个集群上一次性挂 `EnvoyProxy` + `Gateway`;用户在 Langflow 命名空间里挂一条 `HTTPRoute` 指向 `langflow-service:8080`。单条 rule + 单个 backend 即可,无需按 path 拆规则。 - -最简 HTTPRoute 示例(假设 Gateway `langflow-gw` 已存在): - -```yaml -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: langflow - namespace: -spec: - parentRefs: - - {group: gateway.networking.k8s.io, kind: Gateway, name: langflow-gw, namespace: } - hostnames: [] - rules: - - matches: [{path: {type: PathPrefix, value: "/"}}] - backendRefs: - - {name: langflow-service, port: 8080} -``` - -**备选:上游 chart 自带 Ingress** - -Chart 也提供 Ingress 字段(默认关)。通过 wrap CR 打开: - -```yaml -spec: - langflow: - ingress: - enabled: true - hosts: - - host: langflow.example.com - paths: [{path: /, pathType: Prefix}] - tls: - - {secretName: langflow-tls, hosts: [langflow.example.com]} -``` - -注意: - -- chart 默认 `ingress.enabled: false`,wrap 保持不动 —— 预开在无对应 ingress class / 域名的集群上会失败。 -- **OAuth2 Proxy 不在上游 chart 里**。如需 SSO,需要另外部署一个 OAuth2 Proxy(或平台已有的 SSO 网关)作为 Langflow Service 前置,wrap 不管这个生命周期。跟平台上其他 chart-wrap 组件同套路。 - -### 4. 配置身份验证和用户管理(可选) - -上游社区 chart **不提供** `auth` 结构化字段。Langflow 的鉴权通过 backend 容器的环境变量控制。在 `spec.langflow.backend.env` 下设置: - -```yaml -spec: - langflow: - backend: - env: - - name: LANGFLOW_AUTO_LOGIN - value: "false" # 关闭自动登录(默认:true) - - name: LANGFLOW_SUPERUSER - valueFrom: - secretKeyRef: {name: langflow-superuser, key: username} - - name: LANGFLOW_SUPERUSER_PASSWORD - valueFrom: - secretKeyRef: {name: langflow-superuser, key: password} - - name: LANGFLOW_NEW_USER_IS_ACTIVE - value: "false" # 新用户需超级用户激活(默认:false) - - name: LANGFLOW_ENABLE_SUPERUSER_CLI - value: "false" # 关闭 CLI 超级用户引导 -``` - -`LANGFLOW_AUTO_LOGIN=false` 已实测行为: - -- `GET /api/v1/auto_login` 返回 **403**(自动登录已关)。 -- `POST /api/v1/login` 用正确超级用户凭据返回 **200**,带 `access_token`。 -- `POST /api/v1/login` 用错误密码返回 **401**。 -- 受保护接口(如 `GET /api/v1/all`)用有效 Bearer token 返回 **200**,无 token 返回 **403**。 - -注意: - -- `LANGFLOW_AUTO_LOGIN=false` 下不支持自注册。新用户必须由超级用户在 `/admin` 添加;如 `LANGFLOW_NEW_USER_IS_ACTIVE=false`,超级用户还需手动激活账户方可登录。 -- 超级用户凭据**只在首次启动**时消费。一旦写入数据库(SQLite 或 PostgreSQL),只改环境变量**不会**轮换凭据 —— 后续修改必须走 Langflow 管理界面或数据库迁移。 -- 访问/刷新 token 过期时间由 `LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS` / `LANGFLOW_REFRESH_TOKEN_EXPIRE_SECONDS` 控制(默认较保守,非必要不要动)。 - -### 5. 单点登录(SSO) - -上游 `langflow-ide` chart **不包含 OAuth2 Proxy 边车或独立 Deployment**。如需 SSO,需要在 Langflow frontend Service 前面另外部署 OAuth2 Proxy(或平台已有的 SSO 网关)作为独立工作负载 —— wrap CR 不管这一段的生命周期,跟平台上其他 chart-wrap 组件同套路。将 OAuth2 Proxy 上游指向 `langflow-service:8080`,同时把 backend 的 `LANGFLOW_AUTO_LOGIN=false`,让 proxy 成为唯一的鉴权入口。 - -### 6. 配置运行时模式(仅后端) - -运行时模式去掉 React IDE 前端,只跑 backend REST API,适合生产 API 服务场景。 - -#### 6.1 启用运行时模式 - -需要同时设置两个字段才是完整的 runtime mode: - -- `spec.langflow.backend.backendOnly: true` —— backend 启动带 `--backend-only`(当前 chart 里默认已 true,保留显式声明)。 -- `spec.langflow.frontend.enabled: false` —— chart 会**跳过 frontend Deployment**(实测:`kubectl get deploy -n ` 返回 0 条,只剩 backend StatefulSet)。 - -可选:自动从 PVC 或 ConfigMap 导入 flow: - -```yaml -spec: - langflow: - backend: - backendOnly: true - env: - - name: LANGFLOW_LOAD_FLOWS_PATH - value: "/app/flows" - volumes: - - name: flows - persistentVolumeClaim: {claimName: langflow-flows-pvc} - volumeMounts: - - name: flows - mountPath: /app/flows - frontend: - enabled: false -``` - -启用 `LANGFLOW_LOAD_FLOWS_PATH` 时,需要保留 `LANGFLOW_AUTO_LOGIN=true`(自动登录模式)—— 这是 Langflow 的约束:用户所有的自动导入 flow 需要 auto-login 默认用户存在。 - -## 访问地址 - -### 1. 通过 Gateway API 访问(推荐) - -按 [配置外部访问](#3-配置外部访问) 挂上 Gateway API 后,Gateway 数据面 Service 的 NodePort 或 LoadBalancer 地址就是入口。例如: - -```bash -# 查 envoy 数据面 Service 分配到的 NodePort(或 LoadBalancer 地址) -kubectl get svc -A -l gateway.envoyproxy.io/owning-gateway-name=langflow-gw - -# 用任意集群节点 IP + 该 NodePort 访问 Langflow -curl http://:/health_check -# 或浏览器打开 http://:/ 就是 Langflow IDE -``` - -### 2. 通过集群内 port-forward 访问(仅开发) - -```bash -kubectl port-forward -n svc/langflow-service 8080:8080 -# 浏览器打开 http://localhost:8080/ -``` - -### 3. 通过 Ingress 访问 - -若通过 `spec.langflow.ingress.enabled=true` 打开了 Ingress,请通过配置的域名访问(DNS 解析 + TLS 证书需集群运维准备)。 - -# Langflow 快速入门 - -有关快速入门指南,请参阅官方文档: - -# 生产环境建议 - -本节提供在生产环境中使用 Langflow 的实用建议和优化配置。 - -## 1. 通过 ConfigMap 导入现有流程 - -在生产环境中,可以通过 Kubernetes ConfigMap 将现有流程文件导入 Langflow。 - -### 1.1 创建包含流程 JSON 的 ConfigMap - -首先,创建一个包含流程 JSON 文件的 ConfigMap: - -```yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: langflow-flows - namespace: -data: - project1.json: | - -``` - -### 1.2 将 ConfigMap 挂载到 backend 容器 - -把 ConfigMap 作为 volume 加进来,并通过 `LANGFLOW_LOAD_FLOWS_PATH` 暴露挂载路径。上游 chart 会把用户提供的 volumes/volumeMounts 追加到自带的 default 之后: - -```yaml -spec: - langflow: - backend: - volumes: - - name: flows - configMap: {name: langflow-flows} - volumeMounts: - - name: flows - mountPath: /app/flows - env: - - name: LANGFLOW_LOAD_FLOWS_PATH - value: /app/flows -``` - -### 1.3 自动导入 - -backend 重启后,Langflow 扫描 `LANGFLOW_LOAD_FLOWS_PATH` 并自动把里面每个 `*.json` 导入为 Flow。由于 flow 归属绑定用户,自动导入模式需要 `LANGFLOW_AUTO_LOGIN=true`(默认)—— 导入的 flow 会归到内置的默认用户。开鉴权后(`LANGFLOW_AUTO_LOGIN=false`),上游 chart 不支持用户归属的自动导入,请改用 REST API(`POST /api/v1/flows/` + Bearer token)。 - -## 2. 使用模型 - -在生产环境中,可以通过两种方式加载和使用模型:通过 API 调用远程模型或通过卷挂载加载本地模型。根据具体需求选择适当的方法。 - -### 2.1 调用远程模型 - -这种方法适用于以下场景: - -- 模型有显著的资源需求 -- 模型需要在多个服务之间共享 -- 需要独立的扩展和资源管理 -- 模型版本管理和更新需要单独处理 - -远程模型可以是自部署的模型服务或供应商提供的第三方模型服务。要在 Langflow 中使用远程模型,在流程编辑器中,使用基于 API 的模型组件(例如 OpenAI、Custom API 等)通过配置 API 基础 URL 和身份验证凭据连接到模型服务端点。 - -### 2.2 加载本地模型 - -这种方法适用于以下场景: - -- 模型的资源开销较低(例如,嵌入模型) -- 模型大小和资源消耗在 Langflow 容器内可控 -- 需要直接文件访问模型 - -#### 2.2.1 通过卷挂载模型文件 - -将模型文件存到持久卷,通过附加 volume/volumeMount 挂给 Langflow backend 容器: - -```yaml -spec: - langflow: - backend: - volumes: - - name: models - persistentVolumeClaim: {claimName: langflow-models-pvc} - volumeMounts: - - name: models - mountPath: /opt/models -``` - -#### 2.2.2 上传模型 - -用户可以使用 `kubectl cp` 命令将模型上传到 Langflow 容器,如下所示: - -```bash -kubectl cp -n :/opt/models -``` - -#### 2.2.3 在组件中配置本地模型 - -在 Langflow 的流程编辑器中,使用相应的模型组件时,可以将本地模型访问路径配置为 `/opt/models`。 - -## 3. 添加额外的 Python 依赖 - -在生产环境中,当使用自定义组件时,可能需要安装额外的 Python 包。可以按如下方式进行: - -### 3.1 通过 PVC 挂载依赖 - -用 PVC 挂载一个目录存放额外的 Python 包: - -```yaml -spec: - langflow: - backend: - volumes: - - name: python-packages - persistentVolumeClaim: {claimName: langflow-packages-pvc} - volumeMounts: - - name: python-packages - mountPath: /opt/python-packages - env: - - name: PYTHONPATH - value: "/opt/python-packages" -``` - -### 3.2 安装依赖 - -安装依赖包时,使用 `pip --target` 参数将包安装到 PVC 挂载的目录: - -```bash -# 在容器中执行,将包安装到 PVC 挂载的目录 -pip install --target /opt/python-packages package-name - -# 或从 requirements.txt 安装 -pip install --target /opt/python-packages -r requirements.txt -``` - -## 4. 通过环境变量传递全局变量 - -流程组件配置通常需要在不同环境中使用不同的值。Langflow 的全局变量功能允许将这些特定于环境的值与流程定义分开。全局变量的值可以从环境变量加载。 - -### 4.1 配置环境变量 - -在 `spec.langflow.backend.env` 下添加环境变量: - -```yaml -spec: - langflow: - backend: - env: - - name: LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT - value: VAR1,VAR2,VAR3 # 逗号分隔,列出会被 Langflow 变成全局变量的 env 名字 - - name: VAR1 - value: xxx # 明文值 - - name: VAR2 - valueFrom: - configMapKeyRef: - name: langflow-configs - key: var2 # 从 ConfigMap - - name: VAR3 - valueFrom: - secretKeyRef: - name: langflow-secrets - key: var3 # 从 Secret(敏感值推荐用这个) -``` - -实测已验证:wrap CR 上 `LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT=MY_PLAIN_VAR,MY_SECRET_KEY` + 对应的 env 定义,backend 启动后 `GET /api/v1/variables/` 返回两条 `type: Credential` 的条目,可直接被 flow 组件引用。 - -### 4.2 在流程中使用全局变量 - -在 Langflow 的流程编辑器中: - -1. 转到 **设置** 页面 -2. 在 **全局变量** 部分,添加全局变量并设置其值 -3. 在组件配置中引用这些全局变量 -4. 导出流程时,**必须**选择“与我的 API 密钥一起保存”,否则全局变量配置可能不会包含在导出的 JSON 文件中 - -## 5. 优化建议 - -为提高生产环境中的性能、安全性和稳定性,建议进行以下优化配置: - -### 5.1 禁用使用跟踪 - -Langflow 默认收集使用数据。在生产环境中,可以禁用此功能以保护隐私并减少网络请求: - -```yaml -spec: - langflow: - backend: - env: - - name: DO_NOT_TRACK - value: "true" -``` - -### 5.2 禁用事务日志 - -Langflow 每次处理请求都会把每个组件的输入、输出、执行日志写到数据库(IDE Logs 面板可看)。关掉能减少数据库写压力: - -```yaml -spec: - langflow: - backend: - env: - - name: LANGFLOW_TRANSACTIONS_STORAGE_ENABLED - value: "false" -``` - -### 5.3 设置工作进程数量 - -```yaml -spec: - langflow: - backend: - numWorkers: 1 # gunicorn worker 数(默认:1) -``` - -### 5.4 配置资源限制 - -建议分别为 backend 和 frontend 容器配置资源限制。以下示例仅供参考,按实际负载调整: - -```yaml -spec: - langflow: - backend: - resources: - requests: {cpu: "2", memory: "4Gi"} - limits: {cpu: "4", memory: "8Gi"} - frontend: - resources: - requests: {cpu: "0.3", memory: "512Mi"} -``` - -### 5.5 使用 API 密钥 - -Langflow 支持 REST 请求走 `x-api-key` 鉴权。两种方式建 key: - -1. **在 IDE 内**(Settings → Langflow API Keys):点击 "Add New" 给 key 起个名字,Langflow 只显示一次密钥值,请立即记录。 -2. **走 REST**:`POST /api/v1/api_key/` 带 Bearer token: - ```bash - curl -X POST http:///api/v1/api_key/ \ - -H "Authorization: Bearer " \ - -H "Content-Type: application/json" \ - -d '{"name":"my-key"}' - ``` - 响应体里的 `api_key` 就是要记录的 key。 - -后续请求带 `x-api-key: ` header: - -- 有效 key → `200` -- 缺 / 错 → `403` - -e2e smoke H 探针在 4.3-x86 上已实测:建 key + 用有效 key 打 `/api/v1/all` 返回 200(含完整组件目录);用错误 key 打同接口返回 403。 - -### 5.6 禁用 UI - -参考 [配置运行时模式](#6-配置运行时模式仅后端) —— 同时设置 `backend.backendOnly=true` 和 `frontend.enabled=false` 才能真正跳过 frontend Deployment。 - -### 5.7 参考官方文档 - -有关发布流程和生产最佳实践的更详细信息,请参阅官方 Langflow 文档: - -- **发布概念**: -- **生产最佳实践**: From 86ef818172189087f1452b0d31f27cdc5c46039d Mon Sep 17 00:00:00 2001 From: luohua13 Date: Wed, 8 Jul 2026 02:21:01 +0000 Subject: [PATCH 3/4] docs(langflow): drop internal terminology, inline full Gateway API YAML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer feedback: 1. Prerequisites section removed. The default-StorageClass requirement is already documented under §1.1 Configure SQLite Storage (via the `existingStorageClassName: "default"` magic string). No need to warn about it twice. 2. External access section (§3) now inlines the complete EnvoyProxy + Gateway YAML alongside the HTTPRoute. Previously it referenced an example file in an internal repo — end-user docs shouldn't leak platform-internal paths. The 3-object bundle is now self-contained and copy-pasteable. 3. Terminology scrub. Removed all occurrences of "chart-wrap", "wrap CR", "upstream chart", "community chart", and the repo path `components/langflow/examples/...`. The doc talks about the `Langflow` custom resource without exposing how the package is assembled. --- .../How_to_install_and_use_Langflow.md | 90 ++++++++++++------- 1 file changed, 57 insertions(+), 33 deletions(-) diff --git a/docs/en/solutions/How_to_install_and_use_Langflow.md b/docs/en/solutions/How_to_install_and_use_Langflow.md index dac04bf31..e1b2825cf 100644 --- a/docs/en/solutions/How_to_install_and_use_Langflow.md +++ b/docs/en/solutions/How_to_install_and_use_Langflow.md @@ -44,28 +44,13 @@ Use the violet command to publish to the platform repository: violet push --platform-address=platform-access-address --platform-username=platform-admin --platform-password=platform-admin-password langflow-operator.alpha.ALL.v1.10.1.tgz ``` -Starting with v1.10.1, Langflow is packaged as an OLM `OperatorBundle` (chart-wrap of the upstream `langflow-ai/langflow-helm-charts/langflow-ide` chart), not a raw Helm chart. Installation goes through OperatorHub and a `Langflow` custom resource, not the Applications / Catalog picker. - -## Prerequisites - -Before installing Langflow, the target workload cluster must have: - -- **A default StorageClass** — Langflow's backend uses SQLite by default, backed by an RWO PVC that requests the cluster's default StorageClass. Without a default, `data-langflow-service-0` will stay `Pending` and the backend pod cannot schedule. Set one with: - - ```bash - kubectl get sc - kubectl patch sc -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' - ``` - - If you want to pin a specific StorageClass instead of relying on the cluster default, set `spec.langflow.backend.sqlite.volume.existingStorageClassName` on the `Langflow` custom resource (see [Configure Storage](#1-configure-storage)). - -- **(Optional, for Gateway API external access)** Envoy Gateway installed on the cluster with a `GatewayClass` whose `controllerName` contains `envoy`. Without one, users can only reach Langflow via `kubectl port-forward` or by opening a NodePort/LoadBalancer Service manually. +Starting with v1.10.1, Langflow is installed via `OperatorHub` and a `Langflow` custom resource, not from the Applications / Catalog form. ## Deployment ### Prepare Storage -Langflow uses SQLite by default with an RWO PVC (1Gi). For production, PostgreSQL is recommended (see [Configure Database](#2-configure-database)). The cluster must have a default StorageClass or the user must set `existingStorageClassName` explicitly. +Langflow uses SQLite by default with an RWO PVC (1Gi). For production, PostgreSQL is recommended (see [Configure Database](#2-configure-database)). The StorageClass for the SQLite PVC is configured under `spec.langflow.backend.sqlite.volume` — see [Configure Storage](#1-configure-storage) for details. ### Prepare Database (Optional) @@ -107,11 +92,11 @@ Production environments strongly recommend PostgreSQL: spec: {} ``` - Empty `spec: {}` uses the chart's defaults (SQLite on the cluster default StorageClass, IDE mode, ClusterIP Services only). To customize, add fields under `spec.langflow.*` per the sections below — the wrap CR spec mirrors the upstream chart's `values.yaml` structure. See the upstream [`values.yaml`](https://github.com/langflow-ai/langflow-helm-charts/blob/langflow-ide-0.1.2/charts/langflow-ide/values.yaml) for the full field list. + Empty `spec: {}` uses defaults (SQLite on the cluster default StorageClass, IDE mode, ClusterIP Services only). To customize, add fields under `spec.langflow.*` per the sections below. ## Configuration -Users can edit the `Langflow` custom resource's `spec.langflow.*` fields to customize the deployment. The wrap CR spec mirrors the upstream `langflow-ide` chart's `values.yaml` structure. The main configurations to focus on are as follows. +The `Langflow` custom resource's `spec.langflow.*` fields customize the deployment. The main configurations to focus on are as follows. > **⚠ Array fields REPLACE chart defaults, they do not append.** > When you set `spec.langflow.backend.volumes` (or `.volumeMounts`), the chart drops its own default `tmp` / `data` / `db` / `flows` `emptyDir` volumes and uses only what you provide. If you add a custom volume without re-declaring the defaults, the backend container will crash on startup with `FileNotFoundError: No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp', '/app']` (the Langflow entrypoint imports `dill`, which calls `tempfile.gettempdir()` — `readOnlyRootFilesystem: true` means `/tmp` must be a writable volume). @@ -188,20 +173,51 @@ The chart runs a small startup shim inside the backend container that reads thes ### 3. Configure External Access -The upstream chart creates only two `ClusterIP` Services by default: +Langflow creates only two `ClusterIP` Services by default: - `langflow-service` on port 8080 — frontend (React IDE served by nginx) - `langflow-service-backend` on port 7860 — backend (FastAPI + `/api/v1/*`) -The frontend nginx also reverse-proxies `/api`, `/health` and `/health_check` to the backend, so **routing all external traffic to `langflow-service:8080` gives users both the SPA and the backend API through the same entry point**. +The frontend nginx also reverse-proxies `/api`, `/health` and `/health_check` to the backend, so **routing all external traffic to `langflow-service:8080` gives users both the IDE and the backend API through the same entry point**. -**Recommended path: Gateway API (Envoy Gateway)** - -The chart-wrap ships an example under `components/langflow/examples/gateway-httproute.example.yaml` (in the `oss-operator-factory` repo). Cluster operators apply an `EnvoyProxy` + `Gateway` once per cluster; users add an `HTTPRoute` in the Langflow namespace pointing at `langflow-service:8080`. A single rule with one backend covers everything — no path-prefix split needed. - -Minimal HTTPRoute example (assuming a Gateway `langflow-gw` already exists): +External access is provided via Gateway API (Envoy Gateway). Apply the three resources below in the same namespace as your `Langflow` custom resource. Adjust the `gatewayClassName` (`envoy-gateway-system-aieg` is the default on Alauda Container Platform 4.3+) and the `hostname` to match your environment. ```yaml +# ── 1) EnvoyProxy: expose the data plane via NodePort (or LoadBalancer if available). ──── +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: langflow-proxy + namespace: +spec: + logging: {level: {default: warn}} + provider: + type: Kubernetes + kubernetes: + envoyService: + type: NodePort # change to LoadBalancer if the cluster has one + externalTrafficPolicy: Cluster +--- +# ── 2) Gateway: HTTP listener; add an HTTPS listener with a cert Secret for TLS. ───────── +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: langflow-gw + namespace: +spec: + gatewayClassName: envoy-gateway-system-aieg + infrastructure: + parametersRef: + group: gateway.envoyproxy.io + kind: EnvoyProxy + name: langflow-proxy + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: {namespaces: {from: Same}} +--- +# ── 3) HTTPRoute: all paths → langflow-service:8080; nginx fans out /api* to backend. ──── apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: @@ -209,20 +225,28 @@ metadata: namespace: spec: parentRefs: - - {group: gateway.networking.k8s.io, kind: Gateway, name: langflow-gw, namespace: } - hostnames: [] + - {group: gateway.networking.k8s.io, kind: Gateway, name: langflow-gw} + # hostnames: [langflow.example.com] # optional; omit to accept any Host rules: - matches: [{path: {type: PathPrefix, value: "/"}}] backendRefs: - {name: langflow-service, port: 8080} ``` -Notes: -- The chart also ships an Ingress block (default off), but the platform standardises on Gateway API for chart-wrap components — Ingress is not the supported external-access path for Langflow and is not covered by this document. +After apply, wait for the `Gateway` to reach `PROGRAMMED=True`, then find the NodePort that Envoy Gateway allocated: + +```bash +kubectl get gateway langflow-gw -n +kubectl get svc -A -l gateway.envoyproxy.io/owning-gateway-name=langflow-gw +``` + +The NodePort service in the output is the entry point — reach Langflow at `http://:/`. + +If you added an HTTPS listener with a certificate `Secret` in a different namespace, you'll also need a `ReferenceGrant` from the Gateway's namespace to the certificate's namespace. ### 4. Configure Authentication and User Management (Optional) -The upstream community chart does not expose a structured `auth` field. Instead, Langflow authentication is controlled by environment variables set on the backend container. Set them under `spec.langflow.backend.env`: +Langflow authentication is controlled by environment variables on the backend container. Set them under `spec.langflow.backend.env`: ```yaml spec: @@ -379,7 +403,7 @@ Verified on ACP 4.3: with the above CR, restarting the backend caused Langflow t ### 1.3 Auto Import -After the backend restarts, Langflow scans `LANGFLOW_LOAD_FLOWS_PATH` and auto-imports every `*.json` file in it as a Flow. Since flow ownership is tied to a user, the auto-import mode requires `LANGFLOW_AUTO_LOGIN=true` (the default) — the imported flows are attached to the built-in default user. With authentication enabled (`LANGFLOW_AUTO_LOGIN=false`), user-owned imports are not supported by the upstream chart; use the REST API (`POST /api/v1/flows/` with a Bearer token) instead. +After the backend restarts, Langflow scans `LANGFLOW_LOAD_FLOWS_PATH` and auto-imports every `*.json` file in it as a Flow. Since flow ownership is tied to a user, the auto-import mode requires `LANGFLOW_AUTO_LOGIN=true` (the default) — the imported flows are attached to the built-in default user. With authentication enabled (`LANGFLOW_AUTO_LOGIN=false`), user-owned imports are not supported; use the REST API (`POST /api/v1/flows/` with a Bearer token) instead. ## 2. Using Models @@ -512,7 +536,7 @@ spec: key: var3 # From Secret (recommended for sensitive values) ``` -Verified: with `LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT=MY_PLAIN_VAR,MY_SECRET_KEY` on the wrap CR, `GET /api/v1/variables/` returns both entries with `type: Credential`, ready to be referenced from flow components. +Verified: with `LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT=MY_PLAIN_VAR,MY_SECRET_KEY` on the `Langflow` custom resource, `GET /api/v1/variables/` returns both entries with `type: Credential`, ready to be referenced from flow components. ### 4.2 Use Global Variables in Flows From f091f547997b811e3de4b0a59ef5cc7b2102d021 Mon Sep 17 00:00:00 2001 From: luohua13 Date: Wed, 8 Jul 2026 03:04:31 +0000 Subject: [PATCH 4/4] docs(langflow): auth verification via browser (clear cookies + log in) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous verification step listed HTTP status codes (403/200/401 on /auto_login, /login, /all) which is what an operator would probe with curl during development. End users following the doc reported that after setting the auth env vars, "the page still went straight into the IDE" — because their browser had cookies from a previous auto-login session, and Langflow's JWTs stay valid until expiration regardless of the current LANGFLOW_AUTO_LOGIN setting. Replace the status-code checklist with browser steps: 1. Open in Incognito (or clear the 3 lf cookies). 2. Expect to see a login form, not the IDE. 3. Log in with the superuser credentials. Also fix the token-expiration defaults note (upstream is 30d/60d, not "conservative") and give a concrete production-recommended pair with LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS=3600 + LANGFLOW_REFRESH_TOKEN_ EXPIRE_SECONDS=604800. --- .../How_to_install_and_use_Langflow.md | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/docs/en/solutions/How_to_install_and_use_Langflow.md b/docs/en/solutions/How_to_install_and_use_Langflow.md index e1b2825cf..7e4a47e5b 100644 --- a/docs/en/solutions/How_to_install_and_use_Langflow.md +++ b/docs/en/solutions/How_to_install_and_use_Langflow.md @@ -267,17 +267,22 @@ spec: value: "false" # Disable CLI superuser bootstrap ``` -Verified behavior with `LANGFLOW_AUTO_LOGIN=false`: +**Verify the login flow in a browser**: -- `GET /api/v1/auto_login` returns **403** (auto-login disabled). -- `POST /api/v1/login` with the correct superuser credentials returns **200** with an `access_token`. -- `POST /api/v1/login` with wrong credentials returns **401**. -- Protected endpoints (e.g. `GET /api/v1/all`) return **200** with a valid Bearer token and **403** without. +1. **Open the Langflow URL in a fresh browser tab** — use an Incognito / Private window, or clear the site's cookies first (DevTools → Application → Cookies → delete `access_token_lf`, `refresh_token_lf`, `apikey_tkn_lflw`). Without this step, previously issued auto-login cookies keep working until they expire, and the browser walks straight into the IDE as if authentication were still off. +2. **The page should show a login form** instead of loading the IDE directly. +3. **Log in with the superuser credentials** you set in `LANGFLOW_SUPERUSER` / `LANGFLOW_SUPERUSER_PASSWORD`. You should land in the IDE with your username shown in the top-right menu; entering a wrong password should keep you on the login page with an error message. Notes: -- With `LANGFLOW_AUTO_LOGIN=false`, self-registration is not supported. New users must be added by the superuser via `/admin`; if `LANGFLOW_NEW_USER_IS_ACTIVE=false`, the superuser must activate the account before login is allowed. -- The superuser credentials are only consumed on **first startup**. Once written into the database (SQLite or PostgreSQL), changing the env vars alone does not rotate them — the credential update must go through Langflow's admin UI or a DB migration. -- Access/refresh token expiration are controlled by `LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS` / `LANGFLOW_REFRESH_TOKEN_EXPIRE_SECONDS` (defaults are conservative; adjust only if required). + +- Self-registration is not supported when `LANGFLOW_AUTO_LOGIN=false`. New users must be added by the superuser from the admin page; if `LANGFLOW_NEW_USER_IS_ACTIVE=false`, the superuser must also activate each new account before the user can log in. +- The superuser credentials are consumed on **first startup only**. Once written into the database, changing the env vars alone does not rotate the password — update it through Langflow's admin UI instead. Rotating requires either editing the existing user or wiping the database and restarting. +- Access/refresh token expiration are controlled by `LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS` (default 30 days) and `LANGFLOW_REFRESH_TOKEN_EXPIRE_SECONDS` (default 60 days). For production, shorter values are recommended: + ```yaml + env: + - {name: LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS, value: "3600"} # 1 hour + - {name: LANGFLOW_REFRESH_TOKEN_EXPIRE_SECONDS, value: "604800"} # 7 days + ``` ### 5. Configure Runtime Mode (Backend-Only)