Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 195 additions & 0 deletions ct/langflow.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
#!/usr/bin/env bash
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main}"
source <(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Yamon
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.langflow.org/

APP="Langflow"
var_tags="${var_tags:-ai;interface}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-12288}"
var_disk="${var_disk:-16}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"

header_info "$APP"
variables
color
catch_errors

function update_script() {
header_info
check_container_storage
check_container_resources

if [[ ! -d /opt/langflow || ! -f /etc/systemd/system/langflow.service || ! -x /opt/langflow/.venv/bin/python ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi

local TS BACKUP_DIR OLD_VERSION TARGET_VERSION
TS="$(date +%Y%m%d-%H%M%S)"
BACKUP_DIR="/opt/langflow/backups/${TS}"
TARGET_VERSION="${LANGFLOW_TARGET_VERSION:-latest}"
OLD_VERSION="$([ -x /opt/langflow/.venv/bin/python ] && /opt/langflow/.venv/bin/python -m pip show langflow 2>/dev/null | awk '/^Version:/ {print $2}')"
msg_info "Installed Version: ${OLD_VERSION:-unknown}"
if [[ "${TARGET_VERSION}" == "latest" ]] && ! check_for_gh_release "langflow" "langflow-ai/langflow"; then
msg_ok "Langflow is already up to date"
exit
fi

msg_info "Preparing Backup"
mkdir -p "${BACKUP_DIR}"
if [[ -f /opt/langflow/.env ]]; then
cp -a /opt/langflow/.env "${BACKUP_DIR}/.env"
fi
if compgen -G "/opt/langflow/data/langflow.db*" >/dev/null; then
cp -a /opt/langflow/data/langflow.db* "${BACKUP_DIR}/"
fi
msg_ok "Backup saved to ${BACKUP_DIR}"

msg_info "Stopping Service"
systemctl stop langflow
msg_ok "Stopped Service"

UV_PYTHON="3.12" setup_uv
UV_CONCURRENT_DOWNLOADS="${UV_CONCURRENT_DOWNLOADS:-2}"
UV_CONCURRENT_BUILDS="${UV_CONCURRENT_BUILDS:-1}"
UV_CONCURRENT_INSTALLS="${UV_CONCURRENT_INSTALLS:-1}"
LANGFLOW_NO_CACHE="${LANGFLOW_NO_CACHE:-false}"
UV_CACHE_ARGS=()
if [[ "${LANGFLOW_NO_CACHE,,}" == "true" || "${LANGFLOW_NO_CACHE}" == "1" ]]; then
UV_CACHE_ARGS+=(--no-cache)
fi

msg_info "Pinning CPU Torch"
if ! $STD env \
UV_CONCURRENT_DOWNLOADS="${UV_CONCURRENT_DOWNLOADS}" \
UV_CONCURRENT_BUILDS="${UV_CONCURRENT_BUILDS}" \
UV_CONCURRENT_INSTALLS="${UV_CONCURRENT_INSTALLS}" \
uv pip install --python /opt/langflow/.venv/bin/python "${UV_CACHE_ARGS[@]}" \
--index-strategy unsafe-best-match \
--index-url https://download.pytorch.org/whl/cpu \
--extra-index-url https://pypi.org/simple \
"torch==2.8.0+cpu"; then
msg_error "Failed to install CPU torch"
exit 1
fi
msg_ok "Pinned CPU Torch"

msg_info "Updating Langflow (${TARGET_VERSION})"
if [[ "${TARGET_VERSION}" == "latest" ]]; then
if ! $STD env \
UV_CONCURRENT_DOWNLOADS="${UV_CONCURRENT_DOWNLOADS}" \
UV_CONCURRENT_BUILDS="${UV_CONCURRENT_BUILDS}" \
UV_CONCURRENT_INSTALLS="${UV_CONCURRENT_INSTALLS}" \
uv pip install --python /opt/langflow/.venv/bin/python "${UV_CACHE_ARGS[@]}" --upgrade langflow; then
msg_error "Langflow update failed"
if [[ -n "${OLD_VERSION}" ]]; then
msg_info "Rolling back to ${OLD_VERSION}"
$STD env \
UV_CONCURRENT_DOWNLOADS="${UV_CONCURRENT_DOWNLOADS}" \
UV_CONCURRENT_BUILDS="${UV_CONCURRENT_BUILDS}" \
UV_CONCURRENT_INSTALLS="${UV_CONCURRENT_INSTALLS}" \
uv pip install --python /opt/langflow/.venv/bin/python "${UV_CACHE_ARGS[@]}" "langflow==${OLD_VERSION}"
fi
if [[ -f "${BACKUP_DIR}/.env" ]]; then
cp -a "${BACKUP_DIR}/.env" /opt/langflow/.env
fi
if compgen -G "${BACKUP_DIR}/langflow.db*" >/dev/null; then
cp -a "${BACKUP_DIR}/langflow.db"* /opt/langflow/data/
fi
if ! systemctl start langflow; then
msg_error "Failed to start service after rollback"
fi
exit 1
fi
else
if ! $STD env \
UV_CONCURRENT_DOWNLOADS="${UV_CONCURRENT_DOWNLOADS}" \
UV_CONCURRENT_BUILDS="${UV_CONCURRENT_BUILDS}" \
UV_CONCURRENT_INSTALLS="${UV_CONCURRENT_INSTALLS}" \
uv pip install --python /opt/langflow/.venv/bin/python "${UV_CACHE_ARGS[@]}" "langflow==${TARGET_VERSION}"; then
msg_error "Langflow update to ${TARGET_VERSION} failed"
if [[ -n "${OLD_VERSION}" ]]; then
msg_info "Rolling back to ${OLD_VERSION}"
$STD env \
UV_CONCURRENT_DOWNLOADS="${UV_CONCURRENT_DOWNLOADS}" \
UV_CONCURRENT_BUILDS="${UV_CONCURRENT_BUILDS}" \
UV_CONCURRENT_INSTALLS="${UV_CONCURRENT_INSTALLS}" \
uv pip install --python /opt/langflow/.venv/bin/python "${UV_CACHE_ARGS[@]}" "langflow==${OLD_VERSION}"
fi
if [[ -f "${BACKUP_DIR}/.env" ]]; then
cp -a "${BACKUP_DIR}/.env" /opt/langflow/.env
fi
if compgen -G "${BACKUP_DIR}/langflow.db*" >/dev/null; then
cp -a "${BACKUP_DIR}/langflow.db"* /opt/langflow/data/
fi
if ! systemctl start langflow; then
msg_error "Failed to start service after rollback"
fi
exit 1
fi
fi
msg_ok "Updated Langflow"

msg_info "Starting Service"
systemctl start langflow

if [[ "$(systemctl is-active langflow)" != "active" ]]; then
msg_error "Service failed to start"
if [[ -n "${OLD_VERSION}" ]]; then
msg_info "Rolling back to ${OLD_VERSION}"
$STD env \
UV_CONCURRENT_DOWNLOADS="${UV_CONCURRENT_DOWNLOADS}" \
UV_CONCURRENT_BUILDS="${UV_CONCURRENT_BUILDS}" \
UV_CONCURRENT_INSTALLS="${UV_CONCURRENT_INSTALLS}" \
uv pip install --python /opt/langflow/.venv/bin/python "${UV_CACHE_ARGS[@]}" "langflow==${OLD_VERSION}"
if [[ -f "${BACKUP_DIR}/.env" ]]; then
cp -a "${BACKUP_DIR}/.env" /opt/langflow/.env
fi
if compgen -G "${BACKUP_DIR}/langflow.db*" >/dev/null; then
cp -a "${BACKUP_DIR}/langflow.db"* /opt/langflow/data/
fi
if ! systemctl restart langflow; then
msg_error "Failed to restart service after rollback"
fi
fi
exit 1
fi

msg_info "Running Health Check"
ensure_dependencies curl
if command -v curl >/dev/null 2>&1; then
for _ in {1..30}; do
if curl -fsS http://127.0.0.1:7860/ >/dev/null 2>&1; then
break
fi
sleep 2
done
if ! curl -fsS http://127.0.0.1:7860/ >/dev/null 2>&1; then
msg_error "Health check failed. Check logs: journalctl -u langflow -n 100"
exit 1
fi
else
msg_info "curl not available, skipping HTTP health check"
fi
msg_ok "Health check passed"
msg_info "If migration errors occur, review Langflow docs before using 'langflow migration --fix'"
msg_ok "Updated successfully!"
exit
}

start
build_container
description

msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:7860${CL}"
echo -e "${INFO}${YW} Post-install credential location:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}/opt/langflow/.env${CL}"
52 changes: 52 additions & 0 deletions frontend/public/json/langflow.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "Langflow",
"slug": "langflow",
"categories": [
20
],
"date_created": "2026-02-21",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 7860,
"documentation": "https://docs.langflow.org/",
"website": "https://www.langflow.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/langflow.webp",
"config_path": "/opt/langflow/.env",
"description": "Langflow is an open-source visual framework for building LLM workflows and multi-agent applications with a drag-and-drop interface.",
"install_methods": [
{
"type": "default",
"script": "ct/langflow.sh",
"resources": {
"cpu": 2,
"ram": 12288,
"hdd": 16,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": "admin",
"password": null
},
"notes": [
{
"text": "Admin credentials are generated during install and stored in `/opt/langflow/.env`.",
"type": "info"
},
{
"text": "Exposed port: 7860",
"type": "info"
},
{
"text": "Change the default admin password after first login.",
"type": "warning"
},
{
"text": "Installation and updates can take a long time due to large Python dependencies.",
"type": "warning"
}
]
}
124 changes: 124 additions & 0 deletions install/langflow-install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/usr/bin/env bash

# Copyright (c) 2021-2026 community-scripts ORG
# Author: Yamon
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.langflow.org/

source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os

# shellcheck disable=SC2034
APP="langflow"
app="${app:-langflow}"
SSH_ROOT="${SSH_ROOT:-no}"

msg_info "Installing Dependencies"
if ! install_packages_with_retry \
build-essential \
python3-dev; then
msg_error "Failed to install dependencies"
exit 1
fi
msg_ok "Installed Dependencies"

UV_PYTHON="3.12" setup_uv
UV_CONCURRENT_DOWNLOADS="${UV_CONCURRENT_DOWNLOADS:-2}"
UV_CONCURRENT_BUILDS="${UV_CONCURRENT_BUILDS:-1}"
UV_CONCURRENT_INSTALLS="${UV_CONCURRENT_INSTALLS:-1}"
LANGFLOW_NO_CACHE="${LANGFLOW_NO_CACHE:-false}"
UV_CACHE_ARGS=()
if [[ "${LANGFLOW_NO_CACHE,,}" == "true" || "${LANGFLOW_NO_CACHE}" == "1" ]]; then
UV_CACHE_ARGS+=(--no-cache)
fi

msg_info "Installing Langflow"
mkdir -p /opt/langflow/data
cd /opt/langflow || exit
Comment thread
YamonBot marked this conversation as resolved.
$STD uv venv --clear /opt/langflow/.venv
$STD env \
UV_CONCURRENT_DOWNLOADS="${UV_CONCURRENT_DOWNLOADS}" \
UV_CONCURRENT_BUILDS="${UV_CONCURRENT_BUILDS}" \
UV_CONCURRENT_INSTALLS="${UV_CONCURRENT_INSTALLS}" \
uv pip install --python /opt/langflow/.venv/bin/python "${UV_CACHE_ARGS[@]}" \
--index-strategy unsafe-best-match \
--index-url https://download.pytorch.org/whl/cpu \
--extra-index-url https://pypi.org/simple \
"torch==2.8.0+cpu"
$STD env \
UV_CONCURRENT_DOWNLOADS="${UV_CONCURRENT_DOWNLOADS}" \
UV_CONCURRENT_BUILDS="${UV_CONCURRENT_BUILDS}" \
UV_CONCURRENT_INSTALLS="${UV_CONCURRENT_INSTALLS}" \
uv pip install --python /opt/langflow/.venv/bin/python "${UV_CACHE_ARGS[@]}" "langflow${LANGFLOW_VERSION:+==${LANGFLOW_VERSION}}"
msg_ok "Installed Langflow"

msg_info "Configuring Langflow"
ADMIN_USER="admin"
ADMIN_PASS="$(openssl rand -base64 32 | tr -dc 'A-Za-z0-9' | head -c 20)"
if [[ ${#ADMIN_PASS} -lt 12 ]]; then
ADMIN_PASS="$(openssl rand -hex 16)"
fi
LANGFLOW_SECRET_KEY=$(openssl rand -base64 48 | tr -d '\n')
CPU_CORES="$(nproc 2>/dev/null || echo 2)"
if [[ "${CPU_CORES}" -ge 8 ]]; then
LANGFLOW_WORKERS_DEFAULT=4
elif [[ "${CPU_CORES}" -ge 4 ]]; then
LANGFLOW_WORKERS_DEFAULT=2
else
LANGFLOW_WORKERS_DEFAULT=1
fi
cat <<EOF2 >/opt/langflow/.env
LANGFLOW_CONFIG_DIR=/opt/langflow/data
LANGFLOW_SAVE_DB_IN_CONFIG_DIR=true
LANGFLOW_DATABASE_URL=sqlite:////opt/langflow/data/langflow.db
LANGFLOW_SECRET_KEY=${LANGFLOW_SECRET_KEY}
LANGFLOW_AUTO_LOGIN=false
LANGFLOW_SUPERUSER=${ADMIN_USER}
LANGFLOW_SUPERUSER_PASSWORD=${ADMIN_PASS}
LANGFLOW_HOST=0.0.0.0
LANGFLOW_PORT=7860
LANGFLOW_OPEN_BROWSER=false
LANGFLOW_LOG_LEVEL=info
DO_NOT_TRACK=true
LANGFLOW_REMOVE_API_KEYS=true
LANGFLOW_FALLBACK_TO_ENV_VAR=false
LANGFLOW_STORE_ENVIRONMENT_VARIABLES=false
LANGFLOW_WORKERS=${LANGFLOW_WORKERS_DEFAULT}
LANGFLOW_WORKER_TIMEOUT=300
LANGFLOW_HEALTH_CHECK_MAX_RETRIES=5
LANGFLOW_LAZY_LOAD_COMPONENTS=false
EOF2
chmod 600 /opt/langflow/.env
msg_ok "Configured Langflow"
msg_warn "Admin credentials are stored in /opt/langflow/.env"
msg_warn "Default admin user: ${ADMIN_USER}"
msg_warn "Generated admin password: ${ADMIN_PASS}"

msg_info "Creating Service"
cat <<'EOF2' >/etc/systemd/system/langflow.service
[Unit]
Description=Langflow Service
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/langflow
EnvironmentFile=/opt/langflow/.env
ExecStart=/opt/langflow/.venv/bin/langflow run --env-file /opt/langflow/.env --no-open-browser
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF2
systemctl enable -q --now langflow
msg_ok "Created Service"

motd_ssh
customize
cleanup_lxc