diff --git a/ct/adventurelog.sh b/ct/adventurelog.sh index 966afb2e4c7..c9cb7441c32 100644 --- a/ct/adventurelog.sh +++ b/ct/adventurelog.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: MickLesk (Canbiz) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -27,6 +27,8 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi + PYTHON_VERSION="3.12" setup_uv + RELEASE=$(curl -fsSL https://api.github.com/repos/seanmorley15/AdventureLog/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then msg_info "Stopping Services" @@ -43,10 +45,16 @@ function update_script() { mv /opt/adventurelog-backup/backend/server/.env /opt/adventurelog/backend/server/.env mv /opt/adventurelog-backup/backend/server/media /opt/adventurelog/backend/server/media cd /opt/adventurelog/backend/server - $STD pip install --upgrade pip - $STD pip install -r requirements.txt - $STD python3 manage.py collectstatic --noinput - $STD python3 manage.py migrate + $STD uv venv --python "$UV_PYTHON_VERSION" .venv + if grep -q "ExecStart=.*python3 manage.py runserver" /etc/systemd/system/adventurelog-backend.service; then + sed -i "s|ExecStart=.*python3 manage.py runserver|ExecStart=$(pwd)/.venv/bin/python manage.py runserver|" /etc/systemd/system/adventurelog-backend.service + systemctl daemon-reload + fi + + $STD uv pip install --upgrade pip --python=.venv/bin/python + $STD uv pip install -r requirements.txt --python=.venv/bin/python + $STD uv run --python=.venv/bin/python python manage.py collectstatic --noinput + $STD uv run --python=.venv/bin/python python manage.py migrate mv /opt/adventurelog-backup/frontend/.env /opt/adventurelog/frontend/.env cd /opt/adventurelog/frontend diff --git a/ct/archivebox.sh b/ct/archivebox.sh index d3289a75df7..52cef18c6e6 100644 --- a/ct/archivebox.sh +++ b/ct/archivebox.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,29 +20,45 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/archivebox ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Stopping ${APP}" - systemctl stop archivebox - msg_ok "Stopped ${APP}" - - msg_info "Updating ${APP}" - cd /opt/archivebox/data - pip install --upgrade --ignore-installed archivebox - sudo -u archivebox archivebox init - msg_ok "Updated ${APP}" - - msg_info "Starting ${APP}" - systemctl start archivebox - msg_ok "Started ${APP}" - - msg_ok "Updated Successfully" + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/archivebox ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Stopping ${APP}" + systemctl stop archivebox + msg_ok "Stopped ${APP}" + + msg_info "Updating ${APP}" + cd /opt/archivebox + $STD uv venv --python "$UV_PYTHON_VERSION" .venv + + if [[ -f /opt/archivebox/uv.lock ]]; then + cp /opt/archivebox/uv.lock /opt/archivebox/data/ || true + fi + + cd /opt/archivebox/data + $STD ../.venv/bin/uv sync + + msg_info "Running ArchiveBox Setup" + sudo -u archivebox ../.venv/bin/playwright install-deps chromium + sudo -u archivebox ../.venv/bin/playwright install chromium + sudo -u archivebox ../.venv/bin/archivebox init + msg_ok "ArchiveBox Updated" + + if grep -q "ExecStart=/usr/local/bin/archivebox" /etc/systemd/system/archivebox.service; then + sed -i "s|ExecStart=/usr/local/bin/archivebox|ExecStart=/opt/archivebox/.venv/bin/archivebox|" /etc/systemd/system/archivebox.service + systemctl daemon-reload + fi + + msg_info "Starting ${APP}" + systemctl start archivebox + msg_ok "Started ${APP}" + + msg_ok "Updated Successfully" + exit } start @@ -52,4 +68,4 @@ 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}:8000/admin/login${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8000/admin/login${CL}" diff --git a/ct/babybuddy.sh b/ct/babybuddy.sh index 741dbc84f48..8aedeb7ff7a 100644 --- a/ct/babybuddy.sh +++ b/ct/babybuddy.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: MickLesk (CanbiZ) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/bazarr.sh b/ct/bazarr.sh index d32aaa5206b..16d3af8a205 100755 --- a/ct/bazarr.sh +++ b/ct/bazarr.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,18 +20,18 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /var/lib/bazarr/ ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt-get update - $STD apt-get -y upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -d /var/lib/bazarr/ ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP LXC" + $STD apt-get update + $STD apt-get -y upgrade + msg_ok "Updated $APP LXC" + exit } start @@ -41,4 +41,4 @@ 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}:6767${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:6767${CL}" diff --git a/ct/calibre-web.sh b/ct/calibre-web.sh index 8a319618cc4..87d2d18045a 100644 --- a/ct/calibre-web.sh +++ b/ct/calibre-web.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) | Co-Author: remz1337 # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -135,4 +135,4 @@ 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}:8083${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8083${CL}" diff --git a/ct/changedetection.sh b/ct/changedetection.sh index 0f1bdeeeb68..3bd14ee001b 100644 --- a/ct/changedetection.sh +++ b/ct/changedetection.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -74,4 +74,4 @@ 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}:5000${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5000${CL}" diff --git a/ct/crafty-controller.sh b/ct/crafty-controller.sh index dfa6d413faa..363c9451e37 100644 --- a/ct/crafty-controller.sh +++ b/ct/crafty-controller.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts # Author: CrazyWolf13 # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/create_lxc.sh b/ct/create_lxc.sh index 7d0779919c2..0fd4a38a6b7 100644 --- a/ct/create_lxc.sh +++ b/ct/create_lxc.sh @@ -4,7 +4,7 @@ # Author: tteck (tteckster) # Co-Author: MickLesk # License: MIT -# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# https://github.com/community-scripts/ProxmoxVE/raw/python_to_uv/LICENSE # This sets verbose mode if the global variable is set to "yes" # if [ "$VERBOSE" == "yes" ]; then set -x; fi diff --git a/ct/deluge.sh b/ct/deluge.sh index 374efc777b3..95e1f448c63 100644 --- a/ct/deluge.sh +++ b/ct/deluge.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,18 +20,18 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /etc/systemd/system/deluged.service ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt-get update - pip3 install deluge[all] --upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -f /etc/systemd/system/deluged.service ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP LXC" + $STD apt-get update + pip3 install deluge[all] --upgrade + msg_ok "Updated $APP LXC" + exit } start @@ -41,4 +41,4 @@ 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}:8112${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8112${CL}" diff --git a/ct/documenso.sh b/ct/documenso.sh index 2d0b1bc5fad..7b557b9d6f6 100644 --- a/ct/documenso.sh +++ b/ct/documenso.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: MickLesk (CanbiZ) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/esphome.sh b/ct/esphome.sh index f9b086a62bb..52f726fada5 100644 --- a/ct/esphome.sh +++ b/ct/esphome.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -52,4 +52,4 @@ 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}:6052${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:6052${CL}" diff --git a/ct/grist.sh b/ct/grist.sh index 0e395a32b8d..e276f87f5f1 100644 --- a/ct/grist.sh +++ b/ct/grist.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Source: https://github.com/gristlabs/grist-core APP="Grist" diff --git a/ct/homeassistant.sh b/ct/homeassistant.sh index 6201915b919..8f33e4ab61c 100644 --- a/ct/homeassistant.sh +++ b/ct/homeassistant.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/homer.sh b/ct/homer.sh index 44c380e40ab..58fc3b8d378 100644 --- a/ct/homer.sh +++ b/ct/homer.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,44 +20,44 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/homer ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Stopping ${APP}" - systemctl stop homer - msg_ok "Stopped ${APP}" + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/homer ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + msg_info "Stopping ${APP}" + systemctl stop homer + msg_ok "Stopped ${APP}" - msg_info "Backing up assets directory" - cd ~ - mkdir -p assets-backup - cp -R /opt/homer/assets/. assets-backup - msg_ok "Backed up assets directory" + msg_info "Backing up assets directory" + cd ~ + mkdir -p assets-backup + cp -R /opt/homer/assets/. assets-backup + msg_ok "Backed up assets directory" - msg_info "Updating ${APP}" - rm -rf /opt/homer/* - cd /opt/homer - curl -fsSL "https://github.com/bastienwirtz/homer/releases/latest/download/homer.zip" -o $(basename "https://github.com/bastienwirtz/homer/releases/latest/download/homer.zip") - $STD unzip homer.zip - msg_ok "Updated ${APP}" + msg_info "Updating ${APP}" + rm -rf /opt/homer/* + cd /opt/homer + curl -fsSL "https://github.com/bastienwirtz/homer/releases/latest/download/homer.zip" -o $(basename "https://github.com/bastienwirtz/homer/releases/latest/download/homer.zip") + $STD unzip homer.zip + msg_ok "Updated ${APP}" - msg_info "Restoring assets directory" - cd ~ - cp -Rf assets-backup/. /opt/homer/assets/ - msg_ok "Restored assets directory" + msg_info "Restoring assets directory" + cd ~ + cp -Rf assets-backup/. /opt/homer/assets/ + msg_ok "Restored assets directory" - msg_info "Cleaning" - rm -rf assets-backup /opt/homer/homer.zip - msg_ok "Cleaned" + msg_info "Cleaning" + rm -rf assets-backup /opt/homer/homer.zip + msg_ok "Cleaned" - msg_info "Starting ${APP}" - systemctl start homer - msg_ok "Started ${APP}" - msg_ok "Updated Successfully" - exit + msg_info "Starting ${APP}" + systemctl start homer + msg_ok "Started ${APP}" + msg_ok "Updated Successfully" + exit } start diff --git a/ct/immich.sh b/ct/immich.sh index c925c52b00e..323683facdc 100644 --- a/ct/immich.sh +++ b/ct/immich.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: vhsdream # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -27,6 +27,9 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi + + setup_uv + STAGING_DIR=/opt/staging BASE_DIR=${STAGING_DIR}/base-images SOURCE_DIR=${STAGING_DIR}/image-source @@ -251,23 +254,16 @@ EOF msg_ok "Updated ${APP} web and microservices" cd "$SRC_DIR"/machine-learning - $STD python3 -m venv "$ML_DIR"/ml-venv + export VIRTUAL_ENV="${ML_DIR}/ml-venv" + $STD uv venv "$VIRTUAL_ENV" if [[ -f ~/.openvino ]]; then msg_info "Updating HW-accelerated machine-learning" - ( - source "$ML_DIR"/ml-venv/bin/activate - $STD pip3 install -U uv - uv -q sync --extra openvino --no-cache --active - ) - patchelf --clear-execstack "$ML_DIR"/ml-venv/lib/python3.11/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-311-x86_64-linux-gnu.so + uv -q sync --extra openvino --no-cache --active + patchelf --clear-execstack "${VIRTUAL_ENV}/lib/python3.11/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-311-x86_64-linux-gnu.so" msg_ok "Updated HW-accelerated machine-learning" else msg_info "Updating machine-learning" - ( - source "$ML_DIR"/ml-venv/bin/activate - $STD pip3 install -U uv - uv -q sync --extra cpu --no-cache --active - ) + uv -q sync --extra cpu --no-cache --active msg_ok "Updated machine-learning" fi cd "$SRC_DIR" diff --git a/ct/jupyternotebook.sh b/ct/jupyternotebook.sh index 2baf5baa8be..bca25ce7d39 100644 --- a/ct/jupyternotebook.sh +++ b/ct/jupyternotebook.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: Dave-code-creater (Tan Dat, Ta) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,16 +20,16 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - msg_info "Updating ${APP} LXC" - $STD apt-get update - $STD apt-get install -y upgrade - $STD pip3 install jupyter --upgrade - msg_ok "Updated Successfully" - exit + msg_info "Updating ${APP} LXC" + $STD apt-get update + $STD apt-get install -y upgrade + $STD pip3 install jupyter --upgrade + msg_ok "Updated Successfully" + exit } start @@ -39,4 +39,4 @@ 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}:8888${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8888${CL}" diff --git a/ct/kometa.sh b/ct/kometa.sh index ece16d5e9ae..00328c7d870 100644 --- a/ct/kometa.sh +++ b/ct/kometa.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: Slaviša Arežina (tremor021) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,51 +20,51 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - if [[ ! -f "/opt/kometa/kometa.py" ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - RELEASE=$(curl -fsSL https://api.github.com/repos/Kometa-Team/Kometa/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') - if [[ "${RELEASE}" != "$(cat /opt/kometa_version.txt)" ]] || [[ ! -f /opt/kometa_version.txt ]]; then - msg_info "Updating $APP" - msg_info "Stopping $APP" - systemctl stop kometa - msg_ok "Stopped $APP" + if [[ ! -f "/opt/kometa/kometa.py" ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + RELEASE=$(curl -fsSL https://api.github.com/repos/Kometa-Team/Kometa/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') + if [[ "${RELEASE}" != "$(cat /opt/kometa_version.txt)" ]] || [[ ! -f /opt/kometa_version.txt ]]; then + msg_info "Updating $APP" + msg_info "Stopping $APP" + systemctl stop kometa + msg_ok "Stopped $APP" - msg_info "Updating $APP to ${RELEASE}" - cd /tmp - temp_file=$(mktemp) - RELEASE=$(curl -fsSL https://api.github.com/repos/Kometa-Team/Kometa/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') -curl -fsSL "https://github.com/Kometa-Team/Kometa/archive/refs/tags/v${RELEASE}.tar.gz" -o ""$temp_file"" - tar -xzf "$temp_file" - cp /opt/kometa/config/config.yml /opt - rm -rf /opt/kometa - mv Kometa-${RELEASE} /opt/kometa - cd /opt/kometa - rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED - $STD pip install -r requirements.txt --ignore-installed - mkdir -p config/assets - cp /opt/config.yml config/config.yml - echo "${RELEASE}" >/opt/kometa_version.txt - msg_ok "Updated $APP to ${RELEASE}" + msg_info "Updating $APP to ${RELEASE}" + cd /tmp + temp_file=$(mktemp) + RELEASE=$(curl -fsSL https://api.github.com/repos/Kometa-Team/Kometa/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') + curl -fsSL "https://github.com/Kometa-Team/Kometa/archive/refs/tags/v${RELEASE}.tar.gz" -o ""$temp_file"" + tar -xzf "$temp_file" + cp /opt/kometa/config/config.yml /opt + rm -rf /opt/kometa + mv Kometa-${RELEASE} /opt/kometa + cd /opt/kometa + rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED + $STD pip install -r requirements.txt --ignore-installed + mkdir -p config/assets + cp /opt/config.yml config/config.yml + echo "${RELEASE}" >/opt/kometa_version.txt + msg_ok "Updated $APP to ${RELEASE}" - msg_info "Starting $APP" - systemctl start kometa - msg_ok "Started $APP" + msg_info "Starting $APP" + systemctl start kometa + msg_ok "Started $APP" - msg_info "Cleaning Up" - rm -f $temp_file - msg_ok "Cleanup Completed" + msg_info "Cleaning Up" + rm -f $temp_file + msg_ok "Cleanup Completed" - msg_ok "Update Successful" - else - msg_ok "No update required. ${APP} is already at ${RELEASE}" - fi - exit + msg_ok "Update Successful" + else + msg_ok "No update required. ${APP} is already at ${RELEASE}" + fi + exit } start @@ -74,4 +74,4 @@ description msg_ok "Completed Successfully!\n" echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" echo -e "${INFO}${YW} Access the LXC at following IP address:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}${IP}${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}${IP}${CL}" diff --git a/ct/lazylibrarian.sh b/ct/lazylibrarian.sh index 478629771a8..e4f1d0755e7 100644 --- a/ct/lazylibrarian.sh +++ b/ct/lazylibrarian.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck | Co-Author: MountyMapleSyrup (MountyMapleSyrup) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,27 +20,27 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/LazyLibrarian/ ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Stopping LazyLibrarian" - systemctl stop lazylibrarian - msg_ok "LazyLibrarian Stopped" - - msg_info "Updating $APP LXC" - $STD git -C /opt/LazyLibrarian pull origin master - msg_ok "Updated $APP LXC" - - msg_info "Starting LazyLibrarian" - systemctl start lazylibrarian - msg_ok "Started LazyLibrarian" - - msg_ok "Updated Successfully" + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/LazyLibrarian/ ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Stopping LazyLibrarian" + systemctl stop lazylibrarian + msg_ok "LazyLibrarian Stopped" + + msg_info "Updating $APP LXC" + $STD git -C /opt/LazyLibrarian pull origin master + msg_ok "Updated $APP LXC" + + msg_info "Starting LazyLibrarian" + systemctl start lazylibrarian + msg_ok "Started LazyLibrarian" + + msg_ok "Updated Successfully" + exit } start @@ -50,4 +50,4 @@ 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}:5299${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5299${CL}" diff --git a/ct/medusa.sh b/ct/medusa.sh index 6c8299a3874..6ad32e7864e 100644 --- a/ct/medusa.sh +++ b/ct/medusa.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -53,4 +53,4 @@ 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}:8081${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8081${CL}" diff --git a/ct/metube.sh b/ct/metube.sh index 287ea264ec6..db4fd47a44f 100644 --- a/ct/metube.sh +++ b/ct/metube.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: MickLesk (Canbiz) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -8,7 +8,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV APP="MeTube" var_tags="${var_tags:-media;youtube}" var_cpu="${var_cpu:-1}" -var_ram="${var_ram:-1024}" +var_ram="${var_ram:-2048}" var_disk="${var_disk:-10}" var_os="${var_os:-debian}" var_version="${var_version:-12}" @@ -23,40 +23,96 @@ function update_script() { header_info check_container_storage check_container_resources + if [[ ! -d /opt/metube ]]; then msg_error "No ${APP} Installation Found!" exit fi + msg_info "Stopping ${APP} Service" systemctl stop metube msg_ok "Stopped ${APP} Service" - msg_info "Updating ${APP} to latest Git" - cd /opt - if [ -d metube_bak ]; then - rm -rf metube_bak + msg_info "Backing up Old Installation" + if [[ -d /opt/metube_bak ]]; then + rm -rf /opt/metube_bak fi - mv metube metube_bak + mv /opt/metube /opt/metube_bak + msg_ok "Backup created" + + msg_info "Cloning Latest ${APP} Release" $STD git clone https://github.com/alexta69/metube /opt/metube + msg_ok "Cloned ${APP}" + + msg_info "Building Frontend" cd /opt/metube/ui $STD npm install $STD node_modules/.bin/ng build + msg_ok "Built Frontend" + + PYTHON_VERSION="3.13" setup_uv + + msg_info "Setting up Python Environment (uv)" + $STD uv venv /opt/metube/.venv + $STD /opt/metube/.venv/bin/python -m ensurepip --upgrade + $STD /opt/metube/.venv/bin/python -m pip install --upgrade pip + $STD /opt/metube/.venv/bin/python -m pip install pipenv + msg_ok "Python Environment Ready" + + msg_info "Installing Backend Requirements" cd /opt/metube - cp /opt/metube_bak/.env /opt/metube/ - $STD pip3 install pipenv - $STD pipenv install + $STD /opt/metube/.venv/bin/pipenv install + msg_ok "Installed Backend" - if [ -d "/opt/metube_bak" ]; then - rm -rf /opt/metube_bak + msg_info "Restoring Environment File" + if [[ -f /opt/metube_bak/.env ]]; then + cp /opt/metube_bak/.env /opt/metube/.env + fi + msg_ok "Restored .env" + + if [[ ! -d /opt/metube/.venv ]]; then + msg_info "Migrating to uv-based environment" + PYTHON_VERSION="3.13" setup_uv + $STD uv venv /opt/metube/.venv + $STD /opt/metube/.venv/bin/python -m ensurepip --upgrade + $STD /opt/metube/.venv/bin/python -m pip install --upgrade pip + $STD /opt/metube/.venv/bin/python -m pip install pipenv + $STD /opt/metube/.venv/bin/pipenv install + + msg_info "Patching systemd Service" + cat </etc/systemd/system/metube.service +[Unit] +Description=Metube - YouTube Downloader +After=network.target + +[Service] +Type=simple +WorkingDirectory=/opt/metube +EnvironmentFile=/opt/metube/.env +ExecStart=/opt/metube/.venv/bin/pipenv run python3 app/main.py +Restart=always +User=root + +[Install] +WantedBy=multi-user.target +EOF + msg_ok "Patched systemd Service" fi - msg_ok "Updated ${APP} to latest Git" + $STD systemctl daemon-reload + msg_ok "Service Updated" + + msg_info "Cleaning up" + rm -rf /opt/metube_bak + $STD apt-get -y autoremove + $STD apt-get -y autoclean + msg_ok "Cleaned Up" msg_info "Starting ${APP} Service" - systemctl start metube + systemctl enable -q --now metube sleep 1 msg_ok "Started ${APP} Service" - msg_ok "Updated Successfully!\n" - exit + + msg_ok "Updated Successfully!" } start @@ -66,4 +122,4 @@ 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}:8081${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8081${CL}" diff --git a/ct/motioneye.sh b/ct/motioneye.sh index 778717ddda4..06d1224fa4b 100644 --- a/ct/motioneye.sh +++ b/ct/motioneye.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,17 +20,17 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /etc/systemd/system/motioneye.service ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating ${APP} LXC" - $STD pip install motioneye --upgrade - msg_ok "Updated Successfully" + header_info + check_container_storage + check_container_resources + if [[ ! -f /etc/systemd/system/motioneye.service ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating ${APP} LXC" + $STD pip install motioneye --upgrade + msg_ok "Updated Successfully" + exit } start @@ -40,4 +40,4 @@ 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}:8765${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8765${CL}" diff --git a/ct/mylar3.sh b/ct/mylar3.sh index 218f4e1587b..1cae52b444e 100644 --- a/ct/mylar3.sh +++ b/ct/mylar3.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: davalanche # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -29,7 +29,7 @@ function update_script() { if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then msg_info "Updating ${APP} to ${RELEASE}" rm -rf /opt/mylar3/* /opt/mylar3/.* -curl -fsSL "https://github.com/mylar3/mylar3/archive/refs/tags/${RELEASE}.tar.gz" | tar -xz --strip-components=1 -C /opt/mylar3 + curl -fsSL "https://github.com/mylar3/mylar3/archive/refs/tags/${RELEASE}.tar.gz" | tar -xz --strip-components=1 -C /opt/mylar3 systemctl restart mylar3 echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP} to ${RELEASE}" @@ -46,4 +46,4 @@ 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}:8090${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8090${CL}" diff --git a/ct/netbox.sh b/ct/netbox.sh index e5dd28d8ecc..d0d348deffd 100644 --- a/ct/netbox.sh +++ b/ct/netbox.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: bvdberg01 # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/nginxproxymanager.sh b/ct/nginxproxymanager.sh index d5b2323be2a..246f8b85dc4 100644 --- a/ct/nginxproxymanager.sh +++ b/ct/nginxproxymanager.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/octoprint.sh b/ct/octoprint.sh index 01a5b36bd4d..ac3d912c6b5 100644 --- a/ct/octoprint.sh +++ b/ct/octoprint.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,27 +20,27 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/octoprint ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Stopping OctoPrint" - systemctl stop octoprint - msg_ok "Stopped OctoPrint" + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/octoprint ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + msg_info "Stopping OctoPrint" + systemctl stop octoprint + msg_ok "Stopped OctoPrint" - msg_info "Updating OctoPrint" - source /opt/octoprint/bin/activate - $STD pip3 install octoprint --upgrade - msg_ok "Updated OctoPrint" + msg_info "Updating OctoPrint" + source /opt/octoprint/bin/activate + $STD pip3 install octoprint --upgrade + msg_ok "Updated OctoPrint" - msg_info "Starting OctoPrint" - systemctl start octoprint - msg_ok "Started OctoPrint" - msg_ok "Updated Successfully" - exit + msg_info "Starting OctoPrint" + systemctl start octoprint + msg_ok "Started OctoPrint" + msg_ok "Updated Successfully" + exit } start @@ -50,4 +50,4 @@ 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}:5000${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5000${CL}" diff --git a/ct/openwebui.sh b/ct/openwebui.sh index 0824a797779..7904f2a6fca 100644 --- a/ct/openwebui.sh +++ b/ct/openwebui.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: havardthom # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/paperless-ai.sh b/ct/paperless-ai.sh index ac9fe430b98..778a5f65b7c 100644 --- a/ct/paperless-ai.sh +++ b/ct/paperless-ai.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: MickLesk (CanbiZ) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/paperless-ngx.sh b/ct/paperless-ngx.sh index d3904274b92..e959118a2ca 100644 --- a/ct/paperless-ngx.sh +++ b/ct/paperless-ngx.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/pialert.sh b/ct/pialert.sh index 032944bb154..d61ccebac5f 100644 --- a/ct/pialert.sh +++ b/ct/pialert.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,16 +20,16 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/pialert ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - bash -c "$(curl -fsSL https://github.com/leiweibau/Pi.Alert/raw/main/install/pialert_update.sh)" -s --lxc - msg_ok "Updated $APP" + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/pialert ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + bash -c "$(curl -fsSL https://github.com/leiweibau/Pi.Alert/raw/main/install/pialert_update.sh)" -s --lxc + msg_ok "Updated $APP" + exit } start diff --git a/ct/prometheus-pve-exporter.sh b/ct/prometheus-pve-exporter.sh index 34c1b2611b5..8fbe7610e02 100644 --- a/ct/prometheus-pve-exporter.sh +++ b/ct/prometheus-pve-exporter.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: Andy Grunwald (andygrunwald) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,26 +20,26 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /etc/systemd/system/prometheus-pve-exporter.service ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Stopping ${APP}" - systemctl stop prometheus-pve-exporter - msg_ok "Stopped ${APP}" + header_info + check_container_storage + check_container_resources + if [[ ! -f /etc/systemd/system/prometheus-pve-exporter.service ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + msg_info "Stopping ${APP}" + systemctl stop prometheus-pve-exporter + msg_ok "Stopped ${APP}" - msg_info "Updating ${APP}" - $STD pip install prometheus-pve-exporter --default-timeout=300 --upgrade --root-user-action=ignore - msg_ok "Updated ${APP}" + msg_info "Updating ${APP}" + $STD pip install prometheus-pve-exporter --default-timeout=300 --upgrade --root-user-action=ignore + msg_ok "Updated ${APP}" - msg_info "Starting ${APP}" - systemctl start prometheus-pve-exporter - msg_ok "Started ${APP}" - msg_ok "Updated Successfully" - exit + msg_info "Starting ${APP}" + systemctl start prometheus-pve-exporter + msg_ok "Started ${APP}" + msg_ok "Updated Successfully" + exit } start @@ -49,4 +49,4 @@ 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}:9221${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9221${CL}" diff --git a/ct/radicale.sh b/ct/radicale.sh index 00c851342dc..dada46ceeec 100644 --- a/ct/radicale.sh +++ b/ct/radicale.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: tremor021 # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,25 +20,25 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/radicale ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - - msg_info "Updating ${APP}" - python3 -m venv /opt/radicale - source /opt/radicale/bin/activate - python3 -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz - msg_ok "Updated ${APP}" - - msg_info "Starting Service" - systemctl enable -q --now radicale - msg_ok "Started Service" - + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/radicale ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + + msg_info "Updating ${APP}" + python3 -m venv /opt/radicale + source /opt/radicale/bin/activate + python3 -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz + msg_ok "Updated ${APP}" + + msg_info "Starting Service" + systemctl enable -q --now radicale + msg_ok "Started Service" + + exit } start @@ -48,4 +48,4 @@ 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}:5232${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5232${CL}" diff --git a/ct/sabnzbd.sh b/ct/sabnzbd.sh index 01d51679774..910baa65925 100644 --- a/ct/sabnzbd.sh +++ b/ct/sabnzbd.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) | Co-Author: MickLesk (CanbiZ) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,44 +20,44 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - if [[ ! -d /opt/sabnzbd ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - setup_uv - RELEASE=$(curl -fsSL https://api.github.com/repos/sabnzbd/sabnzbd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - if [[ -f /opt/${APP}_version.txt ]] && [[ "${RELEASE}" == "$(cat /opt/${APP}_version.txt)" ]]; then - msg_ok "No update required. ${APP} is already at ${RELEASE}" - exit - fi - msg_info "Updating $APP to ${RELEASE}" - systemctl stop sabnzbd - cp -r /opt/sabnzbd /opt/sabnzbd_backup_$(date +%s) - temp_file=$(mktemp) - curl -fsSL "https://github.com/sabnzbd/sabnzbd/releases/download/${RELEASE}/SABnzbd-${RELEASE}-src.tar.gz" -o "$temp_file" - tar -xzf "$temp_file" -C /opt/sabnzbd --strip-components=1 - rm -f "$temp_file" - if [[ ! -d /opt/sabnzbd/venv ]]; then - msg_info "Migrating SABnzbd to uv virtual environment" - $STD uv venv /opt/sabnzbd/venv - msg_ok "Created uv venv at /opt/sabnzbd/venv" + if [[ ! -d /opt/sabnzbd ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + setup_uv + RELEASE=$(curl -fsSL https://api.github.com/repos/sabnzbd/sabnzbd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') + if [[ -f /opt/${APP}_version.txt ]] && [[ "${RELEASE}" == "$(cat /opt/${APP}_version.txt)" ]]; then + msg_ok "No update required. ${APP} is already at ${RELEASE}" + exit + fi + msg_info "Updating $APP to ${RELEASE}" + systemctl stop sabnzbd + cp -r /opt/sabnzbd /opt/sabnzbd_backup_$(date +%s) + temp_file=$(mktemp) + curl -fsSL "https://github.com/sabnzbd/sabnzbd/releases/download/${RELEASE}/SABnzbd-${RELEASE}-src.tar.gz" -o "$temp_file" + tar -xzf "$temp_file" -C /opt/sabnzbd --strip-components=1 + rm -f "$temp_file" + if [[ ! -d /opt/sabnzbd/venv ]]; then + msg_info "Migrating SABnzbd to uv virtual environment" + $STD uv venv /opt/sabnzbd/venv + msg_ok "Created uv venv at /opt/sabnzbd/venv" - if grep -q "ExecStart=python3 SABnzbd.py" /etc/systemd/system/sabnzbd.service; then - sed -i "s|ExecStart=python3 SABnzbd.py|ExecStart=/opt/sabnzbd/venv/bin/python SABnzbd.py|" /etc/systemd/system/sabnzbd.service - systemctl daemon-reload - msg_ok "Updated SABnzbd service to use uv venv" - fi + if grep -q "ExecStart=python3 SABnzbd.py" /etc/systemd/system/sabnzbd.service; then + sed -i "s|ExecStart=python3 SABnzbd.py|ExecStart=/opt/sabnzbd/venv/bin/python SABnzbd.py|" /etc/systemd/system/sabnzbd.service + systemctl daemon-reload + msg_ok "Updated SABnzbd service to use uv venv" fi - $STD uv pip install --upgrade pip --python=/opt/sabnzbd/venv/bin/python - $STD uv pip install -r /opt/sabnzbd/requirements.txt --python=/opt/sabnzbd/venv/bin/python - echo "${RELEASE}" >/opt/${APP}_version.txt - systemctl start sabnzbd - msg_ok "Updated ${APP} to ${RELEASE}" - exit + fi + $STD uv pip install --upgrade pip --python=/opt/sabnzbd/venv/bin/python + $STD uv pip install -r /opt/sabnzbd/requirements.txt --python=/opt/sabnzbd/venv/bin/python + echo "${RELEASE}" >/opt/${APP}_version.txt + systemctl start sabnzbd + msg_ok "Updated ${APP} to ${RELEASE}" + exit } start @@ -68,4 +68,3 @@ 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}:7777${CL}" - diff --git a/ct/searxng.sh b/ct/searxng.sh index 7d9df8d60ba..e2ac0558131 100644 --- a/ct/searxng.sh +++ b/ct/searxng.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: MickLesk (Canbiz) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/slskd.sh b/ct/slskd.sh index 3b8c305bc14..5eec537f67f 100644 --- a/ct/slskd.sh +++ b/ct/slskd.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: vhsdream # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/spoolman.sh b/ct/spoolman.sh index 71ca777775a..d15abba6850 100644 --- a/ct/spoolman.sh +++ b/ct/spoolman.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: MickLesk (Canbiz) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/stirling-pdf.sh b/ct/stirling-pdf.sh index d94ae6f2993..ef05b41d73f 100644 --- a/ct/stirling-pdf.sh +++ b/ct/stirling-pdf.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/tandoor.sh b/ct/tandoor.sh index 085b28f17e7..20998998c0a 100644 --- a/ct/tandoor.sh +++ b/ct/tandoor.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: MickLesk (Canbiz) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/tasmocompiler.sh b/ct/tasmocompiler.sh index a791c3098a5..74ea7b55dd4 100644 --- a/ct/tasmocompiler.sh +++ b/ct/tasmocompiler.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: Slaviša Arežina (tremor021) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,43 +20,43 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/tasmocompiler ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - RELEASE=$(curl -fsSL https://api.github.com/repos/benzino77/tasmocompiler/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') - if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then - msg_info "Stopping $APP" - systemctl stop tasmocompiler - msg_ok "Stopped $APP" - msg_info "Updating $APP to v${RELEASE}" - cd /opt - rm -rf /opt/tasmocompiler - RELEASE=$(curl -fsSL https://api.github.com/repos/benzino77/tasmocompiler/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') - curl -fsSL "https://github.com/benzino77/tasmocompiler/archive/refs/tags/v${RELEASE}.tar.gz" -o $(basename "https://github.com/benzino77/tasmocompiler/archive/refs/tags/v${RELEASE}.tar.gz") - tar xzf v${RELEASE}.tar.gz - mv tasmocompiler-${RELEASE}/ /opt/tasmocompiler/ - cd /opt/tasmocompiler - $STD yarn install - export NODE_OPTIONS=--openssl-legacy-provider - $STD npm i - $STD yarn build - msg_ok "Updated $APP to v${RELEASE}" - msg_info "Starting $APP" - systemctl start tasmocompiler - msg_ok "Started $APP" - echo "${RELEASE}" >/opt/${APP}_version.txt - msg_info "Cleaning up" - rm -r "/opt/v${RELEASE}.tar.gz" - msg_ok "Cleaned" - msg_ok "Update Successful" - else - msg_ok "No update required. ${APP} is already at v${RELEASE}" - fi + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/tasmocompiler ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + RELEASE=$(curl -fsSL https://api.github.com/repos/benzino77/tasmocompiler/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') + if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then + msg_info "Stopping $APP" + systemctl stop tasmocompiler + msg_ok "Stopped $APP" + msg_info "Updating $APP to v${RELEASE}" + cd /opt + rm -rf /opt/tasmocompiler + RELEASE=$(curl -fsSL https://api.github.com/repos/benzino77/tasmocompiler/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') + curl -fsSL "https://github.com/benzino77/tasmocompiler/archive/refs/tags/v${RELEASE}.tar.gz" -o $(basename "https://github.com/benzino77/tasmocompiler/archive/refs/tags/v${RELEASE}.tar.gz") + tar xzf v${RELEASE}.tar.gz + mv tasmocompiler-${RELEASE}/ /opt/tasmocompiler/ + cd /opt/tasmocompiler + $STD yarn install + export NODE_OPTIONS=--openssl-legacy-provider + $STD npm i + $STD yarn build + msg_ok "Updated $APP to v${RELEASE}" + msg_info "Starting $APP" + systemctl start tasmocompiler + msg_ok "Started $APP" + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_info "Cleaning up" + rm -r "/opt/v${RELEASE}.tar.gz" + msg_ok "Cleaned" + msg_ok "Update Successful" + else + msg_ok "No update required. ${APP} is already at v${RELEASE}" + fi + exit } start diff --git a/ct/tautulli.sh b/ct/tautulli.sh index 263dc6193a1..2609eb31d9f 100644 --- a/ct/tautulli.sh +++ b/ct/tautulli.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,18 +20,18 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/Tautulli/ ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_info "Updating $APP LXC" - $STD apt-get update - $STD apt-get -y upgrade - msg_ok "Updated $APP LXC" + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/Tautulli/ ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_info "Updating $APP LXC" + $STD apt-get update + $STD apt-get -y upgrade + msg_ok "Updated $APP LXC" + exit } start @@ -41,4 +41,4 @@ 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}:8181${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8181${CL}" diff --git a/ct/tianji.sh b/ct/tianji.sh index ed89d07d225..031ad8d529c 100644 --- a/ct/tianji.sh +++ b/ct/tianji.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: MickLesk (Canbiz) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/ct/unmanic.sh b/ct/unmanic.sh index b0329cb748e..6fd0b99dd53 100644 --- a/ct/unmanic.sh +++ b/ct/unmanic.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 tteck # Author: tteck (tteckster) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -41,4 +41,4 @@ 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}:8888${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8888${CL}" diff --git a/ct/web-check.sh b/ct/web-check.sh index 635ebac48e9..0942fc1c720 100644 --- a/ct/web-check.sh +++ b/ct/web-check.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: CrazyWolf13 # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE @@ -20,15 +20,15 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/web-check ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - msg_error "Currently we don't provide an update function for this ${APP}." + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/web-check ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + msg_error "Currently we don't provide an update function for this ${APP}." + exit } start @@ -38,4 +38,4 @@ 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}:3000${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}" diff --git a/ct/wger.sh b/ct/wger.sh index cd0e4d26775..ad952a34fcb 100644 --- a/ct/wger.sh +++ b/ct/wger.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/build.func) # Copyright (c) 2021-2025 community-scripts ORG # Author: Slaviša Arežina (tremor021) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE diff --git a/install/adventurelog-install.sh b/install/adventurelog-install.sh index a56cd6949f2..6935a3a58a9 100644 --- a/install/adventurelog-install.sh +++ b/install/adventurelog-install.sh @@ -18,11 +18,10 @@ msg_info "Installing Dependencies" $STD apt-get install -y \ gdal-bin \ libgdal-dev \ - git \ - python3-venv \ - python3-pip + git msg_ok "Installed Dependencies" +PYTHON_VERSION="3.12" setup_uv NODE_VERSION="22" NODE_MODULE="pnpm@latest" install_node_and_modules PG_VERSION="16" PG_MODULES="postgis" install_postgresql @@ -79,11 +78,13 @@ DISABLE_REGISTRATION=False EOF cd /opt/adventurelog/backend/server mkdir -p /opt/adventurelog/backend/server/media -$STD pip install --upgrade pip -$STD pip install -r requirements.txt -$STD python3 manage.py collectstatic --noinput -$STD python3 manage.py migrate -$STD python3 manage.py download-countries +$STD uv venv /opt/adventurelog/backend/server/.venv +$STD /opt/adventurelog/backend/server/.venv/bin/python -m ensurepip --upgrade +$STD /opt/adventurelog/backend/server/.venv/bin/python -m pip install --upgrade pip +$STD /opt/adventurelog/backend/server/.venv/bin/python -m pip install -r requirements.txt +$STD /opt/adventurelog/backend/server/.venv/bin/python -m manage collectstatic --noinput +$STD /opt/adventurelog/backend/server/.venv/bin/python -m manage migrate +$STD /opt/adventurelog/backend/server/.venv/bin/python -m manage download-countries cat </opt/adventurelog/frontend/.env PUBLIC_SERVER_URL=http://$LOCAL_IP:8000 BODY_SIZE_LIMIT=Infinity @@ -96,7 +97,8 @@ echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt" msg_ok "Installed AdventureLog" msg_info "Setting up Django Admin" -$STD python3 /opt/adventurelog/backend/server/manage.py shell </etc/systemd/system/archivebox.service @@ -79,12 +83,13 @@ After=network.target [Service] User=archivebox WorkingDirectory=/opt/archivebox/data -ExecStart=/usr/local/bin/archivebox server 0.0.0.0:8000 +ExecStart=/opt/archivebox/.venv/bin/archivebox server 0.0.0.0:8000 Restart=always [Install] WantedBy=multi-user.target EOF + systemctl enable -q --now archivebox msg_ok "Created Service" diff --git a/install/babybuddy-install.sh b/install/babybuddy-install.sh index 424edaa119f..827abafbfb8 100644 --- a/install/babybuddy-install.sh +++ b/install/babybuddy-install.sh @@ -19,8 +19,7 @@ $STD apt-get install -y \ uwsgi-plugin-python3 \ libopenjp2-7-dev \ libpq-dev \ - nginx \ - python3 + nginx msg_ok "Installed Dependencies" setup_uv @@ -32,9 +31,13 @@ mkdir -p /opt/{babybuddy,data} curl -fsSL "https://github.com/babybuddy/babybuddy/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file" tar zxf "$temp_file" --strip-components=1 -C /opt/babybuddy cd /opt/babybuddy -$STD uv venv .venv -$STD source .venv/bin/activate -$STD uv pip install -r requirements.txt +setup_uv + +$STD uv venv /opt/babybuddy/.venv +$STD /opt/babybuddy/.venv/bin/python -m ensurepip --upgrade +$STD /opt/babybuddy/.venv/bin/python -m pip install --upgrade pip +$STD /opt/babybuddy/.venv/bin/python -m pip install -r requirements.txt + cp babybuddy/settings/production.example.py babybuddy/settings/production.py SECRET_KEY=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-32) ALLOWED_HOSTS=$(hostname -I | tr ' ' ',' | sed 's/,$//')",127.0.0.1,localhost" @@ -44,7 +47,8 @@ sed -i \ babybuddy/settings/production.py export DJANGO_SETTINGS_MODULE=babybuddy.settings.production -$STD python manage.py migrate +cd /opt/babybuddy +$STD /opt/babybuddy/.venv/bin/python -m manage migrate chown -R www-data:www-data /opt/data chmod 640 /opt/data/db.sqlite3 chmod 750 /opt/data @@ -93,7 +97,7 @@ server { EOF ln -sf /etc/nginx/sites-available/babybuddy /etc/nginx/sites-enabled/babybuddy -rm /etc/nginx/sites-enabled/default +rm -f /etc/nginx/sites-enabled/default systemctl enable -q --now nginx service nginx reload msg_ok "Configured NGINX" diff --git a/install/bazarr-install.sh b/install/bazarr-install.sh index 7837b815384..d518bed2583 100755 --- a/install/bazarr-install.sh +++ b/install/bazarr-install.sh @@ -13,20 +13,18 @@ setting_up_container network_check update_os -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-dev \ - python3-pip -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" +PYTHON_VERSION="3.12" setup_uv msg_info "Installing Bazarr" mkdir -p /var/lib/bazarr/ curl -fsSL "https://github.com/morpheus65535/bazarr/releases/latest/download/bazarr.zip" -o "bazarr.zip" $STD unzip bazarr -d /opt/bazarr chmod 775 /opt/bazarr /var/lib/bazarr/ -$STD python3 -m pip install -q -r /opt/bazarr/requirements.txt +cd /opt/bazarr +$STD uv venv /opt/bazarr/.venv +$STD /opt/bazarr/.venv/bin/python -m ensurepip --upgrade +$STD /opt/bazarr/.venv/bin/python -m pip install --upgrade pip +$STD /opt/bazarr/.venv/bin/python -m pip install -r requirements.txt msg_ok "Installed Bazarr" msg_info "Creating Service" @@ -41,7 +39,7 @@ UMask=0002 Restart=on-failure RestartSec=5 Type=simple -ExecStart=/usr/bin/python3 /opt/bazarr/bazarr.py +ExecStart=/opt/bazarr/.venv/bin/python /opt/bazarr/bazarr.py KillSignal=SIGINT TimeoutStopSec=20 SyslogIdentifier=bazarr diff --git a/install/calibre-web-install.sh b/install/calibre-web-install.sh index ff4d47dd79b..7ad2bf0f3fd 100644 --- a/install/calibre-web-install.sh +++ b/install/calibre-web-install.sh @@ -15,13 +15,10 @@ network_check update_os msg_info "Installing Dependencies" -$STD apt-get install -y imagemagick +$STD apt-get install -y imagemagick calibre msg_ok "Installed Dependencies" -msg_info "Installing Python Dependencies" -$STD apt-get -y install python3-pip -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Installed Python Dependencies" +PYTHON_VERSION="3.12" setup_uv msg_info "Installing Kepubify" mkdir -p /opt/kepubify @@ -32,10 +29,10 @@ msg_ok "Installed Kepubify" msg_info "Installing Calibre-Web" mkdir -p /opt/calibre-web -$STD apt-get install -y calibre $STD curl -fsSL https://github.com/janeczku/calibre-web/raw/master/library/metadata.db -o /opt/calibre-web/metadata.db -$STD pip install calibreweb -$STD pip install jsonschema +cd /opt/calibre-web +$STD uv venv /opt/calibre-web/.venv +$STD uv pip install calibreweb jsonschema msg_ok "Installed Calibre-Web" msg_info "Creating Service" @@ -47,7 +44,7 @@ After=network.target [Service] Type=simple WorkingDirectory=/opt/calibre-web -ExecStart=/usr/local/bin/cps +ExecStart=/opt/calibre-web/.venv/bin/cps TimeoutStopSec=20 KillMode=process Restart=on-failure diff --git a/install/changedetection-install.sh b/install/changedetection-install.sh index 976b6159d7a..168302703c3 100644 --- a/install/changedetection-install.sh +++ b/install/changedetection-install.sh @@ -43,24 +43,19 @@ $STD apt-get install -y \ ca-certificates msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-dev \ - python3-pip -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" - +PYTHON_VERSION="3.12" setup_uv NODE_VERSION="22" install_node_and_modules msg_info "Installing Change Detection" -mkdir /opt/changedetection -$STD pip3 install changedetection.io +mkdir -p /opt/changedetection +cd /opt/changedetection +$STD uv venv /opt/changedetection/.venv +$STD uv pip install changedetection.io msg_ok "Installed Change Detection" msg_info "Installing Browserless & Playwright" mkdir /opt/browserless -$STD python3 -m pip install playwright +$STD /opt/paperless/.venv/bin/uv pip install playwright $STD git clone https://github.com/browserless/chrome /opt/browserless $STD npm install --prefix /opt/browserless $STD /opt/browserless/node_modules/playwright-core/cli.js install --with-deps &>/dev/null @@ -117,7 +112,7 @@ Type=simple WorkingDirectory=/opt/changedetection Environment=WEBDRIVER_URL=http://127.0.0.1:4444/wd/hub Environment=PLAYWRIGHT_DRIVER_URL=ws://localhost:3000/chrome?launch={"defaultViewport":{"height":720,"width":1280},"headless":false,"stealth":true}&blockAds=true -ExecStart=changedetection.io -d /opt/changedetection -p 5000 +ExecStart=/opt/changedetection/.venv/bin/changedetection.io -d /opt/changedetection -p 5000 [Install] WantedBy=multi-user.target EOF diff --git a/install/crafty-controller-install.sh b/install/crafty-controller-install.sh index d12e9ae6fd7..b924f39519d 100644 --- a/install/crafty-controller-install.sh +++ b/install/crafty-controller-install.sh @@ -13,7 +13,7 @@ setting_up_container network_check update_os -msg_info "Installing Dependencies (a lot of patience)" +msg_info "Installing Dependencies (Patience)" $STD apt-get install -y \ git \ sed \ @@ -23,6 +23,8 @@ $STD apt-get install -y \ software-properties-common msg_ok "Installed Dependencies" +PYTHON_VERSION="3.12" setup_uv + msg_info "Setting up TemurinJDK" mkdir -p /etc/apt/keyrings curl -fsSL "https://packages.adoptium.net/artifactory/api/gpg/key/public" | tee /etc/apt/keyrings/adoptium.asc @@ -32,20 +34,11 @@ $STD apt-get install -y temurin-{8,11,17,21}-jre sudo update-alternatives --set java /usr/lib/jvm/temurin-21-jre-amd64/bin/java msg_ok "Installed TemurinJDK" -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-dev \ - python3-pip \ - python3-venv -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" - msg_info "Installing Craty-Controller (Patience)" useradd crafty -m -s /bin/bash cd /opt mkdir -p /opt/crafty-controller/crafty /opt/crafty-controller/server -RELEASE=$(curl -fsSL "https://gitlab.com/api/v4/projects/20430749/releases" | grep -o '"tag_name":"v[^"]*"' | head -n 1 | sed 's/"tag_name":"v//;s/"//') +RELEASE=$(curl -fsSL "https://gitlab.com/api/v4/projects/20430749/releases" | grep -o '"tag_name":"v[^\"]*"' | head -n 1 | sed 's/"tag_name":"v//;s/"//') echo "${RELEASE}" >"/opt/crafty-controller_version.txt" curl -fsSL "https://gitlab.com/crafty-controller/crafty-4/-/archive/v${RELEASE}/crafty-4-v${RELEASE}.zip" -o "crafty-4-v${RELEASE}.zip" $STD unzip crafty-4-v${RELEASE}.zip @@ -53,12 +46,11 @@ cp -a crafty-4-v${RELEASE}/. /opt/crafty-controller/crafty/crafty-4/ rm -rf crafty-4-v${RELEASE} cd /opt/crafty-controller/crafty -python3 -m venv .venv +$STD uv venv /opt/crafty-controller/crafty/.venv chown -R crafty:crafty /opt/crafty-controller/ $STD sudo -u crafty bash -c ' - source /opt/crafty-controller/crafty/.venv/bin/activate cd /opt/crafty-controller/crafty/crafty-4 - pip3 install --no-cache-dir -r requirements.txt + uv pip install --no-cache-dir -r requirements.txt ' msg_ok "Installed Craft-Controller and dependencies" @@ -83,8 +75,8 @@ $STD systemctl enable -q --now crafty-controller sleep 10 { echo "Crafty-Controller-Credentials" - echo "Username: $(grep -oP '(?<="username": ")[^"]*' /opt/crafty-controller/crafty/crafty-4/app/config/default-creds.txt)" - echo "Password: $(grep -oP '(?<="password": ")[^"]*' /opt/crafty-controller/crafty/crafty-4/app/config/default-creds.txt)" + echo "Username: $(grep -oP '(?<="username": \")[^\"]*' /opt/crafty-controller/crafty/crafty-4/app/config/default-creds.txt)" + echo "Password: $(grep -oP '(?<="password": \")[^\"]*' /opt/crafty-controller/crafty/crafty-4/app/config/default-creds.txt)" } >>~/crafty-controller.creds msg_ok "Crafty-Controller service started" diff --git a/install/deluge-install.sh b/install/deluge-install.sh index f8ebab68154..c75f34202ac 100644 --- a/install/deluge-install.sh +++ b/install/deluge-install.sh @@ -14,24 +14,23 @@ network_check update_os msg_info "Installing Dependencies" -$STD apt-get install -y python3-libtorrent +$STD apt-get install -y python3-libtorrent build-essential msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-dev \ - python3-pip -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" +PYTHON_VERSION="3.12" setup_uv msg_info "Installing Deluge" -$STD pip install deluge[all] +mkdir -p /opt/deluge +cd /opt/deluge +$STD uv venv /opt/deluge/.venv +$STD /opt/prometheus-pve-exporter/.venv/bin/python -m ensurepip --upgrade +$STD /opt/prometheus-pve-exporter/.venv/bin/python -m pip install --upgrade pip +$STD /opt/prometheus-pve-exporter/.venv/bin/python -m pip install deluge libtorrent msg_ok "Installed Deluge" msg_info "Creating Service" -service_path="/etc/systemd/system/deluged.service" -echo "[Unit] +cat </etc/systemd/system/deluged.service +[Unit] Description=Deluge Bittorrent Client Daemon Documentation=man:deluged After=network-online.target @@ -39,15 +38,16 @@ After=network-online.target [Service] Type=simple UMask=007 -ExecStart=/usr/local/bin/deluged -d +ExecStart=/opt/deluge/.venv/bin/deluged -d Restart=on-failure TimeoutStopSec=300 [Install] -WantedBy=multi-user.target" >$service_path +WantedBy=multi-user.target +EOF -service_path="/etc/systemd/system/deluge-web.service" -echo "[Unit] +cat </etc/systemd/system/deluge-web.service +[Unit] Description=Deluge Bittorrent Client Web Interface Documentation=man:deluge-web After=deluged.service @@ -56,11 +56,13 @@ Wants=deluged.service [Service] Type=simple UMask=027 -ExecStart=/usr/local/bin/deluge-web -d +ExecStart=/opt/deluge/.venv/bin/deluge-web -d Restart=on-failure [Install] -WantedBy=multi-user.target" >$service_path +WantedBy=multi-user.target +EOF + systemctl enable --now -q deluged.service systemctl enable --now -q deluge-web.service msg_ok "Created Service" diff --git a/install/documenso-install.sh b/install/documenso-install.sh index 861f3f40e30..a16ad88ad16 100644 --- a/install/documenso-install.sh +++ b/install/documenso-install.sh @@ -23,13 +23,12 @@ $STD apt-get install -y \ libc6 \ make \ cmake \ - jq \ - python3 \ - python3-bcrypt + jq msg_ok "Installed Dependencies" NODE_VERSION="22" NODE_MODULE="turbo@1.9.3" install_node_and_modules PG_VERSION="16" install_postgresql +PYTHON_VERSION="3.12" setup_uv msg_info "Setting up PostgreSQL" DB_NAME="documenso_db" @@ -55,6 +54,10 @@ curl -fsSL "https://github.com/documenso/documenso/archive/refs/tags/v${RELEASE} $STD unzip v${RELEASE}.zip mv documenso-${RELEASE} /opt/documenso cd /opt/documenso +$STD uv venv /opt/documenso/.venv +$STD /opt/documenso/.venv/bin/python -m ensurepip --upgrade +$STD /opt/documenso/.venv/bin/python -m pip install --upgrade pip +$STD /opt/documenso/.venv/bin/python -m pip install bcrypt mv .env.example /opt/documenso/.env sed -i \ -e "s|^NEXTAUTH_SECRET=.*|NEXTAUTH_SECRET='$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-32)'|" \ @@ -78,7 +81,7 @@ echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt" msg_ok "Installed Documenso" msg_info "Create User" -PASSWORD_HASH=$(python3 -c "import bcrypt; print(bcrypt.hashpw(b'helper-scripts', bcrypt.gensalt(rounds=12)).decode())") +PASSWORD_HASH=$(/opt/documenso/.venv/bin/python3 -c "import bcrypt; print(bcrypt.hashpw(b'helper-scripts', bcrypt.gensalt(rounds=12)).decode())") $STD sudo -u postgres psql -d documenso_db -c "INSERT INTO \"User\" (name, email, \"emailVerified\", password, \"identityProvider\", roles, \"createdAt\", \"lastSignedIn\", \"updatedAt\", \"customerId\") VALUES ('helper-scripts', 'helper-scripts@local.com', '2025-01-20 17:14:45.058', '$PASSWORD_HASH', 'DOCUMENSO', ARRAY['USER', 'ADMIN']::\"Role\"[], '2025-01-20 16:04:05.543', '2025-01-20 16:14:55.249', '2025-01-20 16:14:55.25', NULL) RETURNING id;" $STD npm run prisma:migrate-deploy msg_ok "User created" diff --git a/install/esphome-install.sh b/install/esphome-install.sh index 37e2d71d095..8e8e022c548 100644 --- a/install/esphome-install.sh +++ b/install/esphome-install.sh @@ -17,34 +17,34 @@ msg_info "Installing Dependencies" $STD apt-get install -y git msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-dev \ - python3-pip \ - python3-venv -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" - -msg_info "Installing ESPHome" -mkdir /root/config -$STD pip install esphome tornado esptool -msg_ok "Installed ESPHome" +PYTHON_VERSION="3.12" setup_uv + +msg_info "Setting up Virtual Environment" +mkdir -p /opt/esphome +mkdir -p /root/config +cd /opt/esphome +$STD uv venv /opt/esphome/.venv +$STD /opt/esphome/.venv/bin/python -m ensurepip --upgrade +$STD /opt/esphome/.venv/bin/python -m pip install --upgrade pip +$STD /opt/esphome/.venv/bin/python -m pip install esphome tornado esptool +msg_ok "Setup and Installed ESPHome" msg_info "Creating Service" +mkdir -p /root/config cat </etc/systemd/system/esphomeDashboard.service [Unit] Description=ESPHome Dashboard After=network.target [Service] -ExecStart=/usr/local/bin/esphome dashboard /root/config/ +ExecStart=/opt/esphome/.venv/bin/esphome dashboard /root/config/ Restart=always User=root [Install] WantedBy=multi-user.target EOF + systemctl enable -q --now esphomeDashboard msg_ok "Created Service" diff --git a/install/grist-install.sh b/install/grist-install.sh index 9649accf4c7..ab805d08c70 100644 --- a/install/grist-install.sh +++ b/install/grist-install.sh @@ -14,12 +14,10 @@ network_check update_os msg_info "Installing Dependencies" -$STD apt-get install -y \ - make \ - ca-certificates \ - python3.11-venv +$STD apt-get install -y make ca-certificates msg_ok "Installed Dependencies" +PYTHON_VERSION="3.12" setup_uv NODE_VERSION="22" NODE_MODULE="yarn@latest" install_node_and_modules msg_info "Installing Grist" @@ -28,20 +26,24 @@ export CYPRESS_INSTALL_BINARY=0 export NODE_OPTIONS="--max-old-space-size=2048" cd /opt curl -fsSL "https://github.com/gristlabs/grist-core/archive/refs/tags/v${RELEASE}.zip" -o "v${RELEASE}.zip" -$STD unzip v$RELEASE.zip -mv grist-core-${RELEASE} grist -cd grist +$STD unzip "v${RELEASE}.zip" +mv "grist-core-${RELEASE}" /opt/grist +cd /opt/grist +$STD uv venv /opt/grist/sandbox_venv3 +$STD /opt/grist/sandbox_venv3/bin/python -m ensurepip --upgrade +$STD /opt/grist/sandbox_venv3/bin/python -m pip install --upgrade pip +$STD /opt/grist/sandbox_venv3/bin/python -m pip install -r sandbox/requirements.txt $STD yarn install $STD yarn run build:prod -$STD yarn run install:python +ln -sf /opt/grist/sandbox_venv3/bin/python3 /opt/grist/sandbox_venv3/bin/python cat </opt/grist/.env NODE_ENV=production GRIST_HOST=0.0.0.0 EOF -echo "${RELEASE}" >/opt/${APPLICATION}_version.txt +echo "${RELEASE}" >/opt/grist_version.txt msg_ok "Installed Grist" -msg_info "Create Service" +msg_info "Creating Service" cat </etc/systemd/system/grist.service [Unit] Description=Grist @@ -49,9 +51,10 @@ After=network.target [Service] Type=exec -WorkingDirectory=/opt/grist +WorkingDirectory=/opt/grist ExecStart=/usr/bin/yarn run start:prod EnvironmentFile=-/opt/grist/.env +Restart=always [Install] WantedBy=multi-user.target @@ -64,7 +67,7 @@ motd_ssh customize msg_info "Cleaning up" -rm -rf /opt/v${RELEASE}.zip +rm -rf "/opt/v${RELEASE}.zip" $STD apt-get -y autoremove $STD apt-get -y autoclean msg_ok "Cleaned" diff --git a/install/homeassistant-install.sh b/install/homeassistant-install.sh index e041e72fcb4..6111c033d08 100644 --- a/install/homeassistant-install.sh +++ b/install/homeassistant-install.sh @@ -13,19 +13,6 @@ setting_up_container network_check update_os -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-dev \ - python3-pip \ - python3-venv -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" - -msg_info "Installing runlike" -$STD pip install runlike -msg_ok "Installed runlike" - get_latest_release() { curl -fsSL https://api.github.com/repos/$1/releases/latest | grep '"tag_name":' | cut -d'"' -f4 } @@ -36,8 +23,8 @@ PORTAINER_LATEST_VERSION=$(get_latest_release "portainer/portainer") msg_info "Installing Docker $DOCKER_LATEST_VERSION" DOCKER_CONFIG_PATH='/etc/docker/daemon.json' -mkdir -p $(dirname $DOCKER_CONFIG_PATH) -echo -e '{\n "log-driver": "journald"\n}' >/etc/docker/daemon.json +mkdir -p $(dirname "$DOCKER_CONFIG_PATH") +echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH" $STD sh <(curl -fsSL https://get.docker.com) msg_ok "Installed Docker $DOCKER_LATEST_VERSION" diff --git a/install/homer-install.sh b/install/homer-install.sh index 525dd3a4f38..3c0b6ab0750 100644 --- a/install/homer-install.sh +++ b/install/homer-install.sh @@ -13,12 +13,11 @@ setting_up_container network_check update_os -msg_info "Installing Dependencies" -$STD apt-get install -y pip -msg_ok "Installed Dependencies" +PYTHON_VERSION="3.12" setup_uv msg_info "Installing Homer" mkdir -p /opt/homer +$STD uv venv /opt/homer/.venv cd /opt/homer curl -fsSL "https://github.com/bastienwirtz/homer/releases/latest/download/homer.zip" -o "homer.zip" $STD unzip homer.zip @@ -34,7 +33,7 @@ After=network-online.target [Service] Type=simple WorkingDirectory=/opt/homer -ExecStart=python3 -m http.server 8010 +ExecStart=/opt/homer/.venv/bin/python3 -m http.server 8010 [Install] WantedBy=multi-user.target EOF diff --git a/install/immich-install.sh b/install/immich-install.sh index ae766de0527..2ccee7f0c69 100644 --- a/install/immich-install.sh +++ b/install/immich-install.sh @@ -13,6 +13,8 @@ setting_up_container network_check update_os +setup_uv + msg_info "Configuring apt and installing dependencies" echo "deb http://deb.debian.org/debian testing main contrib" >/etc/apt/sources.list.d/immich.list cat </etc/apt/preferences.d/immich @@ -27,7 +29,6 @@ $STD apt-get install --no-install-recommends -y \ redis \ autoconf \ build-essential \ - python3-venv \ python3-dev \ cmake \ jq \ @@ -304,25 +305,19 @@ cp LICENSE "$APP_DIR" msg_ok "Installed Immich Web Components" cd "$SRC_DIR"/machine-learning -$STD python3 -m venv "$ML_DIR/ml-venv" +export VIRTUAL_ENV="${ML_DIR}/ml-venv" +$STD uv venv "$VIRTUAL_ENV" if [[ -f ~/.openvino ]]; then msg_info "Installing HW-accelerated machine-learning" - ( - source "$ML_DIR"/ml-venv/bin/activate - $STD pip3 install uv - uv -q sync --extra openvino --no-cache --active - ) - patchelf --clear-execstack "$ML_DIR"/ml-venv/lib/python3.11/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-311-x86_64-linux-gnu.so + uv -q sync --no-cache --extra openvino --active + patchelf --clear-execstack "${VIRTUAL_ENV}/lib/python3.11/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-311-x86_64-linux-gnu.so" msg_ok "Installed HW-accelerated machine-learning" else msg_info "Installing machine-learning" - ( - source "$ML_DIR"/ml-venv/bin/activate - $STD pip3 install uv - uv -q sync --extra cpu --no-cache --active - ) + uv -q sync --no-cache --extra cpu --active msg_ok "Installed machine-learning" fi + cd "$SRC_DIR" cp -a machine-learning/{ann,immich_ml} "$ML_DIR" if [[ -f ~/.openvino ]]; then @@ -396,7 +391,7 @@ set -a . ${INSTALL_DIR}/.env set +a -python -m immich_ml +python3 -m immich_ml EOF chmod +x "$ML_DIR"/ml_start.sh cat </etc/systemd/system/"${APPLICATION}"-web.service diff --git a/install/jupyternotebook-install.sh b/install/jupyternotebook-install.sh index 843921187ac..4b8229d7cb6 100644 --- a/install/jupyternotebook-install.sh +++ b/install/jupyternotebook-install.sh @@ -13,15 +13,16 @@ setting_up_container network_check update_os -msg_info "Installing Dependencies" -$STD apt-get install -y \ - python3 \ - python3-pip -msg_ok "Installed Dependencies" +PYTHON_VERSION="3.12" setup_uv -msg_info "Setting up Jupyter Notebook" -$STD pip3 install jupyter -msg_ok "Setup Jupyter Notebook" +msg_info "Installing Jupyter" +mkdir -p /opt/jupyter +cd /opt/jupyter +$STD uv venv /opt/jupyter/.venv +$STD /opt/jupyter/.venv/bin/python -m ensurepip --upgrade +$STD /opt/jupyter/.venv/bin/python -m pip install --upgrade pip +$STD /opt/jupyter/.venv/bin/python -m pip install jupyter +msg_ok "Installed Jupyter" msg_info "Creating Service" cat </etc/systemd/system/jupyternotebook.service @@ -31,7 +32,8 @@ After=network.target [Service] Type=simple -ExecStart=jupyter notebook --ip=0.0.0.0 --port=8888 --allow-root +WorkingDirectory=/opt/jupyter +ExecStart=/opt/jupyter/.venv/bin/jupyter notebook --ip=0.0.0.0 --port=8888 --allow-root Restart=always RestartSec=10 @@ -39,6 +41,7 @@ RestartSec=10 WantedBy=multi-user.target EOF systemctl enable -q --now jupyternotebook +msg_ok "Created Service" motd_ssh customize diff --git a/install/kometa-install.sh b/install/kometa-install.sh index 8c9634188eb..64b79e4ebe1 100644 --- a/install/kometa-install.sh +++ b/install/kometa-install.sh @@ -13,28 +13,28 @@ setting_up_container network_check update_os -msg_info "Setup Python 3" -$STD apt-get install python3-pip -y -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python 3" +PYTHON_VERSION="3.12" setup_uv -msg_info "Setup Kometa" -temp_file=$(mktemp) +msg_info "Installing Kometa" +tmp_file=$(mktemp) RELEASE=$(curl -fsSL https://api.github.com/repos/Kometa-Team/Kometa/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') -curl -fsSL "https://github.com/Kometa-Team/Kometa/archive/refs/tags/v${RELEASE}.tar.gz" -o """$temp_file""" -tar -xzf "$temp_file" -mv Kometa-"${RELEASE}" /opt/kometa +curl -fsSL "https://github.com/Kometa-Team/Kometa/archive/refs/tags/v${RELEASE}.tar.gz" -o "$tmp_file" +tar -xzf "$tmp_file" +mv "Kometa-${RELEASE}" /opt/kometa cd /opt/kometa -$STD pip install -r requirements.txt --ignore-installed +$STD uv venv /home/wger/.venv +$STD /opt/kometa/.venv/bin/python -m ensurepip --upgrade +$STD /opt/kometa/.venv/bin/python -m pip install --upgrade pip +$STD /opt/kometa/.venv/bin/python -m pip install -r requirements.txt mkdir -p config/assets cp config/config.yml.template config/config.yml -echo "${RELEASE}" >/opt/kometa_version.txt -msg_ok "Setup Kometa" +echo "$RELEASE" >/opt/kometa_version.txt +msg_ok "Installed Kometa" -read -p "${TAB3}nter your TMDb API key: " TMDBKEY +read -p "${TAB3}Enter your TMDb API key: " TMDBKEY read -p "${TAB3}Enter your Plex URL: " PLEXURL read -p "${TAB3}Enter your Plex token: " PLEXTOKEN -sed -i -e "s#url: http://192.168.1.12:32400#url: $PLEXURL #g" /opt/kometa/config/config.yml +sed -i -e "s#url: http://192.168.1.12:32400#url: $PLEXURL#g" /opt/kometa/config/config.yml sed -i -e "s/token: ####################/token: $PLEXTOKEN/g" /opt/kometa/config/config.yml sed -i -e "s/apikey: ################################/apikey: $TMDBKEY/g" /opt/kometa/config/config.yml @@ -47,21 +47,21 @@ After=network-online.target [Service] Type=simple WorkingDirectory=/opt/kometa -ExecStart=/usr/bin/python3 kometa.py +ExecStart=/opt/kometa/.venv/bin/python kometa.py Restart=always RestartSec=30 [Install] WantedBy=multi-user.target EOF -systemctl enable --now -q kometa +systemctl enable -q --now kometa msg_ok "Created Service" motd_ssh customize msg_info "Cleaning up" -rm -f "$temp_file" +rm -f "$tmp_file" $STD apt-get -y autoremove $STD apt-get -y autoclean msg_ok "Cleaned" diff --git a/install/lazylibrarian-install.sh b/install/lazylibrarian-install.sh index 7749ae6bc38..49fe2e89d42 100644 --- a/install/lazylibrarian-install.sh +++ b/install/lazylibrarian-install.sh @@ -14,29 +14,24 @@ setting_up_container network_check update_os +PYTHON_VERSION="3.12" setup_uv + msg_info "Installing Dependencies" $STD apt-get install -y \ - git \ - libpng-dev \ - libjpeg-dev \ - libtiff-dev \ - imagemagick + git \ + libpng-dev \ + libjpeg-dev \ + libtiff-dev \ + imagemagick msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y \ - pip \ - python3-irc -$STD pip install jaraco.stream -$STD pip install python-Levenshtein -$STD pip install soupsieve -$STD pip install pypdf -msg_ok "Setup Python3" - msg_info "Installing LazyLibrarian" $STD git clone https://gitlab.com/LazyLibrarian/LazyLibrarian /opt/LazyLibrarian cd /opt/LazyLibrarian -$STD pip install . +$STD uv venv /opt/LazyLibrarian/.venv +$STD /opt/LazyLibrarian/.venv/bin/python -m ensurepip --upgrade +$STD /opt/LazyLibrarian/.venv/bin/python -m pip install --upgrade pip +$STD /opt/LazyLibrarian/.venv/bin/python -m pip install . jaraco.stream python-Levenshtein soupsieve pypdf msg_ok "Installed LazyLibrarian" msg_info "Creating Service" @@ -44,17 +39,20 @@ cat </etc/systemd/system/lazylibrarian.service [Unit] Description=LazyLibrarian Daemon After=syslog.target network.target + [Service] -UMask=0002 Type=simple -ExecStart=/usr/bin/python3 /opt/LazyLibrarian/LazyLibrarian.py +WorkingDirectory=/opt/LazyLibrarian +ExecStart=/opt/LazyLibrarian/.venv/bin/python LazyLibrarian.py +UMask=0002 +Restart=on-failure TimeoutStopSec=20 KillMode=process -Restart=on-failure + [Install] WantedBy=multi-user.target EOF -systemctl enable --now -q lazylibrarian +systemctl enable -q --now lazylibrarian msg_ok "Created Service" motd_ssh diff --git a/install/medusa-install.sh b/install/medusa-install.sh index e46ececb7d2..e8eeacb41b9 100644 --- a/install/medusa-install.sh +++ b/install/medusa-install.sh @@ -14,6 +14,8 @@ setting_up_container network_check update_os +PYTHON_VERSION="3.12" setup_uv + msg_info "Installing Dependencies" $STD apt-get install -y \ git-core \ @@ -29,6 +31,11 @@ msg_ok "Installed Dependencies" msg_info "Installing Medusa" $STD git clone https://github.com/pymedusa/Medusa.git /opt/medusa +cd /opt/medusa +$STD uv venv /opt/medusa/.venv +$STD /opt/LazyLibrarian/.venv/bin/python -m ensurepip --upgrade +$STD /opt/LazyLibrarian/.venv/bin/python -m pip install --upgrade pip +$STD /opt/LazyLibrarian/.venv/bin/python -m pip install . msg_ok "Installed Medusa" msg_info "Creating Service" @@ -39,7 +46,8 @@ After=network.target [Service] Type=simple -ExecStart=/usr/bin/python3 /opt/medusa/start.py -q --nolaunch --datadir=/opt/medusa +WorkingDirectory=/opt/medusa +ExecStart=/opt/medusa/.venv/bin/python start.py -q --nolaunch --datadir=/opt/medusa TimeoutStopSec=25 KillMode=process Restart=on-failure diff --git a/install/metube-install.sh b/install/metube-install.sh index 34910d44914..207a7c69697 100644 --- a/install/metube-install.sh +++ b/install/metube-install.sh @@ -1,8 +1,7 @@ #!/usr/bin/env bash # Copyright (c) 2021-2025 tteck -# Author: tteck -# Co-Author: MickLesk (Canbiz) +# Author: MickLesk (Canbiz) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # Source: https://github.com/alexta69/metube @@ -28,14 +27,7 @@ $STD apt-get install -y --no-install-recommends \ ca-certificates msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-dev \ - python3-pip \ - python3-venv -msg_ok "Setup Python3" - +PYTHON_VERSION="3.13" setup_uv NODE_VERSION="22" install_node_and_modules msg_info "Installing MeTube" @@ -44,8 +36,12 @@ cd /opt/metube/ui $STD npm install $STD node_modules/.bin/ng build cd /opt/metube -$STD pip3 install pipenv -$STD pipenv install +$STD uv venv /opt/metube/.venv +$STD /opt/metube/.venv/bin/python -m ensurepip --upgrade +$STD /opt/metube/.venv/bin/python -m pip install --upgrade pip +$STD /opt/metube/.venv/bin/python -m pip install pipenv +$STD /opt/metube/.venv/bin/pipenv install + mkdir -p /opt/metube_downloads /opt/metube_downloads/.metube /opt/metube_downloads/music /opt/metube_downloads/videos cat </opt/metube/.env DOWNLOAD_DIR=/opt/metube_downloads @@ -65,7 +61,7 @@ After=network.target Type=simple WorkingDirectory=/opt/metube EnvironmentFile=/opt/metube/.env -ExecStart=/usr/local/bin/pipenv run python3 app/main.py +ExecStart=/opt/metube/.venv/bin/pipenv run python3 app/main.py Restart=always User=root diff --git a/install/motioneye-install.sh b/install/motioneye-install.sh index 47b6f8ff7bb..8f58c21409c 100644 --- a/install/motioneye-install.sh +++ b/install/motioneye-install.sh @@ -18,13 +18,7 @@ $STD apt-get install -y git $STD apt-get install -y cifs-utils msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-dev \ - python3-pip -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" +PYTHON_VERSION="3.12" setup_uv msg_info "Installing Motion" $STD apt-get install -y motion @@ -38,7 +32,11 @@ msg_ok "Installed FFmpeg" msg_info "Installing MotionEye" $STD apt-get update -$STD pip install git+https://github.com/motioneye-project/motioneye.git@dev +$STD uv venv /opt/motioneye/.venv +$STD /opt/motioneye/.venv/bin/python -m ensurepip --upgrade +$STD /opt/motioneye/.venv/bin/python -m pip install --upgrade pip +$STD /opt/motioneye/.venv/bin/python -m pip install --pre motioneye + mkdir -p /etc/motioneye chown -R root:root /etc/motioneye chmod -R 777 /etc/motioneye @@ -48,6 +46,8 @@ msg_ok "Installed MotionEye" msg_info "Creating Service" curl -fsSL "https://raw.githubusercontent.com/motioneye-project/motioneye/dev/motioneye/extra/motioneye.systemd" -o "/etc/systemd/system/motioneye.service" +sed -i 's|^ExecStart=.*|ExecStart=/opt/motioneye/.venv/bin/meyectl startserver -c /etc/motioneye/motioneye.conf|' /etc/systemd/system/motioneye.service +systemctl daemon-reexec systemctl enable -q --now motioneye msg_ok "Created Service" diff --git a/install/mylar3-install.sh b/install/mylar3-install.sh index cab578fbb2f..c5327afd069 100644 --- a/install/mylar3-install.sh +++ b/install/mylar3-install.sh @@ -21,18 +21,18 @@ $STD apt-get install -y unrar rm /etc/apt/sources.list.d/non-free.list msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y python3-pip -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -$STD pip install -U --no-cache-dir pip -msg_ok "Setup Python3" +PYTHON_VERSION="3.12" setup_uv msg_info "Installing ${APPLICATION}" mkdir -p /opt/mylar3 mkdir -p /opt/mylar3-data RELEASE=$(curl -fsSL https://api.github.com/repos/mylar3/mylar3/releases/latest | jq -r '.tag_name') curl -fsSL "https://github.com/mylar3/mylar3/archive/refs/tags/${RELEASE}.tar.gz" | tar -xz --strip-components=1 -C /opt/mylar3 -$STD pip install --no-cache-dir -r /opt/mylar3/requirements.txt +cd /opt/mylar3 +$STD uv venv /opt/mylar3/.venv +$STD /opt/mylar3/.venv/bin/python -m ensurepip --upgrade +$STD /opt/mylar3/.venv/bin/python -m pip install --upgrade pip +$STD /opt/mylar3/.venv/bin/python -m pip install -r requirements.txt echo "${RELEASE}" >/opt/${APPLICATION}_version.txt msg_ok "Installed ${APPLICATION}" @@ -43,7 +43,7 @@ Description=Mylar3 Service After=network-online.target [Service] -ExecStart=/usr/bin/python3 /opt/mylar3/Mylar.py --daemon --nolaunch --datadir=/opt/mylar3-data +ExecStart=/opt/mylar3/.venv/bin/python /opt/mylar3/Mylar.py --daemon --nolaunch --datadir=/opt/mylar3-data GuessMainPID=no Type=forking Restart=on-failure diff --git a/install/netbox-install.sh b/install/netbox-install.sh index 6a3499c4cbb..8d50a58f4e0 100644 --- a/install/netbox-install.sh +++ b/install/netbox-install.sh @@ -27,14 +27,7 @@ $STD apt-get install -y \ msg_ok "Installed Dependencies" PG_VERSION="16" install_postgresql - -msg_info "Installing Python" -$STD apt-get install -y \ - python3 \ - python3-pip \ - python3-venv \ - python3-dev -msg_ok "Installed Python" +PYTHON_VERSION="3.12" setup_uv msg_info "Setting up PostgreSQL" DB_NAME=netbox @@ -63,8 +56,11 @@ chown --recursive netbox /opt/netbox/netbox/reports/ chown --recursive netbox /opt/netbox/netbox/scripts/ mv /opt/netbox/netbox/netbox/configuration_example.py /opt/netbox/netbox/netbox/configuration.py +$STD uv venv /opt/netbox/.venv +$STD /opt/netbox/.venv/bin/python -m ensurepip --upgrade +$STD /opt/netbox/.venv/bin/python -m pip install --upgrade pip -SECRET_KEY=$(python3 /opt/netbox/netbox/generate_secret_key.py) +SECRET_KEY=$(/opt/netbox/.venv/bin/python /opt/netbox/netbox/generate_secret_key.py) ESCAPED_SECRET_KEY=$(printf '%s\n' "$SECRET_KEY" | sed 's/[&/\]/\\&/g') sed -i 's/ALLOWED_HOSTS = \[\]/ALLOWED_HOSTS = ["*"]/' /opt/netbox/netbox/netbox/configuration.py @@ -95,7 +91,7 @@ DJANGO_USER=Admin DJANGO_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13) source /opt/netbox/venv/bin/activate -$STD python3 /opt/netbox/netbox/manage.py shell </etc/apt/sources.list.d/openresty.list +curl -fsSL https://openresty.org/package/pubkey.gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/openresty.gpg +echo "deb http://openresty.org/package/debian $VERSION openresty" >/etc/apt/sources.list.d/openresty.list $STD apt-get update -$STD apt-get -y install openresty -msg_ok "Installed Openresty" - -msg_info "Installing Node.js" -$STD bash <(curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh) -source ~/.bashrc -$STD nvm install 16.20.2 -ln -sf /root/.nvm/versions/node/v16.20.2/bin/node /usr/bin/node -msg_ok "Installed Node.js" - -msg_info "Installing pnpm" -$STD npm install -g pnpm@8.15 -msg_ok "Installed pnpm" - -RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest | - grep "tag_name" | - awk '{print substr($2, 3, length($2)-4) }') - -read -r -p "${TAB3}Would you like to install an older version (v2.10.4)? " prompt -if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then - msg_info "Downloading Nginx Proxy Manager v2.10.4" - curl -fsSL "https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v2.10.4" | tar -xz - cd ./nginx-proxy-manager-2.10.4 - msg_ok "Downloaded Nginx Proxy Manager v2.10.4" -else - msg_info "Downloading Nginx Proxy Manager v${RELEASE}" - curl -fsSL "https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE}" | tar -xz - cd ./nginx-proxy-manager-"${RELEASE}" - msg_ok "Downloaded Nginx Proxy Manager v${RELEASE}" -fi -msg_info "Setting up Environment" -ln -sf /usr/bin/python3 /usr/bin/python -ln -sf /usr/bin/certbot /opt/certbot/bin/certbot +$STD apt-get install -y openresty ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx -ln -sf /usr/local/openresty/nginx/ /etc/nginx -if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then - sed -i "s|\"version\": \"0.0.0\"|\"version\": \"2.10.4\"|" backend/package.json - sed -i "s|\"version\": \"0.0.0\"|\"version\": \"2.10.4\"|" frontend/package.json -else - sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" backend/package.json - sed -i "s|\"version\": \"0.0.0\"|\"version\": \"$RELEASE\"|" frontend/package.json -fi -sed -i 's|"fork-me": ".*"|"fork-me": "Proxmox VE Helper-Scripts"|' frontend/js/i18n/messages.json -sed -i "s|https://github.com.*source=nginx-proxy-manager|https://helper-scripts.com|g" frontend/js/app/ui/footer/main.ejs -sed -i 's+^daemon+#daemon+g' docker/rootfs/etc/nginx/nginx.conf -NGINX_CONFS=$(find "$(pwd)" -type f -name "*.conf") -for NGINX_CONF in $NGINX_CONFS; do - sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF" -done +ln -sf /usr/local/openresty/nginx /etc/nginx +msg_ok "Installed OpenResty" + +RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest | grep "tag_name" | awk -F'"' '{print $4}') +msg_info "Downloading Nginx Proxy Manager v${RELEASE}" +curl -fsSL "https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/refs/tags/v${RELEASE}" | tar -xz +cd ./nginx-proxy-manager-${RELEASE} +msg_ok "Downloaded Nginx Proxy Manager" + +msg_info "Setting up Nginx Proxy Manager" +sed -i "s|\"version\": \"0.0.0\"|\"version\": \"${RELEASE}\"|" backend/package.json frontend/package.json +sed -i 's|^daemon|#daemon|' docker/rootfs/etc/nginx/nginx.conf +find . -type f -name "*.conf" -exec sed -i 's|include conf.d|include /etc/nginx/conf.d|g' {} \; mkdir -p /var/www/html /etc/nginx/logs cp -r docker/rootfs/var/www/html/* /var/www/html/ @@ -100,7 +60,9 @@ cp docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini cp docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf rm -f /etc/nginx/conf.d/dev.conf +msg_ok "Set up Nginx Proxy Manager" +msg_info "Preparing Runtime Environment" mkdir -p /tmp/nginx/body \ /run/nginx \ /data/nginx \ @@ -120,31 +82,29 @@ mkdir -p /tmp/nginx/body \ chmod -R 777 /var/cache/nginx chown root /tmp/nginx - echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf - if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then - openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem &>/dev/null + openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \ + -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" \ + -keyout /data/nginx/dummykey.pem \ + -out /data/nginx/dummycert.pem &>/dev/null fi - -mkdir -p /app/global /app/frontend/images -cp -r backend/* /app -cp -r global/* /app/global -msg_ok "Set up Environment" +msg_ok "Prepared Runtime Environment" msg_info "Building Frontend" cd ./frontend -$STD pnpm install -$STD pnpm upgrade -$STD pnpm run build +$STD yarn install --frozen-lockfile +$STD yarn upgrade +$STD yarn run build cp -r dist/* /app/frontend cp -r app-images/* /app/frontend/images msg_ok "Built Frontend" msg_info "Initializing Backend" +cd ../backend rm -rf /app/config/default.json -if [ ! -f /app/config/production.json ]; then - cat <<'EOF' >/app/config/production.json +mkdir -p /app/config +cat </app/config/production.json { "database": { "engine": "knex-native", @@ -157,13 +117,16 @@ if [ ! -f /app/config/production.json ]; then } } EOF -fi +cd .. +mkdir -p /app/global /app/frontend/images +cp -r backend/* /app +cp -r global/* /app/global cd /app -$STD pnpm install +$STD yarn install --frozen-lockfile msg_ok "Initialized Backend" -msg_info "Creating Service" -cat <<'EOF' >/lib/systemd/system/npm.service +msg_info "Creating Systemd Service" +cat </etc/systemd/system/npm.service [Unit] Description=Nginx Proxy Manager After=network.target @@ -180,22 +143,21 @@ Restart=on-failure [Install] WantedBy=multi-user.target EOF -msg_ok "Created Service" +msg_ok "Created Systemd Service" motd_ssh customize msg_info "Starting Services" -sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf -sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager -sed -i 's/include-system-site-packages = false/include-system-site-packages = true/g' /opt/certbot/pyvenv.cfg +sed -i 's/user npm/user root/g; s/^pid/#pid/' /usr/local/openresty/nginx/conf/nginx.conf +sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/' /etc/logrotate.d/nginx-proxy-manager +sed -i 's/include-system-site-packages = false/include-system-site-packages = true/' /opt/certbot/.venv/pyvenv.cfg systemctl enable -q --now openresty systemctl enable -q --now npm msg_ok "Started Services" -msg_info "Cleaning up" +msg_info "Cleaning Up" rm -rf ../nginx-proxy-manager-* -systemctl restart openresty $STD apt-get -y autoremove $STD apt-get -y autoclean msg_ok "Cleaned" diff --git a/install/octoprint-install.sh b/install/octoprint-install.sh index a4924ce195a..b887910051a 100644 --- a/install/octoprint-install.sh +++ b/install/octoprint-install.sh @@ -19,15 +19,7 @@ $STD apt-get install -y git \ build-essential msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-dev \ - python3-pip \ - python3-venv \ - python3-setuptools -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" +PYTHON_VERSION="3.12" setup_uv msg_info "Creating user octoprint" useradd -m -s /bin/bash -p $(openssl passwd -1 octoprint) octoprint @@ -40,11 +32,9 @@ msg_info "Installing OctoPrint" $STD sudo -u octoprint bash </opt/open-webui/.env diff --git a/install/paperless-ai-install.sh b/install/paperless-ai-install.sh index f4972ef4665..4520b3ef863 100644 --- a/install/paperless-ai-install.sh +++ b/install/paperless-ai-install.sh @@ -18,12 +18,9 @@ $STD apt-get install -y \ build-essential msg_ok "Installed Dependencies" -msg_info "Installing Python3" -$STD apt-get install -y \ - python3-pip -msg_ok "Installed Python3" +PYTHON_VERSION="3.12" setup_uv -install_node_and_modules +NODE_VERSION="22" install_node_and_modules msg_info "Setup Paperless-AI" cd /opt @@ -32,7 +29,8 @@ curl -fsSL "https://github.com/clusterzx/paperless-ai/archive/refs/tags/v${RELEA $STD unzip v${RELEASE}.zip mv paperless-ai-${RELEASE} /opt/paperless-ai cd /opt/paperless-ai -$STD pip install --no-cache-dir -r requirements.txt +$STD uv venv .venv +$STD .venv/bin/uv pip install --no-cache-dir -r requirements.txt mkdir -p data/chromadb $STD npm install mkdir -p /opt/paperless-ai/data @@ -87,7 +85,7 @@ After=network.target [Service] WorkingDirectory=/opt/paperless-ai -ExecStart=/usr/bin/python3 main.py --host 0.0.0.0 --port 8000 --initialize +ExecStart=/opt/paperless-ai/.venv/bin/python main.py --host 0.0.0.0 --port 8000 --initialize Restart=always [Install] diff --git a/install/paperless-ngx-install.sh b/install/paperless-ngx-install.sh index 541aa4b2abf..239e6a7f183 100644 --- a/install/paperless-ngx-install.sh +++ b/install/paperless-ngx-install.sh @@ -35,17 +35,9 @@ $STD apt-get install -y \ libleptonica-dev msg_ok "Installed Dependencies" +PYTHON_VERSION="3.12" setup_uv PG_VERSION="16" install_postgresql -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-pip \ - python3-dev \ - python3-setuptools \ - python3-wheel -msg_ok "Setup Python3" - msg_info "Installing OCR Dependencies (Patience)" $STD apt-get install -y \ unpaper \ @@ -85,8 +77,7 @@ $STD tar -xf "paperless-ngx-$Paperlessngx.tar.xz" -C /opt/ mv paperless-ngx paperless rm "paperless-ngx-$Paperlessngx.tar.xz" cd /opt/paperless -$STD pip install --upgrade pip -$STD pip install -r requirements.txt +$STD uv sync curl -fsSL "https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/paperless.conf.example" -o /opt/paperless/paperless.conf mkdir -p {consume,data,media,static} sed -i -e 's|#PAPERLESS_REDIS=redis://localhost:6379|PAPERLESS_REDIS=redis://localhost:6379|' /opt/paperless/paperless.conf @@ -98,7 +89,7 @@ echo "${Paperlessngx}" >/opt/"${APPLICATION}"_version.txt msg_ok "Installed Paperless-ngx" msg_info "Installing Natural Language Toolkit (Patience)" -$STD python3 -m nltk.downloader -d /usr/share/nltk_data all +$STD /opt/paperless/.venv/bin/python -m nltk.downloader -d /usr/share/nltk_data all msg_ok "Installed Natural Language Toolkit" msg_info "Setting up PostgreSQL database" @@ -122,7 +113,7 @@ sed -i -e "s|#PAPERLESS_DBUSER=paperless|PAPERLESS_DBUSER=$DB_USER|" /opt/paperl sed -i -e "s|#PAPERLESS_DBPASS=paperless|PAPERLESS_DBPASS=$DB_PASS|" /opt/paperless/paperless.conf sed -i -e "s|#PAPERLESS_SECRET_KEY=change-me|PAPERLESS_SECRET_KEY=$SECRET_KEY|" /opt/paperless/paperless.conf cd /opt/paperless/src -$STD python3 manage.py migrate +$STD /opt/paperless/.venv/bin/python manage migrate msg_ok "Set up PostgreSQL database" read -r -p "${TAB3}Would you like to add Adminer? " prompt @@ -144,7 +135,7 @@ fi msg_info "Setting up admin Paperless-ngx User & Password" ## From https://github.com/linuxserver/docker-paperless-ngx/blob/main/root/etc/cont-init.d/99-migrations -cat </dev/null 2>&1 rm -rf /var/lib/ieee-data /var/www/html/index.html +cd /opt/pialert +$STD uv venv /opt/pialert/.venv +$STD /opt/pialert/.venv/bin/python -m ensurepip --upgrade +$STD /opt/pialert/.venv/bin/python -m pip install --upgrade pip +$STD /opt/pialert/.venv/bin/python -m pip install mac-vendor-lookup fritzconnection cryptography pyunifi sed -i -e 's#^sudo cp -n /usr/share/ieee-data/.* /var/lib/ieee-data/#\# &#' -e '/^sudo mkdir -p 2_backup$/s/^/# /' -e '/^sudo cp \*.txt 2_backup$/s/^/# /' -e '/^sudo cp \*.csv 2_backup$/s/^/# /' /opt/pialert/back/update_vendors.sh mv /var/www/html/index.lighttpd.html /var/www/html/index.lighttpd.html.old ln -s /usr/share/ieee-data/ /var/lib/ @@ -75,7 +69,7 @@ done sed -i 's#PIALERT_PATH\s*=\s*'\''/home/pi/pialert'\''#PIALERT_PATH = '\''/opt/pialert'\''#' /opt/pialert/config/pialert.conf sed -i 's/$HOME/\/opt/g' /opt/pialert/install/pialert.cron crontab /opt/pialert/install/pialert.cron -echo "python3 /opt/pialert/back/pialert.py 1" >/usr/bin/scan +echo "/opt/pialert/.venv/bin/python /opt/pialert/back/pialert.py 1" >/usr/bin/scan chmod +x /usr/bin/scan echo "/opt/pialert/back/pialert-cli set_permissions --lxc" >/usr/bin/permissions chmod +x /usr/bin/permissions @@ -84,9 +78,9 @@ chmod +x /usr/bin/sudoers msg_ok "Installed Pi.Alert" msg_info "Start Pi.Alert Scan (Patience)" -$STD python3 /opt/pialert/back/pialert.py update_vendors -$STD python3 /opt/pialert/back/pialert.py internet_IP -$STD python3 /opt/pialert/back/pialert.py 1 +$STD /opt/pialert/.venv/bin/python /opt/pialert/back/pialert.py update_vendors +$STD /opt/pialert/.venv/bin/python /opt/pialert/back/pialert.py internet_IP +$STD /opt/pialert/.venv/bin/python /opt/pialert/back/pialert.py 1 msg_ok "Finished Pi.Alert Scan" motd_ssh diff --git a/install/prometheus-pve-exporter-install.sh b/install/prometheus-pve-exporter-install.sh index b2ccef80dca..513611e5bff 100644 --- a/install/prometheus-pve-exporter-install.sh +++ b/install/prometheus-pve-exporter-install.sh @@ -13,16 +13,16 @@ setting_up_container network_check update_os -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-pip -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" +PYTHON_VERSION="3.12" setup_uv msg_info "Installing Prometheus Proxmox VE Exporter" -python3 -m pip install --default-timeout=300 --quiet --root-user-action=ignore prometheus-pve-exporter mkdir -p /opt/prometheus-pve-exporter +cd /opt/prometheus-pve-exporter + +$STD uv venv /opt/prometheus-pve-exporter/.venv +$STD /opt/prometheus-pve-exporter/.venv/bin/python -m ensurepip --upgrade +$STD /opt/prometheus-pve-exporter/.venv/bin/python -m pip install --upgrade pip +$STD /opt/prometheus-pve-exporter/.venv/bin/python -m pip install prometheus-pve-exporter cat </opt/prometheus-pve-exporter/pve.yml default: user: prometheus@pve @@ -42,7 +42,7 @@ After=syslog.target network.target User=root Restart=always Type=simple -ExecStart=pve_exporter \ +ExecStart=/opt/prometheus-pve-exporter/.venv/bin/pve_exporter \ --config.file=/opt/prometheus-pve-exporter/pve.yml \ --web.listen-address=0.0.0.0:9221 ExecReload=/bin/kill -HUP \$MAINPID diff --git a/install/radicale-install.sh b/install/radicale-install.sh index bed34b116ea..dc143de44f0 100644 --- a/install/radicale-install.sh +++ b/install/radicale-install.sh @@ -15,17 +15,20 @@ update_os msg_info "Installing Dependencies" $STD apt-get install -y \ - apache2-utils \ - python3-pip \ - python3.11-venv + apache2-utils msg_ok "Installed Dependencies" +PYTHON_VERSION="3.12" setup_uv + msg_info "Setting up Radicale" -python3 -m venv /opt/radicale -source /opt/radicale/bin/activate -$STD python3 -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz +mkdir -p /opt/radicale/{users} +cd /opt/radicale +$STD uv venv /opt/radicale/.venv +$STD /opt/radicale/.venv/bin/python -m ensurepip --upgrade +$STD /opt/radicale/.venv/bin/python -m pip install --upgrade pip +$STD /opt/radicale/.venv/bin/python -m pip install --upgrade https://github.com/Kozea/Radicale/archive/master.tar.gz RNDPASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13) -$STD htpasswd -c -b -5 /opt/radicale/users admin $RNDPASS +$STD htpasswd -c -b -5 /opt/radicale/users admin "$RNDPASS" { echo "Radicale Credentials" echo "Admin User: admin" @@ -34,16 +37,15 @@ $STD htpasswd -c -b -5 /opt/radicale/users admin $RNDPASS msg_ok "Done setting up Radicale" msg_info "Setup Service" - cat </opt/radicale/start.sh #!/usr/bin/env bash -source /opt/radicale/bin/activate -python3 -m radicale --storage-filesystem-folder=/var/lib/radicale/collections --hosts 0.0.0.0:5232 --auth-type htpasswd --auth-htpasswd-filename /opt/radicale/users --auth-htpasswd-encryption sha512 +uv run -m radicale --storage-filesystem-folder=/var/lib/radicale/collections --hosts 0.0.0.0:5232 --auth-type htpasswd --auth-htpasswd-filename /opt/radicale/users --auth-htpasswd-encryption sha512 EOF chmod +x /opt/radicale/start.sh cat </etc/systemd/system/radicale.service +[Unit] Description=A simple CalDAV (calendar) and CardDAV (contact) server After=network.target Requires=network.target @@ -51,13 +53,11 @@ Requires=network.target [Service] ExecStart=/opt/radicale/start.sh Restart=on-failure -# User=radicale -# Deny other users access to the calendar data -# UMask=0027 [Install] WantedBy=multi-user.target EOF + systemctl enable -q --now radicale msg_ok "Created Service" diff --git a/install/sabnzbd-install.sh b/install/sabnzbd-install.sh index 49b396689e1..47daebd70d0 100644 --- a/install/sabnzbd-install.sh +++ b/install/sabnzbd-install.sh @@ -15,14 +15,10 @@ update_os msg_info "Installing Dependencies" $STD apt-get install -y \ - par2 \ - p7zip-full + par2 \ + p7zip-full msg_ok "Installed Dependencies" -msg_info "Setup uv" -setup_uv -msg_ok "Setup uv" - msg_info "Setup Unrar" cat </etc/apt/sources.list.d/non-free.list deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware @@ -35,11 +31,11 @@ msg_ok "Setup Unrar" msg_info "Installing SABnzbd" RELEASE=$(curl -fsSL https://api.github.com/repos/sabnzbd/sabnzbd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') mkdir -p /opt/sabnzbd -$STD uv venv /opt/sabnzbd/venv +cd /opt/sabnzbd temp_file=$(mktemp) curl -fsSL "https://github.com/sabnzbd/sabnzbd/releases/download/${RELEASE}/SABnzbd-${RELEASE}-src.tar.gz" -o "$temp_file" tar -xzf "$temp_file" -C /opt/sabnzbd --strip-components=1 -$STD uv pip install -r /opt/sabnzbd/requirements.txt --python=/opt/sabnzbd/venv/bin/python +VENV_FOLDER="/opt/sabnzbd/.venv" REQUIREMENTS_FILE="requirements.txt" PYTHON_VERSION="3.12" setup_uv_venv echo "${RELEASE}" >/opt/${APPLICATION}_version.txt msg_ok "Installed SABnzbd" @@ -51,7 +47,7 @@ After=network.target [Service] WorkingDirectory=/opt/sabnzbd -ExecStart=/opt/sabnzbd/venv/bin/python SABnzbd.py -s 0.0.0.0:7777 +ExecStart=/opt/sabnzbd/.venv/bin/python SABnzbd.py -s 0.0.0.0:7777 Restart=always User=root diff --git a/install/searxng-install.sh b/install/searxng-install.sh index 0d955cb2026..d9875bdef81 100644 --- a/install/searxng-install.sh +++ b/install/searxng-install.sh @@ -22,13 +22,7 @@ $STD apt-get install -y \ git msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-{pip,venv,yaml,dev} -$STD pip install --upgrade pip setuptools wheel -$STD pip install pyyaml -msg_ok "Setup Python3" +PYTHON_VERSION="3.12" setup_uv msg_info "Setup SearXNG" mkdir -p /usr/local/searxng /etc/searxng @@ -36,11 +30,10 @@ useradd -d /etc/searxng searxng chown searxng:searxng /usr/local/searxng /etc/searxng $STD git clone https://github.com/searxng/searxng.git /usr/local/searxng/searxng-src cd /usr/local/searxng/ -sudo -u searxng python3 -m venv /usr/local/searxng/searx-pyenv -source /usr/local/searxng/searx-pyenv/bin/activate -$STD pip install --upgrade pip setuptools wheel -$STD pip install pyyaml -$STD pip install --use-pep517 --no-build-isolation -e /usr/local/searxng/searxng-src +$STD uv venv /usr/local/searxng/.venv +$STD uv pip install --upgrade pip setuptools wheel pyyaml +$STD uv pip install --no-build-isolation -e /usr/local/searxng/searxng-src + SECRET_KEY=$(openssl rand -hex 32) cat </etc/searxng/settings.yml # SearXNG settings @@ -94,7 +87,7 @@ Type=simple User=searxng Group=searxng Environment="SEARXNG_SETTINGS_PATH=/etc/searxng/settings.yml" -ExecStart=/usr/local/searxng/searx-pyenv/bin/python -m searx.webapp +ExecStart=/usr/local/searxng/searx-pyenv/bin/uv run -m searx.webapp WorkingDirectory=/usr/local/searxng/searxng-src Restart=always diff --git a/install/slskd-install.sh b/install/slskd-install.sh index b4b3d8b129a..e758a70d3a1 100644 --- a/install/slskd-install.sh +++ b/install/slskd-install.sh @@ -13,16 +13,13 @@ setting_up_container network_check update_os -msg_info "Installing Dependencies" -$STD apt-get install -y \ - python3-pip -msg_ok "Installed Dependencies" +PYTHON_VERSION="3.12" setup_uv msg_info "Setup ${APPLICATION}" tmp_file=$(mktemp) RELEASE=$(curl -s https://api.github.com/repos/slskd/slskd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') -curl -fsSL "https://github.com/slskd/slskd/releases/download/${RELEASE}/slskd-${RELEASE}-linux-x64.zip" -o $tmp_file -$STD unzip $tmp_file -d /opt/${APPLICATION} +curl -fsSL "https://github.com/slskd/slskd/releases/download/${RELEASE}/slskd-${RELEASE}-linux-x64.zip" -o "$tmp_file" +$STD unzip "$tmp_file" -d /opt/${APPLICATION} echo "${RELEASE}" >/opt/${APPLICATION}_version.txt JWT_KEY=$(openssl rand -base64 44) SLSKD_API_KEY=$(openssl rand -base64 44) @@ -40,13 +37,13 @@ sed -i \ msg_ok "Setup ${APPLICATION}" msg_info "Installing Soularr" -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED cd /tmp curl -fsSL -o main.zip https://github.com/mrusse/soularr/archive/refs/heads/main.zip $STD unzip main.zip mv soularr-main /opt/soularr cd /opt/soularr -$STD pip install -r requirements.txt +$STD uv venv /opt/soularr/.venv +$STD uv pip install -r requirements.txt sed -i \ -e "\|[Slskd]|,\|host_url|s|yourslskdapikeygoeshere|$SLSKD_API_KEY|" \ -e "/host_url/s/slskd/localhost/" \ @@ -54,7 +51,7 @@ sed -i \ sed -i \ -e "/#This\|#Default\|INTERVAL/{N;d;}" \ -e "/while\|#Pass/d" \ - -e "\|python|s|app|opt/soularr|; s|python|python3|" \ + -e "\|python|s|app|opt/soularr|; s|python|/opt/soularr/.venv/bin/python3|" \ -e "/dt/,+2d" \ /opt/soularr/run.sh sed -i -E "/(soularr.py)/s/.{5}$//; /if/,/fi/s/.{4}//" /opt/soularr/run.sh @@ -85,7 +82,6 @@ RefuseManualStop=no [Timer] Persistent=true -# run every 5 minutes OnCalendar=*-*-* *:0/5:00 Unit=soularr.service @@ -106,7 +102,8 @@ ExecStart=/bin/bash -c /opt/soularr/run.sh [Install] WantedBy=multi-user.target EOF -systemctl enable -q --now ${APPLICATION} + +systemctl enable -q --now soularr systemctl enable -q soularr.timer msg_ok "Created Services" @@ -114,8 +111,7 @@ motd_ssh customize msg_info "Cleaning up" -rm -rf $tmp_file -rm -rf /tmp/main.zip +rm -f "$tmp_file" /tmp/main.zip $STD apt-get -y autoremove $STD apt-get -y autoclean msg_ok "Cleaned" diff --git a/install/spoolman-install.sh b/install/spoolman-install.sh index 4a70725bfa3..c3ebbf8616d 100644 --- a/install/spoolman-install.sh +++ b/install/spoolman-install.sh @@ -22,22 +22,18 @@ $STD apt-get install -y \ ca-certificates msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y \ - python3-dev \ - python3-setuptools \ - python3-wheel \ - python3-pip -msg_ok "Setup Python3" +PYTHON_VERSION="3.12" setup_uv msg_info "Installing Spoolman" RELEASE=$(curl -fsSL https://github.com/Donkie/Spoolman/releases/latest | grep "title>Release" | cut -d " " -f 4) cd /opt curl -fsSL "https://github.com/Donkie/Spoolman/releases/download/$RELEASE/spoolman.zip" -o "spoolman.zip" $STD unzip spoolman.zip -d spoolman -rm -rf spoolman.zip +rm -f spoolman.zip cd spoolman -$STD pip3 install -r requirements.txt +$STD uv venv /opt/spoolman/.venv +$STD uv pip install -r requirements.txt + curl -fsSL "https://raw.githubusercontent.com/Donkie/Spoolman/master/.env.example" -o ".env" echo "${RELEASE}" >/opt/${APPLICATION}_version.txt msg_ok "Installed Spoolman" @@ -47,13 +43,15 @@ cat </etc/systemd/system/spoolman.service [Unit] Description=Spoolman After=network.target + [Service] Type=simple WorkingDirectory=/opt/spoolman EnvironmentFile=/opt/spoolman/.env -ExecStart=uvicorn spoolman.main:app --host 0.0.0.0 --port 7912 +ExecStart=/opt/spoolman/.venv/bin/uvicorn spoolman.main:app --host 0.0.0.0 --port 7912 Restart=always User=root + [Install] WantedBy=multi-user.target EOF diff --git a/install/stirling-pdf-install.sh b/install/stirling-pdf-install.sh index c058ab7bea0..84d1ad90d36 100644 --- a/install/stirling-pdf-install.sh +++ b/install/stirling-pdf-install.sh @@ -40,12 +40,13 @@ $STD apt-get install -y \ python3-uno msg_ok "Installed LibreOffice Components" -msg_info "Installing Python Dependencies" -$STD apt-get install -y \ - python3 \ - python3-pip -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -$STD pip3 install \ +PYTHON_VERSION="3.12" setup_uv + +msg_info "Installing Python Dependencies via uv" +$STD uv venv /opt/stirling/.venv +$STD /opt/stirling/.venv/bin/python -m ensurepip --upgrade +$STD /opt/stirling/.venv/bin/python -m pip install --upgrade pip +$STD /opt/stirling/.venv/bin/python -m pip install \ uno \ opencv-python-headless \ unoconv \ diff --git a/install/streamlink-webui-install.sh b/install/streamlink-webui-install.sh index 2ab9fe6a2bb..ab83ee58ec7 100644 --- a/install/streamlink-webui-install.sh +++ b/install/streamlink-webui-install.sh @@ -14,10 +14,8 @@ setting_up_container network_check update_os -NODE_VERSION="22" -NODE_MODULE="npm@latest,yarn@latest" -install_node_and_modules -setup_uv +NODE_VERSION="22" NODE_MODULE="npm@latest,yarn@latest" install_node_and_modules +PYTHON_VERSION="3.12" setup_uv fetch_and_deploy_gh_release "CrazyWolf13/streamlink-webui" msg_info "Setup ${APPLICATION}" diff --git a/install/tandoor-install.sh b/install/tandoor-install.sh index 3673e301382..d4dcfbb09c8 100644 --- a/install/tandoor-install.sh +++ b/install/tandoor-install.sh @@ -15,7 +15,7 @@ network_check update_os msg_info "Installing Dependencies (Patience)" -$STD apt-get install -y --no-install-recommends \ +$STD apt-get install -y \ build-essential \ libpq-dev \ libmagic-dev \ @@ -32,25 +32,22 @@ $STD apt-get install -y --no-install-recommends \ libxmlsec1-openssl msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-dev \ - python3-setuptools \ - python3-pip \ - python3-xmlsec -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" - +PYTHON_VERSION="3.12" setup_uv NODE_VERSION="20" NODE_MODULE="yarn@latest" install_node_and_modules msg_info "Installing Tandoor (Patience)" $STD git clone https://github.com/TandoorRecipes/recipes -b master /opt/tandoor mkdir -p /opt/tandoor/{config,api,mediafiles,staticfiles} -$STD pip3 install -r /opt/tandoor/requirements.txt +cd /opt/tandoor +$STD uv venv /opt/tandoor/.venv +$STD /opt/tandoor/.venv/bin/python -m ensurepip --upgrade +$STD /opt/tandoor/.venv/bin/python -m pip install --upgrade pip +$STD /opt/tandoor/.venv/bin/python -m pip install -r requirements.txt + cd /opt/tandoor/vue $STD yarn install $STD yarn build + curl -fsSL "https://raw.githubusercontent.com/TandoorRecipes/recipes/develop/.env.template" -o "/opt/tandoor/.env" DB_NAME=db_recipes DB_USER=tandoor @@ -65,7 +62,7 @@ sed -i -e "s|SECRET_KEY=.*|SECRET_KEY=$secret_key|g" \ -e "s|POSTGRES_USER=.*|POSTGRES_USER=$DB_USER|g" \ -e "\$a\STATIC_URL=/staticfiles/" /opt/tandoor/.env cd /opt/tandoor -$STD python3 version.py +$STD /opt/tandoor/.venv/bin/python -m version.py msg_ok "Installed Tandoor" msg_info "Install/Set up PostgreSQL Database" @@ -83,9 +80,9 @@ echo -e "Tandoor Database Name: \e[32m$DB_NAME\e[0m" >>~/tandoor.creds echo -e "Tandoor Database User: \e[32m$DB_USER\e[0m" >>~/tandoor.creds echo -e "Tandoor Database Password: \e[32m$DB_PASS\e[0m" >>~/tandoor.creds export $(cat /opt/tandoor/.env | grep "^[^#]" | xargs) -/usr/bin/python3 /opt/tandoor/manage.py migrate >/dev/null 2>&1 -/usr/bin/python3 /opt/tandoor/manage.py collectstatic --no-input >/dev/null 2>&1 -/usr/bin/python3 /opt/tandoor/manage.py collectstatic_js_reverse >/dev/null 2>&1 +$STD /opt/tandoor/.venv/bin/python -m manage migrate +$STD /opt/tandoor/.venv/bin/python -m manage collectstatic --no-input +$STD /opt/tandoor/.venv/bin/python -m python manage collectstatic_js_reverse msg_ok "Set up PostgreSQL Database" msg_info "Creating Services" @@ -100,7 +97,7 @@ Restart=always RestartSec=3 WorkingDirectory=/opt/tandoor EnvironmentFile=/opt/tandoor/.env -ExecStart=/usr/local/bin/gunicorn --error-logfile /tmp/gunicorn_err.log --log-level debug --capture-output --bind unix:/opt/tandoor/tandoor.sock recipes.wsgi:application +ExecStart=/opt/tandoor/.venv/bin/gunicorn --error-logfile /tmp/gunicorn_err.log --log-level debug --capture-output --bind unix:/opt/tandoor/tandoor.sock recipes.wsgi:application [Install] WantedBy=multi-user.target diff --git a/install/tasmocompiler-install.sh b/install/tasmocompiler-install.sh index 1ba241f0bb8..e056df1586b 100644 --- a/install/tasmocompiler-install.sh +++ b/install/tasmocompiler-install.sh @@ -14,21 +14,12 @@ network_check update_os msg_info "Installing Dependencies. Patience" -$STD apt-get install -y \ - git +$STD apt-get install -y git msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y python3-venv -msg_ok "Setup Python3" - +PYTHON_VERSION="3.12" setup_uv NODE_VERSION="22" NODE_MODULE="yarn@latest" install_node_and_modules -msg_info "Setup Platformio" -curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -$STD python3 get-platformio.py -msg_ok "Setup Platformio" - msg_info "Setup TasmoCompiler" mkdir /tmp/Tasmota RELEASE=$(curl -fsSL https://api.github.com/repos/benzino77/tasmocompiler/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') @@ -37,14 +28,18 @@ cd /tmp tar xzf /tmp/v${RELEASE}.tar.gz mv tasmocompiler-${RELEASE}/ /opt/tasmocompiler/ cd /opt/tasmocompiler +$STD uv venv /opt/tasmocompiler/.venv +$STD /opt/tasmocompiler/.venv/bin/python -m ensurepip --upgrade +$STD /opt/tasmocompiler/.venv/bin/python -m pip install --upgrade pip +$STD /opt/tasmocompiler/.venv/bin/python -m pip install platformio $STD yarn install export NODE_OPTIONS=--openssl-legacy-provider $STD npm i $STD yarn build mkdir -p /usr/local/bin -ln -s ~/.platformio/penv/bin/platformio /usr/local/bin/platformio -ln -s ~/.platformio/penv/bin/pio /usr/local/bin/pio -ln -s ~/.platformio/penv/bin/piodebuggdb /usr/local/bin/piodebuggdb +ln -sf /opt/tasmocompiler/.venv/bin/platformio /usr/local/bin/platformio +ln -sf /opt/tasmocompiler/.venv/bin/pio /usr/local/bin/pio +ln -sf /opt/tasmocompiler/.venv/bin/piodebuggdb /usr/local/bin/piodebuggdb echo "${RELEASE}" >"/opt/tasmocompiler_version.txt" msg_ok "Setup TasmoCompiler" diff --git a/install/tautulli-install.sh b/install/tautulli-install.sh index 63734ddd3f6..7c82a89912d 100644 --- a/install/tautulli-install.sh +++ b/install/tautulli-install.sh @@ -15,22 +15,17 @@ update_os msg_info "Installing Dependencies" $STD apt-get install -y git -$STD apt-get install -y pip msg_ok "Installed Dependencies" -msg_info "Setup Python3" -$STD apt-get install -y \ - python3 \ - python3-dev \ - python3-pip -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" +PYTHON_VERSION="3.12" setup_uv msg_info "Installing Tautulli" cd /opt $STD git clone https://github.com/Tautulli/Tautulli.git -$STD pip install -q -r /opt/Tautulli/requirements.txt -$STD pip install pyopenssl +cd /opt/Tautulli +$STD uv venv /opt/Tautulli/.venv +$STD uv pip install -r /opt/Tautulli/requirements.txt +$STD uv pip install pyopenssl msg_ok "Installed Tautulli" msg_info "Creating Service" @@ -44,7 +39,7 @@ WorkingDirectory=/opt/Tautulli/ Restart=on-failure RestartSec=5 Type=simple -ExecStart=/usr/bin/python3 /opt/Tautulli/Tautulli.py +ExecStart=/opt/Tautulli/.venv/bin/python /opt/Tautulli/Tautulli.py KillSignal=SIGINT TimeoutStopSec=20 SyslogIdentifier=tautulli diff --git a/install/tianji-install.sh b/install/tianji-install.sh index 56d079a38fa..45b4200a4ac 100644 --- a/install/tianji-install.sh +++ b/install/tianji-install.sh @@ -16,13 +16,13 @@ update_os msg_info "Installing Dependencies" $STD apt-get install -y \ - python3 \ cmake \ g++ \ build-essential \ git \ make \ - ca-certificates + ca-certificates \ + jq msg_ok "Installed Dependencies" NODE_VERSION="22" NODE_MODULE="pnpm@$(curl -s https://raw.githubusercontent.com/msgbyte/tianji/master/package.json | jq -r '.packageManager | split("@")[1]')" install_node_and_modules diff --git a/install/unmanic-install.sh b/install/unmanic-install.sh index 48d5da7d51b..785103a770d 100644 --- a/install/unmanic-install.sh +++ b/install/unmanic-install.sh @@ -14,10 +14,11 @@ network_check update_os msg_info "Installing Dependencies (Patience)" -$STD apt-get install -y ffmpeg -$STD apt-get install -y python3-pip +$STD apt-get install -y ffmpeg gcc msg_ok "Installed Dependencies" +PYTHON_VERSION="3.12" setup_uv + if [[ "$CTTYPE" == "0" ]]; then msg_info "Setting Up Hardware Acceleration" $STD apt-get -y install \ @@ -33,7 +34,12 @@ if [[ "$CTTYPE" == "0" ]]; then fi msg_info "Installing Unmanic" -$STD pip3 install unmanic +mkdir -p /opt/unmanic +cd /opt/unmanic +$STD uv venv /opt/unmanic/.venv +$STD /opt/unmanic/.venv/bin/python -m ensurepip --upgrade +$STD /opt/unmanic/.venv/bin/python -m pip install --upgrade pip +$STD /opt/unmanic/.venv/bin/python -m pip install unmanic sed -i -e 's/^sgx:x:104:$/render:x:104:root/' -e 's/^render:x:106:root$/sgx:x:106:/' /etc/group msg_ok "Installed Unmanic" @@ -47,7 +53,7 @@ StartLimitBurst=3 [Service] Type=simple -ExecStart=/usr/local/bin/unmanic +ExecStart=/opt/unmanic/.venv/bin/unmanic Restart=always RestartSec=30 diff --git a/install/web-check-install.sh b/install/web-check-install.sh index 6ad50f6cfb6..c6434e5715a 100644 --- a/install/web-check-install.sh +++ b/install/web-check-install.sh @@ -35,13 +35,9 @@ $STD apt-get -y install --no-install-recommends \ x11-apps msg_ok "Installed Dependencies" +PYTHON_VERSION="3.12" setup_uv NODE_VERSION="22" NODE_MODULE="yarn@latest" install_node_and_modules -msg_info "Setup Python3" -$STD apt-get install -y python3 -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Setup Python3" - msg_info "Installing Chromium" curl -fsSL https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /etc/apt/trusted.gpg.d/google-archive.gpg echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >/etc/apt/sources.list.d/google.list diff --git a/install/wger-install.sh b/install/wger-install.sh index 69eccaabda6..edcb48c07dd 100644 --- a/install/wger-install.sh +++ b/install/wger-install.sh @@ -20,11 +20,7 @@ $STD apt-get install -y \ libapache2-mod-wsgi-py3 msg_ok "Installed Dependencies" -msg_info "Installing Python" -$STD apt-get install -y python3-pip -rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED -msg_ok "Installed Python" - +PYTHON_VERSION="3.12" setup_uv NODE_VERSION="22" NODE_MODULE="yarn@latest,sass" install_node_and_modules msg_info "Setting up wger" @@ -42,13 +38,17 @@ curl -fsSL "https://github.com/wger-project/wger/archive/refs/tags/$RELEASE.tar. tar xzf $RELEASE.tar.gz mv wger-$RELEASE /home/wger/src cd /home/wger/src -$STD pip install -r requirements_prod.txt -$STD pip install -e . -$STD wger create-settings --database-path /home/wger/db/database.sqlite +$STD uv venv /home/wger/.venv +$STD /home/wger/.venv/bin/python -m ensurepip --upgrade +$STD /home/wger/.venv/bin/python -m pip install --upgrade pip +$STD /home/wger/.venv/bin/python -m pip install -r requirements_prod.txt +$STD /home/wger/.venv/bin/python -m pip install -e . +$STD /home/wger/.venv/bin/wger create-settings --database-path /home/wger/db/database.sqlite sed -i "s#home/wger/src/media#home/wger/media#g" /home/wger/src/settings.py sed -i "/MEDIA_ROOT = '\/home\/wger\/media'/a STATIC_ROOT = '/home/wger/static'" /home/wger/src/settings.py -$STD wger bootstrap -$STD python3 manage.py collectstatic +$STD /home/wger/.venv/bin/wger bootstrap +cd /home/wger/src/ +$STD /home/wger/.venv/bin/python -m manage collectstatic echo "${RELEASE}" >/opt/wger_version.txt msg_ok "Finished setting up wger" @@ -92,7 +92,7 @@ After=network.target [Service] Type=simple User=root -ExecStart=/usr/local/bin/wger start -a 0.0.0.0 -p 3000 +ExecStart=/home/wger/.venv/bin/wger start -a 0.0.0.0 -p 3000 Restart=always [Install] diff --git a/misc/build.func b/misc/build.func index 531ca1a0341..857bc40abee 100644 --- a/misc/build.func +++ b/misc/build.func @@ -2,7 +2,7 @@ # Author: tteck (tteckster) # Co-Author: MickLesk # Co-Author: michelroegl-brunner -# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/python_to_uv/LICENSE variables() { NSAPP=$(echo "${APP,,}" | tr -d ' ') # This function sets the NSAPP variable by converting the value of the APP variable to lowercase and removing any spaces. @@ -14,7 +14,7 @@ variables() { RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" # generates a random UUID and sets it to the RANDOM_UUID variable. } -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/api.func) # This function sets various color variables using ANSI escape codes for formatting text in the terminal. color() { @@ -70,7 +70,7 @@ catch_errors() { # This function is called when an error occurs. It receives the exit code, line number, and command that caused the error, and displays an error message. error_handler() { - source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) + source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/api.func) if [ -n "$SPINNER_PID" ] && ps -p "$SPINNER_PID" >/dev/null; then kill "$SPINNER_PID" >/dev/null; fi printf "\e[?25h" local exit_code="$?" @@ -276,7 +276,7 @@ update_motd_ip() { # Function to download & save header files get_header() { local app_name=$(echo "${APP,,}" | tr -d ' ') - local header_url="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/headers/${app_name}" + local header_url="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/ct/headers/${app_name}" local local_header_path="/usr/local/community-scripts/headers/${app_name}" mkdir -p "$(dirname "$local_header_path")" @@ -952,7 +952,7 @@ install_script() { header_info echo -e "${INFO}${HOLD} ${GN}Using Config File on node $PVEHOST_NAME${CL}" METHOD="config_file" - source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/config-file.func) + source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/config-file.func) config_file break ;; @@ -1025,13 +1025,8 @@ check_container_storage() { } start() { - source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func) + source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/tools.func) if command -v pveversion >/dev/null 2>&1; then - if ! (whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP} LXC" --yesno "This will create a New ${APP} LXC. Proceed?" 10 58); then - clear - exit_script - exit - fi SPINNER_PID="" install_script fi @@ -1086,9 +1081,9 @@ build_container() { TEMP_DIR=$(mktemp -d) pushd "$TEMP_DIR" >/dev/null if [ "$var_os" == "alpine" ]; then - export FUNCTIONS_FILE_PATH="$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/alpine-install.func)" + export FUNCTIONS_FILE_PATH="$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/alpine-install.func)" else - export FUNCTIONS_FILE_PATH="$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/install.func)" + export FUNCTIONS_FILE_PATH="$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/install.func)" fi export RANDOM_UUID="$RANDOM_UUID" export CACHER="$APT_CACHER" @@ -1122,7 +1117,7 @@ build_container() { $PW " # This executes create_lxc.sh and creates the container and .conf file - bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/create_lxc.sh)" $? + bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/ct/create_lxc.sh)" $? LXC_CONFIG=/etc/pve/lxc/${CTID}.conf if [ "$CT_TYPE" == "0" ]; then @@ -1191,7 +1186,7 @@ http://dl-cdn.alpinelinux.org/alpine/latest-stable/community EOF' pct exec "$CTID" -- ash -c "apk add bash >/dev/null" fi - lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/"$var_install".sh)" $? + lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/install/"$var_install".sh)" $? } @@ -1204,7 +1199,7 @@ description() { cat < - Logo + Logo

${APP} LXC

diff --git a/misc/install.func b/misc/install.func index 842ed4a97d0..a7c8eee86ea 100644 --- a/misc/install.func +++ b/misc/install.func @@ -2,7 +2,7 @@ # Author: tteck (tteckster) # Co-Author: MickLesk # License: MIT -# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# https://github.com/community-scripts/ProxmoxVE/raw/python_to_uv/LICENSE # This function sets color variables for formatting output in the terminal color() { @@ -69,7 +69,7 @@ catch_errors() { # This function handles errors error_handler() { - source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) + source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/api.func) if [ -n "$SPINNER_PID" ] && ps -p "$SPINNER_PID" >/dev/null; then kill "$SPINNER_PID" >/dev/null; fi printf "\e[?25h" local exit_code="$?" @@ -216,7 +216,7 @@ EOF msg_info "Installing core dependencies" $STD apt-get update $STD apt-get install -y sudo curl mc gnupg2 - source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func) + source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/misc/tools.func) msg_ok "Core dependencies installed" } @@ -267,7 +267,7 @@ EOF systemctl restart $(basename $(dirname $GETTY_OVERRIDE) | sed 's/\.d//') msg_ok "Customized Container" fi - echo "bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/${app}.sh)\"" >/usr/bin/update + echo "bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/python_to_uv/ct/${app}.sh)\"" >/usr/bin/update chmod +x /usr/bin/update if [[ -n "${SSH_AUTHORIZED_KEY}" ]]; then diff --git a/misc/tools.func b/misc/tools.func index 430ff02757a..3033d6372b8 100644 --- a/misc/tools.func +++ b/misc/tools.func @@ -164,11 +164,7 @@ install_postgresql() { msg_info "Stopping PostgreSQL service" systemctl stop postgresql fi - - msg_info "Removing pgdg repo and old GPG key" rm -f /etc/apt/sources.list.d/pgdg.list /etc/apt/trusted.gpg.d/postgresql.gpg - - msg_info "Adding PostgreSQL PGDG repository" curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg @@ -1008,63 +1004,163 @@ function download_with_progress() { # ------------------------------------------------------------------------------ # Installs or upgrades uv (Python package manager) from GitHub releases. -# -# Description: -# - Downloads architecture-specific tarball -# - Places binary in /usr/local/bin +# - Downloads platform-specific tarball (no install.sh!) +# - Extracts uv binary +# - Places it in /usr/local/bin +# - Optionally installs a specific Python version via uv # ------------------------------------------------------------------------------ function setup_uv() { $STD msg_info "Checking uv installation..." - UV_BIN="/usr/local/bin/uv" + local UV_BIN="/usr/local/bin/uv" + local TMP_DIR TMP_DIR=$(mktemp -d) + + # Determine system architecture + local ARCH ARCH=$(uname -m) + local UV_TAR - if [[ "$ARCH" == "x86_64" ]]; then - UV_TAR="uv-x86_64-unknown-linux-gnu.tar.gz" - elif [[ "$ARCH" == "aarch64" ]]; then - UV_TAR="uv-aarch64-unknown-linux-gnu.tar.gz" - else + case "$ARCH" in + x86_64) UV_TAR="uv-x86_64-unknown-linux-gnu.tar.gz" ;; + aarch64) UV_TAR="uv-aarch64-unknown-linux-gnu.tar.gz" ;; + *) msg_error "Unsupported architecture: $ARCH" rm -rf "$TMP_DIR" return 1 - fi + ;; + esac + + # Get latest version from GitHub + local LATEST_VERSION + LATEST_VERSION=$(curl -fsSL https://api.github.com/repos/astral-sh/uv/releases/latest | + grep '"tag_name":' | cut -d '"' -f4 | sed 's/^v//') - # get current github version - LATEST_VERSION=$(curl -s https://api.github.com/repos/astral-sh/uv/releases/latest | grep '"tag_name":' | cut -d '"' -f4 | sed 's/^v//') if [[ -z "$LATEST_VERSION" ]]; then msg_error "Could not fetch latest uv version from GitHub." rm -rf "$TMP_DIR" return 1 fi - # check if uv exists + # Check if uv is already up to date if [[ -x "$UV_BIN" ]]; then + local INSTALLED_VERSION INSTALLED_VERSION=$($UV_BIN -V | awk '{print $2}') if [[ "$INSTALLED_VERSION" == "$LATEST_VERSION" ]]; then $STD msg_ok "uv is already at the latest version ($INSTALLED_VERSION)" rm -rf "$TMP_DIR" - # set path - if [[ ":$PATH:" != *":/usr/local/bin:"* ]]; then - export PATH="/usr/local/bin:$PATH" - fi + [[ ":$PATH:" != *":/usr/local/bin:"* ]] && export PATH="/usr/local/bin:$PATH" return 0 else $STD msg_info "Updating uv from $INSTALLED_VERSION to $LATEST_VERSION" fi else - $STD msg_info "uv not found. Installing version $LATEST_VERSION" + $STD msg_info "Installing uv $LATEST_VERSION" fi - # install or update uv - curl -fsSL "https://github.com/astral-sh/uv/releases/latest/download/${UV_TAR}" -o "$TMP_DIR/uv.tar.gz" - tar -xzf "$TMP_DIR/uv.tar.gz" -C "$TMP_DIR" - install -m 755 "$TMP_DIR"/*/uv "$UV_BIN" - rm -rf "$TMP_DIR" + # Download and install manually + local UV_URL="https://github.com/astral-sh/uv/releases/latest/download/${UV_TAR}" + if ! curl -fsSL "$UV_URL" -o "$TMP_DIR/uv.tar.gz"; then + msg_error "Failed to download $UV_URL" + rm -rf "$TMP_DIR" + return 1 + fi + + if ! tar -xzf "$TMP_DIR/uv.tar.gz" -C "$TMP_DIR"; then + msg_error "Failed to extract uv archive" + rm -rf "$TMP_DIR" + return 1 + fi - # set path + install -m 755 "$TMP_DIR"/*/uv "$UV_BIN" || { + msg_error "Failed to install uv binary" + rm -rf "$TMP_DIR" + return 1 + } + + rm -rf "$TMP_DIR" ensure_usr_local_bin_persist - msg_ok "uv installed/updated to $LATEST_VERSION" + msg_ok "uv $LATEST_VERSION installed" + + # Optional: install specific Python version + if [[ -n "${PYTHON_VERSION:-}" ]]; then + $STD msg_info "Ensuring Python $PYTHON_VERSION is available via uv..." + + local VERSION_MATCH + VERSION_MATCH=$(uv python list --only-downloads | + grep -E "^cpython-${PYTHON_VERSION//./\\.}\.[0-9]+-linux" | + cut -d'-' -f2 | sort -V | tail -n1) + + if [[ -z "$VERSION_MATCH" ]]; then + msg_error "No matching Python $PYTHON_VERSION.x version found via uv" + return 1 + fi + + if uv python list | grep -q "cpython-${VERSION_MATCH}-linux.*uv/python"; then + $STD msg_ok "Python $VERSION_MATCH already installed via uv" + else + if ! $STD uv python install "$VERSION_MATCH"; then + msg_error "Failed to install Python $VERSION_MATCH via uv" + return 1 + fi + msg_ok "Installed Python $VERSION_MATCH" + fi + fi +} + +# ------------------------------------------------------------------------------ +# Creates a uv-based venv with optional Python version and installs dependencies +# ------------------------------------------------------------------------------ + +function setup_uv_venv() { + local VENV_FOLDER="${VENV_FOLDER:?VENV_FOLDER not set}" + local PYTHON_VERSION="${PYTHON_VERSION:?PYTHON_VERSION not set}" + local REQUIREMENTS_FILE="${REQUIREMENTS_FILE:-requirements.txt}" + local PYTHON_BIN + + setup_uv || return 1 + + # Install Python via uv if not already available + local VERSION_MATCH + VERSION_MATCH=$(uv python list --only-downloads | + grep -E "^cpython-${PYTHON_VERSION//./\\.}\.[0-9]+-linux" | + cut -d'-' -f2 | sort -V | tail -n1) + + if [[ -z "$VERSION_MATCH" ]]; then + msg_error "No matching Python $PYTHON_VERSION.x version found via uv" + return 1 + fi + + if ! uv python list | grep -q "cpython-${VERSION_MATCH}-linux.*uv/python"; then + $STD msg_info "Installing Python $VERSION_MATCH via uv" + $STD uv python install "$VERSION_MATCH" || { + msg_error "Failed to install Python $VERSION_MATCH via uv" + return 1 + } + fi + + $STD msg_info "Creating uv venv in $VENV_FOLDER" + if ! $STD uv venv "$VENV_FOLDER" --python "$VERSION_MATCH"; then + msg_error "Failed to create uv venv" + return 1 + fi + + PYTHON_BIN="$VENV_FOLDER/bin/python" + + $STD msg_info "Running ensurepip" + $STD "$PYTHON_BIN" -m ensurepip --upgrade || return 1 + + $STD msg_info "Upgrading pip" + $STD "$PYTHON_BIN" -m pip install --upgrade pip || return 1 + + if [[ -f "$REQUIREMENTS_FILE" ]]; then + $STD msg_info "Installing requirements from $REQUIREMENTS_FILE" + $STD "$PYTHON_BIN" -m pip install -r "$REQUIREMENTS_FILE" || return 1 + else + msg_info "No requirements file found at $REQUIREMENTS_FILE – skipping" + fi + + msg_ok "uv venv setup complete in $VENV_FOLDER" } # ------------------------------------------------------------------------------