mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2025-12-14 19:23:32 +01:00
Compare commits
29 Commits
2025-06-19
...
2025-06-20
| Author | SHA1 | Date | |
|---|---|---|---|
| a8deff54d8 | |||
| e33cf652a1 | |||
| b35eadfc36 | |||
| 74a073e8bd | |||
| ce9c1e63a8 | |||
| 25f6245d31 | |||
| 074d6fa31b | |||
| 8dfacb9e7d | |||
| 12a6055ea3 | |||
| 637f9a1f44 | |||
| a7ed02160b | |||
| 03551e23e4 | |||
| 1f7d85ac60 | |||
| 4e46fd739d | |||
| ea5eca83fe | |||
| b49b902d64 | |||
| f81f7fb1c0 | |||
| bcdeeaafb3 | |||
| 92f631b628 | |||
| 9133782289 | |||
| e343c7b5aa | |||
| 3e47e39633 | |||
| 43a90bf9e6 | |||
| cd45ccfb70 | |||
| b52cba817f | |||
| ac203f4e79 | |||
| b019991ee6 | |||
| 6bc17a0031 | |||
| 69d9394840 |
29
CHANGELOG.md
29
CHANGELOG.md
@ -14,8 +14,37 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
All LXC instances created using this repository come pre-installed with Midnight Commander, which is a command-line tool (`mc`) that offers a user-friendly file and directory management interface for the terminal environment.
|
All LXC instances created using this repository come pre-installed with Midnight Commander, which is a command-line tool (`mc`) that offers a user-friendly file and directory management interface for the terminal environment.
|
||||||
|
|
||||||
|
|
||||||
|
## 2025-06-21
|
||||||
|
|
||||||
## 2025-06-20
|
## 2025-06-20
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Immich: remove unneeded tmp_file [@MickLesk](https://github.com/MickLesk) ([#5332](https://github.com/community-scripts/ProxmoxVE/pull/5332))
|
||||||
|
- Huntarr: Fix duplicate update status messages [@tremor021](https://github.com/tremor021) ([#5336](https://github.com/community-scripts/ProxmoxVE/pull/5336))
|
||||||
|
- fix planka Tags [@CrazyWolf13](https://github.com/CrazyWolf13) ([#5311](https://github.com/community-scripts/ProxmoxVE/pull/5311))
|
||||||
|
- PLANKA: Better DB password generate [@tremor021](https://github.com/tremor021) ([#5313](https://github.com/community-scripts/ProxmoxVE/pull/5313))
|
||||||
|
- Immich: Hotfix for #5299 [@vhsdream](https://github.com/vhsdream) ([#5300](https://github.com/community-scripts/ProxmoxVE/pull/5300))
|
||||||
|
- changedetection: add msedge as Browser dependency [@Niklas04](https://github.com/Niklas04) ([#5301](https://github.com/community-scripts/ProxmoxVE/pull/5301))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- (turnkey) Add OpenLDAP as a TurnKey option [@mhaligowski](https://github.com/mhaligowski) ([#5305](https://github.com/community-scripts/ProxmoxVE/pull/5305))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- [core]: unify misc/*.func scripts with centralized logic from core.func [@MickLesk](https://github.com/MickLesk) ([#5316](https://github.com/community-scripts/ProxmoxVE/pull/5316))
|
||||||
|
- Refactor: migrate AdventureLog update to uv and GitHub release logic [@MickLesk](https://github.com/MickLesk) ([#5318](https://github.com/community-scripts/ProxmoxVE/pull/5318))
|
||||||
|
- Refactor: migrate Jupyter Notebook to uv-based installation with update support [@MickLesk](https://github.com/MickLesk) ([#5320](https://github.com/community-scripts/ProxmoxVE/pull/5320))
|
||||||
|
|
||||||
|
### 🌐 Website
|
||||||
|
|
||||||
|
- #### 📝 Script Information
|
||||||
|
|
||||||
|
- Argus: fix wrong port on website [@MickLesk](https://github.com/MickLesk) ([#5322](https://github.com/community-scripts/ProxmoxVE/pull/5322))
|
||||||
|
|
||||||
## 2025-06-19
|
## 2025-06-19
|
||||||
|
|
||||||
### 🆕 New Scripts
|
### 🆕 New Scripts
|
||||||
|
|||||||
@ -27,43 +27,51 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RELEASE=$(curl -fsSL https://api.github.com/repos/seanmorley15/AdventureLog/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
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
|
if [[ "${RELEASE}" != "$(cat ~/.adventurelog 2>/dev/null)" ]] || [[ ! -f ~/.adventurelog ]]; then
|
||||||
msg_info "Stopping Services"
|
msg_info "Stopping Services"
|
||||||
systemctl stop adventurelog-backend
|
systemctl stop adventurelog-backend
|
||||||
systemctl stop adventurelog-frontend
|
systemctl stop adventurelog-frontend
|
||||||
msg_ok "Services Stopped"
|
msg_ok "Services Stopped"
|
||||||
|
|
||||||
msg_info "Updating ${APP} to ${RELEASE}"
|
fetch_and_deploy_gh_release "adventurelog" "seanmorley15/adventurelog"
|
||||||
mv /opt/adventurelog/ /opt/adventurelog-backup/
|
PYTHON_VERSION="3.12" setup_uv
|
||||||
curl -fsSL -o /opt/v${RELEASE}.zip "https://github.com/seanmorley15/AdventureLog/archive/refs/tags/v${RELEASE}.zip"
|
|
||||||
$STD unzip /opt/v${RELEASE}.zip -d /opt/
|
msg_info "Updating ${APP} to v${RELEASE}"
|
||||||
mv /opt/AdventureLog-${RELEASE} /opt/adventurelog
|
# Backend Migration
|
||||||
|
cp /opt/adventurelog-backup/backend/server/.env /opt/adventurelog/backend/server/.env
|
||||||
|
cp -r /opt/adventurelog-backup/backend/server/media /opt/adventurelog/backend/server/media
|
||||||
|
|
||||||
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
|
cd /opt/adventurelog/backend/server
|
||||||
$STD pip install --upgrade pip
|
if [[ ! -x .venv/bin/python ]]; then
|
||||||
$STD pip install -r requirements.txt
|
$STD uv venv .venv
|
||||||
$STD python3 manage.py collectstatic --noinput
|
$STD .venv/bin/python -m ensurepip --upgrade
|
||||||
$STD python3 manage.py migrate
|
fi
|
||||||
|
|
||||||
mv /opt/adventurelog-backup/frontend/.env /opt/adventurelog/frontend/.env
|
$STD .venv/bin/python -m pip install --upgrade pip
|
||||||
|
$STD .venv/bin/python -m pip install -r requirements.txt
|
||||||
|
$STD .venv/bin/python -m manage collectstatic --noinput
|
||||||
|
$STD .venv/bin/python -m manage migrate
|
||||||
|
|
||||||
|
# Frontend Migration
|
||||||
|
cp /opt/adventurelog-backup/frontend/.env /opt/adventurelog/frontend/.env
|
||||||
cd /opt/adventurelog/frontend
|
cd /opt/adventurelog/frontend
|
||||||
$STD pnpm install
|
$STD pnpm i
|
||||||
$STD pnpm run build
|
$STD pnpm build
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
|
||||||
msg_ok "Updated ${APP}"
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
msg_info "Starting Services"
|
msg_info "Starting Services"
|
||||||
|
systemctl daemon-reexec
|
||||||
systemctl start adventurelog-backend
|
systemctl start adventurelog-backend
|
||||||
systemctl start adventurelog-frontend
|
systemctl start adventurelog-frontend
|
||||||
msg_ok "Started Services"
|
msg_ok "Services Started"
|
||||||
|
|
||||||
msg_info "Cleaning Up"
|
msg_info "Cleaning Up"
|
||||||
rm -rf /opt/v${RELEASE}.zip
|
rm -rf /opt/v${RELEASE}.zip
|
||||||
rm -rf /opt/adventurelog-backup
|
rm -rf /opt/adventurelog-backup
|
||||||
msg_ok "Cleaned"
|
msg_ok "Cleaned"
|
||||||
|
|
||||||
msg_ok "Updated Successfully"
|
msg_ok "Updated Successfully"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
|||||||
@ -52,7 +52,7 @@ function update_script() {
|
|||||||
$STD /opt/browserless/node_modules/playwright-core/cli.js install --with-deps
|
$STD /opt/browserless/node_modules/playwright-core/cli.js install --with-deps
|
||||||
# Update Chrome separately, as it has to be done with the force option. Otherwise the installation of other browsers will not be done if Chrome is already installed.
|
# Update Chrome separately, as it has to be done with the force option. Otherwise the installation of other browsers will not be done if Chrome is already installed.
|
||||||
$STD /opt/browserless/node_modules/playwright-core/cli.js install --force chrome
|
$STD /opt/browserless/node_modules/playwright-core/cli.js install --force chrome
|
||||||
$STD /opt/browserless/node_modules/playwright-core/cli.js install chromium firefox webkit
|
$STD /opt/browserless/node_modules/playwright-core/cli.js install chromium firefox webkit msedge
|
||||||
$STD npm run build --prefix /opt/browserless
|
$STD npm run build --prefix /opt/browserless
|
||||||
$STD npm run build:function --prefix /opt/browserless
|
$STD npm run build:function --prefix /opt/browserless
|
||||||
$STD npm prune production --prefix /opt/browserless
|
$STD npm prune production --prefix /opt/browserless
|
||||||
@ -74,4 +74,4 @@ description
|
|||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5000${CL}"
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5000${CL}"
|
||||||
|
|||||||
@ -40,10 +40,10 @@ function update_script() {
|
|||||||
msg_ok "Stopped huntarr service"
|
msg_ok "Stopped huntarr service"
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "huntarr" "plexguide/Huntarr.io"
|
fetch_and_deploy_gh_release "huntarr" "plexguide/Huntarr.io"
|
||||||
msg_info "Updating $APP to v${RELEASE}"
|
msg_info "Configuring $APP"
|
||||||
cd /opt/huntarr
|
cd /opt/huntarr
|
||||||
$STD uv pip install -r requirements.txt --python /opt/huntarr/.venv/bin/python
|
$STD uv pip install -r requirements.txt --python /opt/huntarr/.venv/bin/python
|
||||||
msg_ok "Updated $APP to v${RELEASE}"
|
msg_ok "Configured $APP"
|
||||||
|
|
||||||
msg_info "Starting $APP"
|
msg_info "Starting $APP"
|
||||||
systemctl start huntarr
|
systemctl start huntarr
|
||||||
|
|||||||
@ -208,7 +208,7 @@ function update_script() {
|
|||||||
$STD apt install -y ./vchord.deb
|
$STD apt install -y ./vchord.deb
|
||||||
$STD sudo -u postgres psql -d immich -c "ALTER EXTENSION vchord UPDATE;"
|
$STD sudo -u postgres psql -d immich -c "ALTER EXTENSION vchord UPDATE;"
|
||||||
systemctl restart postgresql
|
systemctl restart postgresql
|
||||||
if [[ ! -f ~/.vchord-version ]] || [[ ! "$(cat ~/.vchord_version)" > "0.3.0" ]]; then
|
if [[ ! -f ~/.vchord_version ]] || [[ ! "$(cat ~/.vchord_version)" > "0.3.0" ]]; then
|
||||||
$STD sudo -u postgres psql -d immich -c "REINDEX DATABASE;"
|
$STD sudo -u postgres psql -d immich -c "REINDEX DATABASE;"
|
||||||
fi
|
fi
|
||||||
echo "$VCHORD_RELEASE" >~/.vchord_version
|
echo "$VCHORD_RELEASE" >~/.vchord_version
|
||||||
@ -226,6 +226,9 @@ function update_script() {
|
|||||||
mv "$APP-$RELEASE"/ "$SRC_DIR"
|
mv "$APP-$RELEASE"/ "$SRC_DIR"
|
||||||
mkdir -p "$ML_DIR"
|
mkdir -p "$ML_DIR"
|
||||||
cd "$SRC_DIR"/server
|
cd "$SRC_DIR"/server
|
||||||
|
if [[ "$RELEASE" == "1.135.1" ]]; then
|
||||||
|
rm ./src/schema/migrations/1750323941566-UnsetPrewarmDimParameter.ts
|
||||||
|
fi
|
||||||
$STD npm install -g node-gyp node-pre-gyp
|
$STD npm install -g node-gyp node-pre-gyp
|
||||||
$STD npm ci
|
$STD npm ci
|
||||||
$STD npm run build
|
$STD npm run build
|
||||||
|
|||||||
@ -20,16 +20,53 @@ color
|
|||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
|
|
||||||
msg_info "Updating ${APP} LXC"
|
INSTALL_DIR="/opt/jupyter"
|
||||||
$STD apt-get update
|
VENV_PYTHON="${INSTALL_DIR}/.venv/bin/python"
|
||||||
$STD apt-get install -y upgrade
|
VENV_JUPYTER="${INSTALL_DIR}/.venv/bin/jupyter"
|
||||||
$STD pip3 install jupyter --upgrade
|
SERVICE_FILE="/etc/systemd/system/jupyternotebook.service"
|
||||||
msg_ok "Updated Successfully"
|
|
||||||
exit
|
if [[ ! -x "$VENV_JUPYTER" ]]; then
|
||||||
|
msg_info "Migrating to uv venv"
|
||||||
|
PYTHON_VERSION="3.12" setup_uv
|
||||||
|
mkdir -p "$INSTALL_DIR"
|
||||||
|
cd "$INSTALL_DIR"
|
||||||
|
$STD uv venv .venv
|
||||||
|
$STD "$VENV_PYTHON" -m ensurepip --upgrade
|
||||||
|
$STD "$VENV_PYTHON" -m pip install --upgrade pip
|
||||||
|
$STD "$VENV_PYTHON" -m pip install jupyter
|
||||||
|
msg_ok "Migrated to uv and installed Jupyter"
|
||||||
|
else
|
||||||
|
msg_info "Updating Jupyter"
|
||||||
|
$STD "$VENV_PYTHON" -m pip install --upgrade pip
|
||||||
|
$STD "$VENV_PYTHON" -m pip install --upgrade jupyter
|
||||||
|
msg_ok "Jupyter updated"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "$SERVICE_FILE" && "$(grep ExecStart "$SERVICE_FILE")" != *".venv/bin/jupyter"* ]]; then
|
||||||
|
msg_info "Updating systemd service to use .venv"
|
||||||
|
cat <<EOF >"$SERVICE_FILE"
|
||||||
|
[Unit]
|
||||||
|
Description=Jupyter Notebook Server
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
WorkingDirectory=${INSTALL_DIR}
|
||||||
|
ExecStart=${VENV_JUPYTER} notebook --ip=0.0.0.0 --port=8888 --allow-root
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl daemon-reexec
|
||||||
|
systemctl restart jupyternotebook
|
||||||
|
msg_ok "Service updated and restarted"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
start
|
start
|
||||||
@ -39,4 +76,4 @@ description
|
|||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8888${CL}"
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8888${CL}"
|
||||||
|
|||||||
@ -6,7 +6,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
# Source: https://github.com/plankanban/planka
|
# Source: https://github.com/plankanban/planka
|
||||||
|
|
||||||
APP="PLANKA"
|
APP="PLANKA"
|
||||||
var_tags="${var_tags:-Arr}"
|
var_tags="${var_tags:-Todo,kanban}"
|
||||||
var_cpu="${var_cpu:-1}"
|
var_cpu="${var_cpu:-1}"
|
||||||
var_ram="${var_ram:-1024}"
|
var_ram="${var_ram:-1024}"
|
||||||
var_disk="${var_disk:-4}"
|
var_disk="${var_disk:-4}"
|
||||||
|
|||||||
2
frontend/public/json/argus.json
generated
2
frontend/public/json/argus.json
generated
@ -8,7 +8,7 @@
|
|||||||
"type": "ct",
|
"type": "ct",
|
||||||
"updateable": true,
|
"updateable": true,
|
||||||
"privileged": false,
|
"privileged": false,
|
||||||
"interface_port": 3000,
|
"interface_port": 8080,
|
||||||
"documentation": "https://release-argus.io/docs/overview/",
|
"documentation": "https://release-argus.io/docs/overview/",
|
||||||
"website": "https://release-argus.io/",
|
"website": "https://release-argus.io/",
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/argus.webp",
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/argus.webp",
|
||||||
|
|||||||
200
frontend/public/json/versions.json
generated
200
frontend/public/json/versions.json
generated
@ -1,13 +1,103 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "plexguide/Huntarr.io",
|
"name": "fallenbagel/jellyseerr",
|
||||||
"version": "8.1.3",
|
"version": "preview-dns-cache-manager",
|
||||||
"date": "2025-06-19T23:45:15Z"
|
"date": "2025-06-20T23:03:23Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "go-gitea/gitea",
|
"name": "go-gitea/gitea",
|
||||||
"version": "v1.24.1",
|
"version": "v1.24.2",
|
||||||
"date": "2025-06-19T19:38:29Z"
|
"date": "2025-06-20T20:37:55Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "coder/code-server",
|
||||||
|
"version": "v4.101.0",
|
||||||
|
"date": "2025-06-20T20:21:50Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "immich-app/immich",
|
||||||
|
"version": "v1.135.3",
|
||||||
|
"date": "2025-06-20T20:19:20Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "apache/tika",
|
||||||
|
"version": "3.2.1-rc1",
|
||||||
|
"date": "2025-06-20T19:41:10Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "VictoriaMetrics/VictoriaMetrics",
|
||||||
|
"version": "v1.24.0-victorialogs",
|
||||||
|
"date": "2025-06-20T19:31:31Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "homarr-labs/homarr",
|
||||||
|
"version": "v1.25.0",
|
||||||
|
"date": "2025-06-20T19:15:43Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "msgbyte/tianji",
|
||||||
|
"version": "v1.22.1",
|
||||||
|
"date": "2025-06-20T18:12:20Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mongodb/mongo",
|
||||||
|
"version": "r8.1.2-rc0",
|
||||||
|
"date": "2025-06-20T17:35:38Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "nzbgetcom/nzbget",
|
||||||
|
"version": "v25.0",
|
||||||
|
"date": "2025-05-12T09:12:04Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sonarr/Sonarr",
|
||||||
|
"version": "v4.0.15.2941",
|
||||||
|
"date": "2025-06-20T17:20:54Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "bunkerity/bunkerweb",
|
||||||
|
"version": "testing",
|
||||||
|
"date": "2025-06-16T18:10:42Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "plexguide/Huntarr.io",
|
||||||
|
"version": "8.1.6",
|
||||||
|
"date": "2025-06-20T14:50:59Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "docker/compose",
|
||||||
|
"version": "v2.37.2",
|
||||||
|
"date": "2025-06-20T13:25:03Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "zabbix/zabbix",
|
||||||
|
"version": "7.2.9",
|
||||||
|
"date": "2025-06-20T10:58:45Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "syncthing/syncthing",
|
||||||
|
"version": "2.0.0-rc.19",
|
||||||
|
"date": "2025-06-02T17:56:25Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "benzino77/tasmocompiler",
|
||||||
|
"version": "v12.7.0",
|
||||||
|
"date": "2025-06-20T08:31:16Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jackett/Jackett",
|
||||||
|
"version": "v0.22.2032",
|
||||||
|
"date": "2025-06-20T05:57:27Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "arunavo4/gitea-mirror",
|
||||||
|
"version": "v2.16.3",
|
||||||
|
"date": "2025-06-20T05:49:06Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "firefly-iii/firefly-iii",
|
||||||
|
"version": "v6.2.18",
|
||||||
|
"date": "2025-06-20T04:45:37Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "paperless-ngx/paperless-ngx",
|
"name": "paperless-ngx/paperless-ngx",
|
||||||
@ -20,20 +110,15 @@
|
|||||||
"date": "2025-06-19T18:30:11Z"
|
"date": "2025-06-19T18:30:11Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "immich-app/immich",
|
"name": "keycloak/keycloak",
|
||||||
"version": "v1.135.1",
|
"version": "26.2.5",
|
||||||
"date": "2025-06-19T17:55:06Z"
|
"date": "2025-05-28T06:49:43Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "rclone/rclone",
|
"name": "rclone/rclone",
|
||||||
"version": "v1.70.1",
|
"version": "v1.70.1",
|
||||||
"date": "2025-06-19T13:19:02Z"
|
"date": "2025-06-19T13:19:02Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "fallenbagel/jellyseerr",
|
|
||||||
"version": "preview-dns-cache-manager",
|
|
||||||
"date": "2025-06-19T12:05:10Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "icereed/paperless-gpt",
|
"name": "icereed/paperless-gpt",
|
||||||
"version": "v0.21.0",
|
"version": "v0.21.0",
|
||||||
@ -59,11 +144,6 @@
|
|||||||
"version": "8.2-m01-int2",
|
"version": "8.2-m01-int2",
|
||||||
"date": "2025-06-12T08:52:10Z"
|
"date": "2025-06-12T08:52:10Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Jackett/Jackett",
|
|
||||||
"version": "v0.22.2029",
|
|
||||||
"date": "2025-06-19T05:56:19Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "prometheus-pve/prometheus-pve-exporter",
|
"name": "prometheus-pve/prometheus-pve-exporter",
|
||||||
"version": "v3.5.5",
|
"version": "v3.5.5",
|
||||||
@ -79,21 +159,11 @@
|
|||||||
"version": "v0.35.0",
|
"version": "v0.35.0",
|
||||||
"date": "2025-05-21T18:00:32Z"
|
"date": "2025-05-21T18:00:32Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "keycloak/keycloak",
|
|
||||||
"version": "26.2.5",
|
|
||||||
"date": "2025-05-28T06:49:43Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "pterodactyl/panel",
|
"name": "pterodactyl/panel",
|
||||||
"version": "v1.11.11",
|
"version": "v1.11.11",
|
||||||
"date": "2025-06-18T18:04:50Z"
|
"date": "2025-06-18T18:04:50Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "msgbyte/tianji",
|
|
||||||
"version": "v1.22.0",
|
|
||||||
"date": "2025-06-18T16:21:38Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "ollama/ollama",
|
"name": "ollama/ollama",
|
||||||
"version": "v0.9.2",
|
"version": "v0.9.2",
|
||||||
@ -114,11 +184,6 @@
|
|||||||
"version": "5.0.0.M3",
|
"version": "5.0.0.M3",
|
||||||
"date": "2025-06-18T14:18:12Z"
|
"date": "2025-06-18T14:18:12Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "zabbix/zabbix",
|
|
||||||
"version": "7.2.8",
|
|
||||||
"date": "2025-06-18T13:46:00Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Bubka/2FAuth",
|
"name": "Bubka/2FAuth",
|
||||||
"version": "v5.6.0",
|
"version": "v5.6.0",
|
||||||
@ -169,11 +234,6 @@
|
|||||||
"version": "jenkins-2.515",
|
"version": "jenkins-2.515",
|
||||||
"date": "2025-06-17T19:17:56Z"
|
"date": "2025-06-17T19:17:56Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "coder/code-server",
|
|
||||||
"version": "v4.100.3",
|
|
||||||
"date": "2025-06-03T21:06:41Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "HabitRPG/habitica",
|
"name": "HabitRPG/habitica",
|
||||||
"version": "v5.36.6",
|
"version": "v5.36.6",
|
||||||
@ -204,11 +264,6 @@
|
|||||||
"version": "4.5.1",
|
"version": "4.5.1",
|
||||||
"date": "2025-04-11T09:57:47Z"
|
"date": "2025-04-11T09:57:47Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "arunavo4/gitea-mirror",
|
|
||||||
"version": "v2.16.2",
|
|
||||||
"date": "2025-06-17T11:59:34Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "crowdsecurity/crowdsec",
|
"name": "crowdsecurity/crowdsec",
|
||||||
"version": "v1.6.9",
|
"version": "v1.6.9",
|
||||||
@ -239,11 +294,6 @@
|
|||||||
"version": "2.36.1",
|
"version": "2.36.1",
|
||||||
"date": "2025-06-16T19:20:54Z"
|
"date": "2025-06-16T19:20:54Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "bunkerity/bunkerweb",
|
|
||||||
"version": "testing",
|
|
||||||
"date": "2025-06-16T18:10:42Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "goauthentik/authentik",
|
"name": "goauthentik/authentik",
|
||||||
"version": "version/2025.6.2",
|
"version": "version/2025.6.2",
|
||||||
@ -251,8 +301,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "runtipi/runtipi",
|
"name": "runtipi/runtipi",
|
||||||
"version": "v4.2.1",
|
"version": "nightly",
|
||||||
"date": "2025-06-03T20:04:28Z"
|
"date": "2025-06-16T17:35:17Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "emqx/emqx",
|
"name": "emqx/emqx",
|
||||||
@ -289,11 +339,6 @@
|
|||||||
"version": "v1.18.3",
|
"version": "v1.18.3",
|
||||||
"date": "2025-06-16T07:03:46Z"
|
"date": "2025-06-16T07:03:46Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "firefly-iii/firefly-iii",
|
|
||||||
"version": "v6.2.17",
|
|
||||||
"date": "2025-06-11T12:07:38Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "jellyfin/jellyfin",
|
"name": "jellyfin/jellyfin",
|
||||||
"version": "v10.10.7",
|
"version": "v10.10.7",
|
||||||
@ -319,11 +364,6 @@
|
|||||||
"version": "v3.1.9",
|
"version": "v3.1.9",
|
||||||
"date": "2025-03-01T02:24:33Z"
|
"date": "2025-03-01T02:24:33Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "syncthing/syncthing",
|
|
||||||
"version": "2.0.0-rc.19",
|
|
||||||
"date": "2025-06-02T17:56:25Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Prowlarr/Prowlarr",
|
"name": "Prowlarr/Prowlarr",
|
||||||
"version": "v1.37.0.5076",
|
"version": "v1.37.0.5076",
|
||||||
@ -359,11 +399,6 @@
|
|||||||
"version": "v2.25.1",
|
"version": "v2.25.1",
|
||||||
"date": "2025-06-14T23:32:15Z"
|
"date": "2025-06-14T23:32:15Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "nzbgetcom/nzbget",
|
|
||||||
"version": "v25.0",
|
|
||||||
"date": "2025-05-12T09:12:04Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "theonedev/onedev",
|
"name": "theonedev/onedev",
|
||||||
"version": "v11.11.0",
|
"version": "v11.11.0",
|
||||||
@ -384,11 +419,6 @@
|
|||||||
"version": "2025.6.1",
|
"version": "2025.6.1",
|
||||||
"date": "2025-06-13T20:16:18Z"
|
"date": "2025-06-13T20:16:18Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "homarr-labs/homarr",
|
|
||||||
"version": "v1.24.0",
|
|
||||||
"date": "2025-06-13T19:15:36Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Luligu/matterbridge",
|
"name": "Luligu/matterbridge",
|
||||||
"version": "3.0.6",
|
"version": "3.0.6",
|
||||||
@ -419,11 +449,6 @@
|
|||||||
"version": "v2.3.0p34",
|
"version": "v2.3.0p34",
|
||||||
"date": "2025-06-12T12:15:44Z"
|
"date": "2025-06-12T12:15:44Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "docker/compose",
|
|
||||||
"version": "v2.37.1",
|
|
||||||
"date": "2025-06-12T09:00:21Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "zitadel/zitadel",
|
"name": "zitadel/zitadel",
|
||||||
"version": "v3.3.0",
|
"version": "v3.3.0",
|
||||||
@ -479,21 +504,11 @@
|
|||||||
"version": "1.11.2",
|
"version": "1.11.2",
|
||||||
"date": "2025-06-10T11:07:14Z"
|
"date": "2025-06-10T11:07:14Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "VictoriaMetrics/VictoriaMetrics",
|
|
||||||
"version": "v1.110.11",
|
|
||||||
"date": "2025-06-10T10:00:25Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "glanceapp/glance",
|
"name": "glanceapp/glance",
|
||||||
"version": "v0.8.4",
|
"version": "v0.8.4",
|
||||||
"date": "2025-06-10T07:57:14Z"
|
"date": "2025-06-10T07:57:14Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Sonarr/Sonarr",
|
|
||||||
"version": "v4.0.14.2939",
|
|
||||||
"date": "2025-03-17T19:12:37Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "tailscale/tailscale",
|
"name": "tailscale/tailscale",
|
||||||
"version": "v1.84.2",
|
"version": "v1.84.2",
|
||||||
@ -694,11 +709,6 @@
|
|||||||
"version": "cassandra-4.0.18",
|
"version": "cassandra-4.0.18",
|
||||||
"date": "2025-05-28T21:45:55Z"
|
"date": "2025-05-28T21:45:55Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "mongodb/mongo",
|
|
||||||
"version": "r6.0.24",
|
|
||||||
"date": "2025-05-28T21:25:03Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Athou/commafeed",
|
"name": "Athou/commafeed",
|
||||||
"version": "5.10.0",
|
"version": "5.10.0",
|
||||||
@ -764,11 +774,6 @@
|
|||||||
"version": "0.5",
|
"version": "0.5",
|
||||||
"date": "2025-05-21T20:19:14Z"
|
"date": "2025-05-21T20:19:14Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "apache/tika",
|
|
||||||
"version": "3.2.0-rc2",
|
|
||||||
"date": "2025-05-21T20:09:07Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Stirling-Tools/Stirling-PDF",
|
"name": "Stirling-Tools/Stirling-PDF",
|
||||||
"version": "v0.46.2",
|
"version": "v0.46.2",
|
||||||
@ -989,11 +994,6 @@
|
|||||||
"version": "v2.10.0",
|
"version": "v2.10.0",
|
||||||
"date": "2025-04-18T20:46:28Z"
|
"date": "2025-04-18T20:46:28Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "benzino77/tasmocompiler",
|
|
||||||
"version": "v12.6.1",
|
|
||||||
"date": "2025-04-17T17:35:02Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "IceWhaleTech/CasaOS",
|
"name": "IceWhaleTech/CasaOS",
|
||||||
"version": "v0.4.15",
|
"version": "v0.4.15",
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Copyright (c) 2021-2025 tteck
|
# Copyright (c) 2021-2025 tteck
|
||||||
# Author: tteck
|
# Author: MickLesk (CanbiZ)
|
||||||
# Co-Author: MickLesk (Canbiz)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://github.com/seanmorley15/AdventureLog
|
# Source: https://github.com/seanmorley15/AdventureLog
|
||||||
|
|
||||||
@ -18,13 +17,12 @@ msg_info "Installing Dependencies"
|
|||||||
$STD apt-get install -y \
|
$STD apt-get install -y \
|
||||||
gdal-bin \
|
gdal-bin \
|
||||||
libgdal-dev \
|
libgdal-dev \
|
||||||
git \
|
git
|
||||||
python3-venv \
|
|
||||||
python3-pip
|
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
NODE_VERSION="22" NODE_MODULE="pnpm@latest" setup_nodejs
|
PYTHON_VERSION="3.12" setup_uv
|
||||||
PG_VERSION="16" PG_MODULES="postgis" setup_postgresql
|
NODE_VERSION="22" NODE_MODULE="pnpm@latest" install_node_and_modules
|
||||||
|
PG_VERSION="16" PG_MODULES="postgis" install_postgresql
|
||||||
|
|
||||||
msg_info "Set up PostgreSQL Database"
|
msg_info "Set up PostgreSQL Database"
|
||||||
DB_NAME="adventurelog_db"
|
DB_NAME="adventurelog_db"
|
||||||
@ -46,15 +44,12 @@ $STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC';"
|
|||||||
} >>~/adventurelog.creds
|
} >>~/adventurelog.creds
|
||||||
msg_ok "Set up PostgreSQL"
|
msg_ok "Set up PostgreSQL"
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "adventurelog" "seanmorley15/adventurelog"
|
||||||
|
|
||||||
msg_info "Installing AdventureLog (Patience)"
|
msg_info "Installing AdventureLog (Patience)"
|
||||||
DJANGO_ADMIN_USER="djangoadmin"
|
DJANGO_ADMIN_USER="djangoadmin"
|
||||||
DJANGO_ADMIN_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)"
|
DJANGO_ADMIN_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)"
|
||||||
LOCAL_IP="$(hostname -I | awk '{print $1}')"
|
LOCAL_IP="$(hostname -I | awk '{print $1}')"
|
||||||
cd /opt
|
|
||||||
RELEASE=$(curl -fsSL https://api.github.com/repos/seanmorley15/AdventureLog/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
|
||||||
curl -fsSL "https://github.com/seanmorley15/AdventureLog/archive/refs/tags/v${RELEASE}.zip" -o "v${RELEASE}.zip"
|
|
||||||
$STD unzip v${RELEASE}.zip
|
|
||||||
mv AdventureLog-${RELEASE} /opt/adventurelog
|
|
||||||
cat <<EOF >/opt/adventurelog/backend/server/.env
|
cat <<EOF >/opt/adventurelog/backend/server/.env
|
||||||
PGHOST='localhost'
|
PGHOST='localhost'
|
||||||
PGDATABASE='${DB_NAME}'
|
PGDATABASE='${DB_NAME}'
|
||||||
@ -79,11 +74,13 @@ DISABLE_REGISTRATION=False
|
|||||||
EOF
|
EOF
|
||||||
cd /opt/adventurelog/backend/server
|
cd /opt/adventurelog/backend/server
|
||||||
mkdir -p /opt/adventurelog/backend/server/media
|
mkdir -p /opt/adventurelog/backend/server/media
|
||||||
$STD pip install --upgrade pip
|
$STD uv venv /opt/adventurelog/backend/server/.venv
|
||||||
$STD pip install -r requirements.txt
|
$STD /opt/adventurelog/backend/server/.venv/bin/python -m ensurepip --upgrade
|
||||||
$STD python3 manage.py collectstatic --noinput
|
$STD /opt/adventurelog/backend/server/.venv/bin/python -m pip install --upgrade pip
|
||||||
$STD python3 manage.py migrate
|
$STD /opt/adventurelog/backend/server/.venv/bin/python -m pip install -r requirements.txt
|
||||||
$STD python3 manage.py download-countries
|
$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 <<EOF >/opt/adventurelog/frontend/.env
|
cat <<EOF >/opt/adventurelog/frontend/.env
|
||||||
PUBLIC_SERVER_URL=http://$LOCAL_IP:8000
|
PUBLIC_SERVER_URL=http://$LOCAL_IP:8000
|
||||||
BODY_SIZE_LIMIT=Infinity
|
BODY_SIZE_LIMIT=Infinity
|
||||||
@ -96,7 +93,8 @@ echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt"
|
|||||||
msg_ok "Installed AdventureLog"
|
msg_ok "Installed AdventureLog"
|
||||||
|
|
||||||
msg_info "Setting up Django Admin"
|
msg_info "Setting up Django Admin"
|
||||||
$STD python3 /opt/adventurelog/backend/server/manage.py shell <<EOF
|
cd /opt/adventurelog/backend/server
|
||||||
|
$STD .venv/bin/python -m manage shell <<EOF
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
UserModel = get_user_model()
|
UserModel = get_user_model()
|
||||||
user = UserModel.objects.create_user('$DJANGO_ADMIN_USER', password='$DJANGO_ADMIN_PASS')
|
user = UserModel.objects.create_user('$DJANGO_ADMIN_USER', password='$DJANGO_ADMIN_PASS')
|
||||||
@ -120,7 +118,7 @@ After=network.target postgresql.service
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
WorkingDirectory=/opt/adventurelog/backend/server
|
WorkingDirectory=/opt/adventurelog/backend/server
|
||||||
ExecStart=python3 manage.py runserver 0.0.0.0:8000
|
ExecStart=/opt/adventurelog/backend/server/.venv/bin/python -m manage runserver 0.0.0.0:8000
|
||||||
Restart=always
|
Restart=always
|
||||||
EnvironmentFile=/opt/adventurelog/backend/server/.env
|
EnvironmentFile=/opt/adventurelog/backend/server/.env
|
||||||
|
|
||||||
|
|||||||
@ -273,11 +273,6 @@ rm -rf "$SOURCE"/build
|
|||||||
} >~/.immich_library_revisions
|
} >~/.immich_library_revisions
|
||||||
msg_ok "Custom Photo-processing Library Compiled"
|
msg_ok "Custom Photo-processing Library Compiled"
|
||||||
|
|
||||||
msg_info "Installing ${APPLICATION} (more patience please)"
|
|
||||||
tmp_file=$(mktemp)
|
|
||||||
RELEASE=$(curl -fsSL https://api.github.com/repos/immich-app/immich/releases?per_page=1 | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
|
||||||
curl -fsSL "https://github.com/immich-app/immich/archive/refs/tags/v${RELEASE}.zip" -o "$tmp_file"
|
|
||||||
unzip -q "$tmp_file"
|
|
||||||
INSTALL_DIR="/opt/${APPLICATION}"
|
INSTALL_DIR="/opt/${APPLICATION}"
|
||||||
UPLOAD_DIR="${INSTALL_DIR}/upload"
|
UPLOAD_DIR="${INSTALL_DIR}/upload"
|
||||||
SRC_DIR="${INSTALL_DIR}/source"
|
SRC_DIR="${INSTALL_DIR}/source"
|
||||||
@ -285,9 +280,12 @@ APP_DIR="${INSTALL_DIR}/app"
|
|||||||
ML_DIR="${APP_DIR}/machine-learning"
|
ML_DIR="${APP_DIR}/machine-learning"
|
||||||
GEO_DIR="${INSTALL_DIR}/geodata"
|
GEO_DIR="${INSTALL_DIR}/geodata"
|
||||||
mkdir -p "$INSTALL_DIR"
|
mkdir -p "$INSTALL_DIR"
|
||||||
mv "$APPLICATION-$RELEASE"/ "$SRC_DIR"
|
|
||||||
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${ML_DIR}","${INSTALL_DIR}"/cache}
|
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${ML_DIR}","${INSTALL_DIR}"/cache}
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "immich" "immich-app/immich" "tarball" "v1.135.0" "$SRC_DIR"
|
||||||
|
|
||||||
|
msg_info "Installing ${APPLICATION} (more patience please)"
|
||||||
|
|
||||||
cd "$SRC_DIR"/server
|
cd "$SRC_DIR"/server
|
||||||
$STD npm install -g node-gyp node-pre-gyp
|
$STD npm install -g node-gyp node-pre-gyp
|
||||||
$STD npm ci
|
$STD npm ci
|
||||||
@ -358,7 +356,6 @@ msg_ok "Installed GeoNames data"
|
|||||||
|
|
||||||
mkdir -p /var/log/immich
|
mkdir -p /var/log/immich
|
||||||
touch /var/log/immich/{web.log,ml.log}
|
touch /var/log/immich/{web.log,ml.log}
|
||||||
echo "$RELEASE" >/opt/"${APPLICATION}"_version.txt
|
|
||||||
msg_ok "Installed ${APPLICATION}"
|
msg_ok "Installed ${APPLICATION}"
|
||||||
|
|
||||||
msg_info "Creating user, env file, scripts & services"
|
msg_info "Creating user, env file, scripts & services"
|
||||||
@ -450,7 +447,6 @@ motd_ssh
|
|||||||
customize
|
customize
|
||||||
|
|
||||||
msg_info "Cleaning up"
|
msg_info "Cleaning up"
|
||||||
rm -f "$tmp_file"
|
|
||||||
$STD apt-get -y autoremove
|
$STD apt-get -y autoremove
|
||||||
$STD apt-get -y autoclean
|
$STD apt-get -y autoclean
|
||||||
msg_ok "Cleaned"
|
msg_ok "Cleaned"
|
||||||
|
|||||||
@ -13,15 +13,19 @@ setting_up_container
|
|||||||
network_check
|
network_check
|
||||||
update_os
|
update_os
|
||||||
|
|
||||||
msg_info "Installing Dependencies"
|
PYTHON_VERSION="3.12" setup_uv
|
||||||
$STD apt-get install -y \
|
|
||||||
python3 \
|
|
||||||
python3-pip
|
|
||||||
msg_ok "Installed Dependencies"
|
|
||||||
|
|
||||||
msg_info "Setting up Jupyter Notebook"
|
msg_info "Installing Jupyter"
|
||||||
$STD pip3 install jupyter
|
mkdir -p /opt/jupyter
|
||||||
msg_ok "Setup Jupyter Notebook"
|
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
|
||||||
|
ln -s /opt/jupyter/.venv/bin/jupyter /usr/local/bin/jupyter
|
||||||
|
ln -s /opt/jupyter/.venv/bin/jupyter-lab /usr/local/bin/jupyter-lab
|
||||||
|
ln -s /opt/jupyter/.venv/bin/jupyter-notebook /usr/local/bin/jupyter-notebook
|
||||||
|
msg_ok "Installed Jupyter"
|
||||||
|
|
||||||
msg_info "Creating Service"
|
msg_info "Creating Service"
|
||||||
cat <<EOF >/etc/systemd/system/jupyternotebook.service
|
cat <<EOF >/etc/systemd/system/jupyternotebook.service
|
||||||
@ -31,7 +35,8 @@ After=network.target
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
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
|
Restart=always
|
||||||
RestartSec=10
|
RestartSec=10
|
||||||
|
|
||||||
@ -39,6 +44,7 @@ RestartSec=10
|
|||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
systemctl enable -q --now jupyternotebook
|
systemctl enable -q --now jupyternotebook
|
||||||
|
msg_ok "Created Service"
|
||||||
|
|
||||||
motd_ssh
|
motd_ssh
|
||||||
customize
|
customize
|
||||||
|
|||||||
@ -26,7 +26,7 @@ PG_VERSION="16" setup_postgresql
|
|||||||
msg_info "Setting up PostgreSQL Database"
|
msg_info "Setting up PostgreSQL Database"
|
||||||
DB_NAME=planka
|
DB_NAME=planka
|
||||||
DB_USER=planka
|
DB_USER=planka
|
||||||
DB_PASS="$(openssl rand -base64 18 | cut -c1-13)"
|
DB_PASS=$(openssl rand -base64 16 | tr -d '/+=')
|
||||||
$STD sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';"
|
$STD sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';"
|
||||||
$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER ENCODING 'UTF8' TEMPLATE template0;"
|
$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER ENCODING 'UTF8' TEMPLATE template0;"
|
||||||
$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8';"
|
$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8';"
|
||||||
|
|||||||
@ -1,52 +1,13 @@
|
|||||||
# Copyright (c) 2021-2025 tteck
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
# Author: tteck (tteckster)
|
# Author: tteck (tteckster)
|
||||||
# Co-Author: MickLesk
|
# Co-Author: MickLesk
|
||||||
# License: MIT
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
|
|
||||||
# This function sets color variables for formatting output in the terminal
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
color() {
|
apk update && apk add curl >/dev/null 2>&1
|
||||||
# Colors
|
fi
|
||||||
YW=$(echo "\033[33m")
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||||
BL=$(echo "\033[36m")
|
load_functions
|
||||||
RD=$(echo "\033[01;31m")
|
|
||||||
GN=$(echo "\033[1;92m")
|
|
||||||
|
|
||||||
# Formatting
|
|
||||||
CL=$(echo "\033[m")
|
|
||||||
BFR="\\r\\033[K"
|
|
||||||
BOLD=$(echo "\033[1m")
|
|
||||||
TAB=" "
|
|
||||||
TAB3=" "
|
|
||||||
|
|
||||||
# System
|
|
||||||
RETRY_NUM=10
|
|
||||||
RETRY_EVERY=3
|
|
||||||
i=$RETRY_NUM
|
|
||||||
|
|
||||||
# Icons
|
|
||||||
CM="${TAB}✔️${TAB}${CL}"
|
|
||||||
CROSS="${TAB}✖️${TAB}${CL}"
|
|
||||||
INFO="${TAB}💡${TAB}${CL}"
|
|
||||||
NETWORK="${TAB}📡${TAB}${CL}"
|
|
||||||
OS="${TAB}🖥️${TAB}${CL}"
|
|
||||||
HOSTNAME="${TAB}🏠${TAB}${CL}"
|
|
||||||
GATEWAY="${TAB}🌐${TAB}${CL}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to set STD mode based on verbosity
|
|
||||||
set_std_mode() {
|
|
||||||
if [ "$VERBOSE" = "yes" ]; then
|
|
||||||
STD=""
|
|
||||||
else
|
|
||||||
STD="silent"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Silent execution function
|
|
||||||
silent() {
|
|
||||||
"$@" >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function enables IPv6 if it's not disabled and sets verbose mode
|
# This function enables IPv6 if it's not disabled and sets verbose mode
|
||||||
verb_ip6() {
|
verb_ip6() {
|
||||||
@ -74,33 +35,15 @@ error_handler() {
|
|||||||
echo -e "\n$error_message\n"
|
echo -e "\n$error_message\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
# This function displays an informational message with a yellow color.
|
|
||||||
msg_info() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -ne " ${TAB}${YW}${msg}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function displays a success message with a green color.
|
|
||||||
msg_ok() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function displays a error message with a red color.
|
|
||||||
msg_error() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function sets up the Container OS by generating the locale, setting the timezone, and checking the network connection
|
# This function sets up the Container OS by generating the locale, setting the timezone, and checking the network connection
|
||||||
setting_up_container() {
|
setting_up_container() {
|
||||||
msg_info "Setting up Container OS"
|
msg_info "Setting up Container OS"
|
||||||
while [ "$i" -gt 0 ]; do
|
while [ $i -gt 0 ]; do
|
||||||
if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" != "" ]; then
|
if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" != "" ]; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
echo 1>&2 -en "${CROSS}${RD} No Network! "
|
echo 1>&2 -en "${CROSS}${RD} No Network! "
|
||||||
sleep "$RETRY_EVERY"
|
sleep $RETRY_EVERY
|
||||||
i=$((i - 1))
|
i=$((i - 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
@ -149,10 +92,9 @@ update_os() {
|
|||||||
|
|
||||||
# This function modifies the message of the day (motd) and SSH settings
|
# This function modifies the message of the day (motd) and SSH settings
|
||||||
motd_ssh() {
|
motd_ssh() {
|
||||||
# Set terminal to 256-color mode
|
|
||||||
echo "export TERM='xterm-256color'" >>/root/.bashrc
|
echo "export TERM='xterm-256color'" >>/root/.bashrc
|
||||||
IP=$(ip -4 addr show eth0 | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
IP=$(ip -4 addr show eth0 | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||||
# Get OS information
|
|
||||||
if [ -f "/etc/os-release" ]; then
|
if [ -f "/etc/os-release" ]; then
|
||||||
OS_NAME=$(grep ^NAME /etc/os-release | cut -d= -f2 | tr -d '"')
|
OS_NAME=$(grep ^NAME /etc/os-release | cut -d= -f2 | tr -d '"')
|
||||||
OS_VERSION=$(grep ^VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"')
|
OS_VERSION=$(grep ^VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"')
|
||||||
@ -213,6 +155,6 @@ EOF
|
|||||||
msg_ok "Customized Container"
|
msg_ok "Customized Container"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "bash -c \"\$(curl -fsSL https://github.com/community-scripts/ProxmoxVE/raw/main/ct/${app}.sh)\"" >/usr/bin/update
|
echo "bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/${app}.sh)\"" >/usr/bin/update
|
||||||
chmod +x /usr/bin/update
|
chmod +x /usr/bin/update
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
post_to_api() {
|
post_to_api() {
|
||||||
|
|
||||||
if ! command -v curl &> /dev/null; then
|
if ! command -v curl &>/dev/null; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -20,7 +20,8 @@ post_to_api() {
|
|||||||
local pve_version="not found"
|
local pve_version="not found"
|
||||||
pve_version=$(pveversion | awk -F'[/ ]' '{print $2}')
|
pve_version=$(pveversion | awk -F'[/ ]' '{print $2}')
|
||||||
|
|
||||||
JSON_PAYLOAD=$(cat <<EOF
|
JSON_PAYLOAD=$(
|
||||||
|
cat <<EOF
|
||||||
{
|
{
|
||||||
"ct_type": $CT_TYPE,
|
"ct_type": $CT_TYPE,
|
||||||
"type":"lxc",
|
"type":"lxc",
|
||||||
@ -37,12 +38,12 @@ post_to_api() {
|
|||||||
"random_id": "$RANDOM_UUID"
|
"random_id": "$RANDOM_UUID"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ "$DIAGNOSTICS" == "yes" ]]; then
|
if [[ "$DIAGNOSTICS" == "yes" ]]; then
|
||||||
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
|
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "$JSON_PAYLOAD") || true
|
-d "$JSON_PAYLOAD") || true
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ post_to_api_vm() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
DIAGNOSTICS=$(grep -i "^DIAGNOSTICS=" /usr/local/community-scripts/diagnostics | awk -F'=' '{print $2}')
|
DIAGNOSTICS=$(grep -i "^DIAGNOSTICS=" /usr/local/community-scripts/diagnostics | awk -F'=' '{print $2}')
|
||||||
if ! command -v curl &> /dev/null; then
|
if ! command -v curl &>/dev/null; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -70,7 +71,8 @@ post_to_api_vm() {
|
|||||||
|
|
||||||
DISK_SIZE_API=${DISK_SIZE%G}
|
DISK_SIZE_API=${DISK_SIZE%G}
|
||||||
|
|
||||||
JSON_PAYLOAD=$(cat <<EOF
|
JSON_PAYLOAD=$(
|
||||||
|
cat <<EOF
|
||||||
{
|
{
|
||||||
"ct_type": 2,
|
"ct_type": 2,
|
||||||
"type":"vm",
|
"type":"vm",
|
||||||
@ -87,42 +89,43 @@ post_to_api_vm() {
|
|||||||
"random_id": "$RANDOM_UUID"
|
"random_id": "$RANDOM_UUID"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ "$DIAGNOSTICS" == "yes" ]]; then
|
if [[ "$DIAGNOSTICS" == "yes" ]]; then
|
||||||
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
|
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "$JSON_PAYLOAD") || true
|
-d "$JSON_PAYLOAD") || true
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
POST_UPDATE_DONE=false
|
POST_UPDATE_DONE=false
|
||||||
post_update_to_api() {
|
post_update_to_api() {
|
||||||
|
|
||||||
if ! command -v curl &> /dev/null; then
|
if ! command -v curl &>/dev/null; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$POST_UPDATE_DONE" = true ]; then
|
if [ "$POST_UPDATE_DONE" = true ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
local API_URL="http://api.community-scripts.org/upload/updatestatus"
|
local API_URL="http://api.community-scripts.org/upload/updatestatus"
|
||||||
local status="${1:-failed}"
|
local status="${1:-failed}"
|
||||||
local error="${2:-No error message}"
|
local error="${2:-No error message}"
|
||||||
|
|
||||||
JSON_PAYLOAD=$(cat <<EOF
|
JSON_PAYLOAD=$(
|
||||||
|
cat <<EOF
|
||||||
{
|
{
|
||||||
"status": "$status",
|
"status": "$status",
|
||||||
"error": "$error",
|
"error": "$error",
|
||||||
"random_id": "$RANDOM_UUID"
|
"random_id": "$RANDOM_UUID"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
|
|
||||||
if [[ "$DIAGNOSTICS" == "yes" ]]; then
|
if [[ "$DIAGNOSTICS" == "yes" ]]; then
|
||||||
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
|
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "$JSON_PAYLOAD") || true
|
-d "$JSON_PAYLOAD") || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
POST_UPDATE_DONE=true
|
POST_UPDATE_DONE=true
|
||||||
|
|||||||
290
misc/build.func
290
misc/build.func
@ -12,56 +12,20 @@ variables() {
|
|||||||
DIAGNOSTICS="yes" # sets the DIAGNOSTICS variable to "yes", used for the API call.
|
DIAGNOSTICS="yes" # sets the DIAGNOSTICS variable to "yes", used for the API call.
|
||||||
METHOD="default" # sets the METHOD variable to "default", used for the API call.
|
METHOD="default" # sets the METHOD variable to "default", used for the API call.
|
||||||
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" # generates a random UUID and sets it to the RANDOM_UUID variable.
|
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" # generates a random UUID and sets it to the RANDOM_UUID variable.
|
||||||
|
CT_TYPE=${var_unprivileged:-$CT_TYPE}
|
||||||
}
|
}
|
||||||
|
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
|
||||||
|
|
||||||
# This function sets various color variables using ANSI escape codes for formatting text in the terminal.
|
if command -v curl >/dev/null 2>&1; then
|
||||||
color() {
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||||
# Colors
|
load_functions
|
||||||
YW=$(echo "\033[33m")
|
#echo "(build.func) Loaded core.func via curl"
|
||||||
YWB=$(echo "\033[93m")
|
elif command -v wget >/dev/null 2>&1; then
|
||||||
BL=$(echo "\033[36m")
|
source <(wget -qO- https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||||
RD=$(echo "\033[01;31m")
|
load_functions
|
||||||
BGN=$(echo "\033[4;92m")
|
#echo "(build.func) Loaded core.func via wget"
|
||||||
GN=$(echo "\033[1;92m")
|
fi
|
||||||
DGN=$(echo "\033[32m")
|
|
||||||
|
|
||||||
# Formatting
|
|
||||||
CL=$(echo "\033[m")
|
|
||||||
BOLD=$(echo "\033[1m")
|
|
||||||
HOLD=" "
|
|
||||||
TAB=" "
|
|
||||||
TAB3=" "
|
|
||||||
|
|
||||||
# Icons
|
|
||||||
CM="${TAB}✔️${TAB}"
|
|
||||||
CROSS="${TAB}✖️${TAB}"
|
|
||||||
INFO="${TAB}💡${TAB}${CL}"
|
|
||||||
OS="${TAB}🖥️${TAB}${CL}"
|
|
||||||
OSVERSION="${TAB}🌟${TAB}${CL}"
|
|
||||||
CONTAINERTYPE="${TAB}📦${TAB}${CL}"
|
|
||||||
DISKSIZE="${TAB}💾${TAB}${CL}"
|
|
||||||
CPUCORE="${TAB}🧠${TAB}${CL}"
|
|
||||||
RAMSIZE="${TAB}🛠️${TAB}${CL}"
|
|
||||||
SEARCH="${TAB}🔍${TAB}${CL}"
|
|
||||||
VERBOSE_CROPPED="🔍${TAB}"
|
|
||||||
VERIFYPW="${TAB}🔐${TAB}${CL}"
|
|
||||||
CONTAINERID="${TAB}🆔${TAB}${CL}"
|
|
||||||
HOSTNAME="${TAB}🏠${TAB}${CL}"
|
|
||||||
BRIDGE="${TAB}🌉${TAB}${CL}"
|
|
||||||
NETWORK="${TAB}📡${TAB}${CL}"
|
|
||||||
GATEWAY="${TAB}🌐${TAB}${CL}"
|
|
||||||
DISABLEIPV6="${TAB}🚫${TAB}${CL}"
|
|
||||||
DEFAULT="${TAB}⚙️${TAB}${CL}"
|
|
||||||
MACADDRESS="${TAB}🔗${TAB}${CL}"
|
|
||||||
VLANTAG="${TAB}🏷️${TAB}${CL}"
|
|
||||||
ROOTSSH="${TAB}🔑${TAB}${CL}"
|
|
||||||
CREATING="${TAB}🚀${TAB}${CL}"
|
|
||||||
ADVANCED="${TAB}🧩${TAB}${CL}"
|
|
||||||
FUSE="${TAB}🗂️${TAB}${CL}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function enables error handling in the script by setting options and defining a trap for the ERR signal.
|
# This function enables error handling in the script by setting options and defining a trap for the ERR signal.
|
||||||
catch_errors() {
|
catch_errors() {
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
@ -71,7 +35,6 @@ 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.
|
# 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() {
|
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/main/misc/api.func)
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p "$SPINNER_PID" >/dev/null; then kill "$SPINNER_PID" >/dev/null; fi
|
|
||||||
printf "\e[?25h"
|
printf "\e[?25h"
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
@ -81,78 +44,6 @@ error_handler() {
|
|||||||
echo -e "\n$error_message\n"
|
echo -e "\n$error_message\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
# This function displays an informational message with logging support.
|
|
||||||
declare -A MSG_INFO_SHOWN
|
|
||||||
SPINNER_ACTIVE=0
|
|
||||||
SPINNER_PID=""
|
|
||||||
SPINNER_MSG=""
|
|
||||||
|
|
||||||
trap 'stop_spinner' EXIT INT TERM HUP
|
|
||||||
|
|
||||||
start_spinner() {
|
|
||||||
local msg="$1"
|
|
||||||
local frames=(⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏)
|
|
||||||
local spin_i=0
|
|
||||||
local interval=0.1
|
|
||||||
|
|
||||||
SPINNER_MSG="$msg"
|
|
||||||
printf "\r\e[2K" >&2
|
|
||||||
|
|
||||||
{
|
|
||||||
while [[ "$SPINNER_ACTIVE" -eq 1 ]]; do
|
|
||||||
printf "\r\e[2K%s %b" "${frames[spin_i]}" "${YW}${SPINNER_MSG}${CL}" >&2
|
|
||||||
spin_i=$(((spin_i + 1) % ${#frames[@]}))
|
|
||||||
sleep "$interval"
|
|
||||||
done
|
|
||||||
} &
|
|
||||||
|
|
||||||
SPINNER_PID=$!
|
|
||||||
disown "$SPINNER_PID"
|
|
||||||
}
|
|
||||||
|
|
||||||
stop_spinner() {
|
|
||||||
if [[ ${SPINNER_PID+v} && -n "$SPINNER_PID" ]] && kill -0 "$SPINNER_PID" 2>/dev/null; then
|
|
||||||
kill "$SPINNER_PID" 2>/dev/null
|
|
||||||
sleep 0.1
|
|
||||||
kill -0 "$SPINNER_PID" 2>/dev/null && kill -9 "$SPINNER_PID" 2>/dev/null
|
|
||||||
wait "$SPINNER_PID" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
SPINNER_ACTIVE=0
|
|
||||||
unset SPINNER_PID
|
|
||||||
}
|
|
||||||
|
|
||||||
spinner_guard() {
|
|
||||||
if [[ "$SPINNER_ACTIVE" -eq 1 ]] && [[ -n "$SPINNER_PID" ]]; then
|
|
||||||
kill "$SPINNER_PID" 2>/dev/null
|
|
||||||
wait "$SPINNER_PID" 2>/dev/null || true
|
|
||||||
SPINNER_ACTIVE=0
|
|
||||||
unset SPINNER_PID
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_info() {
|
|
||||||
local msg="$1"
|
|
||||||
[[ -n "${MSG_INFO_SHOWN["$msg"]+x}" ]] && return
|
|
||||||
MSG_INFO_SHOWN["$msg"]=1
|
|
||||||
|
|
||||||
spinner_guard
|
|
||||||
SPINNER_ACTIVE=1
|
|
||||||
start_spinner "$msg"
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_ok() {
|
|
||||||
local msg="$1"
|
|
||||||
stop_spinner
|
|
||||||
printf "\r\e[2K%s %b\n" "${CM}" "${GN}${msg}${CL}" >&2
|
|
||||||
unset MSG_INFO_SHOWN["$msg"]
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_error() {
|
|
||||||
stop_spinner
|
|
||||||
local msg="$1"
|
|
||||||
printf "\r\e[2K%s %b\n" "${CROSS}" "${RD}${msg}${CL}" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if the shell is using bash
|
# Check if the shell is using bash
|
||||||
shell_check() {
|
shell_check() {
|
||||||
if [[ "$(basename "$SHELL")" != "bash" ]]; then
|
if [[ "$(basename "$SHELL")" != "bash" ]]; then
|
||||||
@ -273,42 +164,6 @@ update_motd_ip() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# 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 local_header_path="/usr/local/community-scripts/headers/${app_name}"
|
|
||||||
|
|
||||||
mkdir -p "$(dirname "$local_header_path")"
|
|
||||||
|
|
||||||
if [ ! -s "$local_header_path" ]; then
|
|
||||||
if ! curl -fsSL "$header_url" -o "$local_header_path"; then
|
|
||||||
echo -e "Failed to download header for ${app_name}. No header will be displayed."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat "$local_header_path"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function sets the APP-Name into an ASCII Header in Slant, figlet needed on proxmox main node.
|
|
||||||
header_info() {
|
|
||||||
local app_name=$(echo "${APP,,}" | tr -d ' ')
|
|
||||||
local header_content
|
|
||||||
|
|
||||||
# Download & save Header-File locally
|
|
||||||
header_content=$(get_header "$app_name")
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
# Fallback: Doesn't show Header
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Show ASCII-Header
|
|
||||||
term_width=$(tput cols 2>/dev/null || echo 120)
|
|
||||||
clear
|
|
||||||
echo "$header_content"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function checks if the script is running through SSH and prompts the user to confirm if they want to proceed or exit.
|
# This function checks if the script is running through SSH and prompts the user to confirm if they want to proceed or exit.
|
||||||
ssh_check() {
|
ssh_check() {
|
||||||
if [ -n "${SSH_CLIENT:+x}" ]; then
|
if [ -n "${SSH_CLIENT:+x}" ]; then
|
||||||
@ -346,8 +201,8 @@ base_settings() {
|
|||||||
SSH="no"
|
SSH="no"
|
||||||
SSH_AUTHORIZED_KEY=""
|
SSH_AUTHORIZED_KEY=""
|
||||||
TAGS="community-script;"
|
TAGS="community-script;"
|
||||||
ENABLE_FUSE="no"
|
ENABLE_FUSE="${1:-no}"
|
||||||
ENABLE_TUN="no"
|
ENABLE_TUN="${1:-no}"
|
||||||
|
|
||||||
# Override default settings with variables from ct script
|
# Override default settings with variables from ct script
|
||||||
CT_TYPE=${var_unprivileged:-$CT_TYPE}
|
CT_TYPE=${var_unprivileged:-$CT_TYPE}
|
||||||
@ -518,30 +373,38 @@ advanced_settings() {
|
|||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
if PW1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "\nSet Root Password (needed for root ssh access)" 9 58 --title "PASSWORD (leave blank for automatic login)" 3>&1 1>&2 2>&3); then
|
if PW1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "\nSet Root Password (needed for root ssh access)" 9 58 --title "PASSWORD (leave blank for automatic login)" 3>&1 1>&2 2>&3); then
|
||||||
if [[ ! -z "$PW1" ]]; then
|
# Empty = Autologin
|
||||||
if [[ "$PW1" == *" "* ]]; then
|
if [[ -z "$PW1" ]]; then
|
||||||
whiptail --msgbox "Password cannot contain spaces. Please try again." 8 58
|
|
||||||
elif [ ${#PW1} -lt 5 ]; then
|
|
||||||
whiptail --msgbox "Password must be at least 5 characters long. Please try again." 8 58
|
|
||||||
else
|
|
||||||
if PW2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "\nVerify Root Password" 9 58 --title "PASSWORD VERIFICATION" 3>&1 1>&2 2>&3); then
|
|
||||||
if [[ "$PW1" == "$PW2" ]]; then
|
|
||||||
PW="-password $PW1"
|
|
||||||
echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}********${CL}"
|
|
||||||
break
|
|
||||||
else
|
|
||||||
whiptail --msgbox "Passwords do not match. Please try again." 8 58
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
PW1="Automatic Login"
|
|
||||||
PW=""
|
PW=""
|
||||||
|
PW1="Automatic Login"
|
||||||
echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}$PW1${CL}"
|
echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}$PW1${CL}"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Invalid: contains spaces
|
||||||
|
if [[ "$PW1" == *" "* ]]; then
|
||||||
|
whiptail --msgbox "Password cannot contain spaces." 8 58
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Invalid: too short
|
||||||
|
if ((${#PW1} < 5)); then
|
||||||
|
whiptail --msgbox "Password must be at least 5 characters." 8 58
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Confirm password
|
||||||
|
if PW2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "\nVerify Root Password" 9 58 --title "PASSWORD VERIFICATION" 3>&1 1>&2 2>&3); then
|
||||||
|
if [[ "$PW1" == "$PW2" ]]; then
|
||||||
|
PW="-password $PW1"
|
||||||
|
echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}********${CL}"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
whiptail --msgbox "Passwords do not match. Please try again." 8 58
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit_script
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
exit_script
|
exit_script
|
||||||
fi
|
fi
|
||||||
@ -565,7 +428,7 @@ advanced_settings() {
|
|||||||
else
|
else
|
||||||
HN=$(echo "${CT_NAME,,}" | tr -d ' ')
|
HN=$(echo "${CT_NAME,,}" | tr -d ' ')
|
||||||
fi
|
fi
|
||||||
|
# Hostname validate (RFC 1123)
|
||||||
if [[ "$HN" =~ ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ ]]; then
|
if [[ "$HN" =~ ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ ]]; then
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
break
|
break
|
||||||
@ -824,11 +687,11 @@ advanced_settings() {
|
|||||||
echo -e "${FUSE}${BOLD}${DGN}Enable FUSE Support: ${BGN}$ENABLE_FUSE${CL}"
|
echo -e "${FUSE}${BOLD}${DGN}Enable FUSE Support: ${BGN}$ENABLE_FUSE${CL}"
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then
|
||||||
VERB="yes"
|
VERBOSE="yes"
|
||||||
else
|
else
|
||||||
VERB="no"
|
VERBOSE="no"
|
||||||
fi
|
fi
|
||||||
echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}$VERB${CL}"
|
echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}$VERBOSE${CL}"
|
||||||
|
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create ${APP} LXC?" 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create ${APP} LXC?" 10 58); then
|
||||||
echo -e "${CREATING}${BOLD}${RD}Creating a ${APP} LXC using the above advanced settings${CL}"
|
echo -e "${CREATING}${BOLD}${RD}Creating a ${APP} LXC using the above advanced settings${CL}"
|
||||||
@ -944,18 +807,18 @@ install_script() {
|
|||||||
1)
|
1)
|
||||||
header_info
|
header_info
|
||||||
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME${CL}"
|
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME${CL}"
|
||||||
VERB="no"
|
VERBOSE="no"
|
||||||
METHOD="default"
|
METHOD="default"
|
||||||
base_settings "$VERB"
|
base_settings "$VERBOSE"
|
||||||
echo_default
|
echo_default
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
header_info
|
header_info
|
||||||
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME (${VERBOSE_CROPPED}Verbose)${CL}"
|
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME (${VERBOSE_CROPPED}Verbose)${CL}"
|
||||||
VERB="yes"
|
VERBOSE="yes"
|
||||||
METHOD="default"
|
METHOD="default"
|
||||||
base_settings "$VERB"
|
base_settings "$VERBOSE"
|
||||||
echo_default
|
echo_default
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
@ -1046,16 +909,8 @@ check_container_storage() {
|
|||||||
start() {
|
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/main/misc/tools.func)
|
||||||
if command -v pveversion >/dev/null 2>&1; then
|
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
|
install_script
|
||||||
fi
|
else
|
||||||
|
|
||||||
if ! command -v pveversion >/dev/null 2>&1; then
|
|
||||||
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP} LXC Update/Setting" --menu \
|
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP} LXC Update/Setting" --menu \
|
||||||
"Support/Update functions for ${APP} LXC. Choose an option:" \
|
"Support/Update functions for ${APP} LXC. Choose an option:" \
|
||||||
12 60 3 \
|
12 60 3 \
|
||||||
@ -1065,11 +920,11 @@ start() {
|
|||||||
|
|
||||||
case "$CHOICE" in
|
case "$CHOICE" in
|
||||||
1)
|
1)
|
||||||
VERB="no"
|
VERBOSE="no"
|
||||||
set_std_mode
|
set_std_mode
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
VERB="yes"
|
VERBOSE="yes"
|
||||||
set_std_mode
|
set_std_mode
|
||||||
;;
|
;;
|
||||||
3)
|
3)
|
||||||
@ -1078,15 +933,13 @@ start() {
|
|||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
SPINNER_PID=""
|
|
||||||
update_script
|
update_script
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# This function collects user settings and integrates all the collected information.
|
# This function collects user settings and integrates all the collected information.
|
||||||
build_container() {
|
build_container() {
|
||||||
# if [ "$VERB" == "yes" ]; then set -x; fi
|
# if [ "$VERBOSE" == "yes" ]; then set -x; fi
|
||||||
|
|
||||||
if [ "$CT_TYPE" == "1" ]; then
|
if [ "$CT_TYPE" == "1" ]; then
|
||||||
FEATURES="keyctl=1,nesting=1"
|
FEATURES="keyctl=1,nesting=1"
|
||||||
@ -1119,7 +972,7 @@ build_container() {
|
|||||||
export APPLICATION="$APP"
|
export APPLICATION="$APP"
|
||||||
export app="$NSAPP"
|
export app="$NSAPP"
|
||||||
export PASSWORD="$PW"
|
export PASSWORD="$PW"
|
||||||
export VERBOSE="$VERB"
|
export VERBOSE="$VERBOSE"
|
||||||
export SSH_ROOT="${SSH}"
|
export SSH_ROOT="${SSH}"
|
||||||
export SSH_AUTHORIZED_KEY
|
export SSH_AUTHORIZED_KEY
|
||||||
export CTID="$CT_ID"
|
export CTID="$CT_ID"
|
||||||
@ -1204,16 +1057,30 @@ EOF
|
|||||||
msg_info "Starting LXC Container"
|
msg_info "Starting LXC Container"
|
||||||
pct start "$CTID"
|
pct start "$CTID"
|
||||||
msg_ok "Started LXC Container"
|
msg_ok "Started LXC Container"
|
||||||
|
msg_info "Customizing LXC Container"
|
||||||
if [ "$var_os" == "alpine" ]; then
|
if [ "$var_os" == "alpine" ]; then
|
||||||
sleep 3
|
sleep 3
|
||||||
pct exec "$CTID" -- /bin/sh -c 'cat <<EOF >/etc/apk/repositories
|
pct exec "$CTID" -- /bin/sh -c 'cat <<EOF >/etc/apk/repositories
|
||||||
http://dl-cdn.alpinelinux.org/alpine/latest-stable/main
|
http://dl-cdn.alpinelinux.org/alpine/latest-stable/main
|
||||||
http://dl-cdn.alpinelinux.org/alpine/latest-stable/community
|
http://dl-cdn.alpinelinux.org/alpine/latest-stable/community
|
||||||
EOF'
|
EOF'
|
||||||
pct exec "$CTID" -- ash -c "apk add bash >/dev/null"
|
pct exec "$CTID" -- ash -c "apk add bash newt curl openssh nano mc ncurses >/dev/null"
|
||||||
fi
|
else
|
||||||
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/"$var_install".sh)" $?
|
sleep 3
|
||||||
|
# Set locale and timezone before update
|
||||||
|
pct exec "$CTID" -- bash -c "sed -i '/$LANG/ s/^# //' /etc/locale.gen"
|
||||||
|
pct exec "$CTID" -- bash -c "locale_line=\$(grep -v '^#' /etc/locale.gen | grep -E '^[a-zA-Z]' | awk '{print \$1}' | head -n 1) && \
|
||||||
|
echo LANG=\$locale_line >/etc/default/locale && \
|
||||||
|
locale-gen >/dev/null && \
|
||||||
|
export LANG=\$locale_line"
|
||||||
|
|
||||||
|
pct exec "$CTID" -- bash -c "echo $tz >/etc/timezone && ln -sf /usr/share/zoneinfo/$tz /etc/localtime"
|
||||||
|
|
||||||
|
# Install curl
|
||||||
|
pct exec "$CTID" -- bash -c "apt-get update >/dev/null && apt-get install -y sudo curl mc gnupg2 >/dev/null"
|
||||||
|
fi
|
||||||
|
msg_ok "Customized LXC Container"
|
||||||
|
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/"$var_install".sh)" $?
|
||||||
}
|
}
|
||||||
|
|
||||||
# This function sets the description of the container.
|
# This function sets the description of the container.
|
||||||
@ -1262,23 +1129,6 @@ EOF
|
|||||||
post_update_to_api "done" "none"
|
post_update_to_api "done" "none"
|
||||||
}
|
}
|
||||||
|
|
||||||
set_std_mode() {
|
|
||||||
if [ "$VERB" = "yes" ]; then
|
|
||||||
STD=""
|
|
||||||
else
|
|
||||||
STD="silent"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Silent execution function
|
|
||||||
silent() {
|
|
||||||
if [ "$VERB" = "no" ]; then
|
|
||||||
"$@" >/dev/null 2>&1 || return 1
|
|
||||||
else
|
|
||||||
"$@" || return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
api_exit_script() {
|
api_exit_script() {
|
||||||
exit_code=$? # Capture the exit status of the last executed command
|
exit_code=$? # Capture the exit status of the last executed command
|
||||||
#200 exit codes indicate error in create_lxc.sh
|
#200 exit codes indicate error in create_lxc.sh
|
||||||
|
|||||||
@ -53,15 +53,15 @@ config_file() {
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if CT_ID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Container ID" 8 58 "$NEXTID" --title "CONTAINER ID" 3>&1 1>&2 2>&3); then
|
if CT_ID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Container ID" 8 58 "$NEXTID" --title "CONTAINER ID" 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$CT_ID" ]; then
|
if [ -z "$CT_ID" ]; then
|
||||||
CT_ID="$NEXTID"
|
CT_ID="$NEXTID"
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}"
|
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}"
|
exit_script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
if [[ -n "${CT_TYPE-}" ]]; then
|
if [[ -n "${CT_TYPE-}" ]]; then
|
||||||
@ -75,23 +75,22 @@ config_file() {
|
|||||||
fi
|
fi
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}"
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}"
|
||||||
else
|
else
|
||||||
if CT_TYPE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \
|
if CT_TYPE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \
|
||||||
"1" "Unprivileged" ON \
|
"1" "Unprivileged" ON \
|
||||||
"0" "Privileged" OFF \
|
"0" "Privileged" OFF \
|
||||||
3>&1 1>&2 2>&3); then
|
3>&1 1>&2 2>&3); then
|
||||||
if [ -n "$CT_TYPE" ]; then
|
if [ -n "$CT_TYPE" ]; then
|
||||||
CT_TYPE_DESC="Unprivileged"
|
CT_TYPE_DESC="Unprivileged"
|
||||||
if [ "$CT_TYPE" -eq 0 ]; then
|
if [ "$CT_TYPE" -eq 0 ]; then
|
||||||
CT_TYPE_DESC="Privileged"
|
CT_TYPE_DESC="Privileged"
|
||||||
fi
|
|
||||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}"
|
|
||||||
fi
|
fi
|
||||||
else
|
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}"
|
||||||
exit_script
|
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
exit_script
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
if [[ -n "${PW-}" ]]; then
|
if [[ -n "${PW-}" ]]; then
|
||||||
if [[ "$PW" == "none" ]]; then
|
if [[ "$PW" == "none" ]]; then
|
||||||
PW=""
|
PW=""
|
||||||
@ -109,50 +108,50 @@ config_file() {
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
while true; do
|
while true; do
|
||||||
if PW1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "\nSet Root Password (needed for root ssh access)" 9 58 --title "PASSWORD (leave blank for automatic login)" 3>&1 1>&2 2>&3); then
|
if PW1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "\nSet Root Password (needed for root ssh access)" 9 58 --title "PASSWORD (leave blank for automatic login)" 3>&1 1>&2 2>&3); then
|
||||||
if [[ -n "$PW1" ]]; then
|
if [[ -n "$PW1" ]]; then
|
||||||
if [[ "$PW1" == *" "* ]]; then
|
if [[ "$PW1" == *" "* ]]; then
|
||||||
whiptail --msgbox "Password cannot contain spaces. Please try again." 8 58
|
whiptail --msgbox "Password cannot contain spaces. Please try again." 8 58
|
||||||
elif [ ${#PW1} -lt 5 ]; then
|
elif [ ${#PW1} -lt 5 ]; then
|
||||||
whiptail --msgbox "Password must be at least 5 characters long. Please try again." 8 58
|
whiptail --msgbox "Password must be at least 5 characters long. Please try again." 8 58
|
||||||
else
|
|
||||||
if PW2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "\nVerify Root Password" 9 58 --title "PASSWORD VERIFICATION" 3>&1 1>&2 2>&3); then
|
|
||||||
if [[ "$PW1" == "$PW2" ]]; then
|
|
||||||
PW="-password $PW1"
|
|
||||||
echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}********${CL}"
|
|
||||||
break
|
|
||||||
else
|
|
||||||
whiptail --msgbox "Passwords do not match. Please try again." 8 58
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
exit_script
|
if PW2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "\nVerify Root Password" 9 58 --title "PASSWORD VERIFICATION" 3>&1 1>&2 2>&3); then
|
||||||
|
if [[ "$PW1" == "$PW2" ]]; then
|
||||||
|
PW="-password $PW1"
|
||||||
|
echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}********${CL}"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
whiptail --msgbox "Passwords do not match. Please try again." 8 58
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit_script
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
PW1="Automatic Login"
|
||||||
|
PW=""
|
||||||
|
echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}$PW1${CL}"
|
||||||
|
break
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
PW1="Automatic Login"
|
exit_script
|
||||||
PW=""
|
|
||||||
echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}$PW1${CL}"
|
|
||||||
break
|
|
||||||
fi
|
fi
|
||||||
else
|
done
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "${HN-}" ]]; then
|
if [[ -n "${HN-}" ]]; then
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
else
|
else
|
||||||
if CT_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 "$NSAPP" --title "HOSTNAME" 3>&1 1>&2 2>&3); then
|
if CT_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 "$NSAPP" --title "HOSTNAME" 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$CT_NAME" ]; then
|
if [ -z "$CT_NAME" ]; then
|
||||||
HN="$NSAPP"
|
HN="$NSAPP"
|
||||||
|
else
|
||||||
|
HN=$(echo "${CT_NAME,,}" | tr -d ' ')
|
||||||
|
fi
|
||||||
|
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||||
else
|
else
|
||||||
HN=$(echo "${CT_NAME,,}" | tr -d ' ')
|
exit_script
|
||||||
fi
|
fi
|
||||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "${DISK_SIZE-}" ]]; then
|
if [[ -n "${DISK_SIZE-}" ]]; then
|
||||||
@ -164,19 +163,19 @@ config_file() {
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GB" 8 58 "$var_disk" --title "DISK SIZE" 3>&1 1>&2 2>&3); then
|
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GB" 8 58 "$var_disk" --title "DISK SIZE" 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$DISK_SIZE" ]; then
|
if [ -z "$DISK_SIZE" ]; then
|
||||||
DISK_SIZE="$var_disk"
|
DISK_SIZE="$var_disk"
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}"
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}"
|
||||||
else
|
else
|
||||||
if ! [[ $DISK_SIZE =~ $INTEGER ]]; then
|
if ! [[ $DISK_SIZE =~ $INTEGER ]]; then
|
||||||
echo -e "{INFO}${HOLD}${RD} DISK SIZE MUST BE AN INTEGER NUMBER!${CL}"
|
echo -e "{INFO}${HOLD}${RD} DISK SIZE MUST BE AN INTEGER NUMBER!${CL}"
|
||||||
advanced_settings
|
advanced_settings
|
||||||
|
fi
|
||||||
|
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}"
|
||||||
fi
|
fi
|
||||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}"
|
else
|
||||||
|
exit_script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "${CORE_COUNT-}" ]]; then
|
if [[ -n "${CORE_COUNT-}" ]]; then
|
||||||
@ -188,15 +187,15 @@ config_file() {
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 "$var_cpu" --title "CORE COUNT" 3>&1 1>&2 2>&3); then
|
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 "$var_cpu" --title "CORE COUNT" 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$CORE_COUNT" ]; then
|
if [ -z "$CORE_COUNT" ]; then
|
||||||
CORE_COUNT="$var_cpu"
|
CORE_COUNT="$var_cpu"
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
exit_script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "${RAM_SIZE-}" ]]; then
|
if [[ -n "${RAM_SIZE-}" ]]; then
|
||||||
@ -208,15 +207,15 @@ config_file() {
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 "$var_ram" --title "RAM" 3>&1 1>&2 2>&3); then
|
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 "$var_ram" --title "RAM" 3>&1 1>&2 2>&3); then
|
||||||
if [ -z "$RAM_SIZE" ]; then
|
if [ -z "$RAM_SIZE" ]; then
|
||||||
RAM_SIZE="$var_ram"
|
RAM_SIZE="$var_ram"
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}"
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}"
|
exit_script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
IFACE_FILEPATH_LIST="/etc/network/interfaces"$'\n'$(find "/etc/network/interfaces.d/" -type f)
|
IFACE_FILEPATH_LIST="/etc/network/interfaces"$'\n'$(find "/etc/network/interfaces.d/" -type f)
|
||||||
@ -227,20 +226,20 @@ config_file() {
|
|||||||
for iface_filepath in ${IFACE_FILEPATH_LIST}; do
|
for iface_filepath in ${IFACE_FILEPATH_LIST}; do
|
||||||
|
|
||||||
iface_indexes_tmpfile=$(mktemp -q -u '.iface-XXXX')
|
iface_indexes_tmpfile=$(mktemp -q -u '.iface-XXXX')
|
||||||
( grep -Pn '^\s*iface' "${iface_filepath}" | cut -d':' -f1 && wc -l "${iface_filepath}" | cut -d' ' -f1 ) | awk 'FNR==1 {line=$0; next} {print line":"$0-1; line=$0}' > "${iface_indexes_tmpfile}" || true
|
(grep -Pn '^\s*iface' "${iface_filepath}" | cut -d':' -f1 && wc -l "${iface_filepath}" | cut -d' ' -f1) | awk 'FNR==1 {line=$0; next} {print line":"$0-1; line=$0}' >"${iface_indexes_tmpfile}" || true
|
||||||
|
|
||||||
if [ -f "${iface_indexes_tmpfile}" ]; then
|
if [ -f "${iface_indexes_tmpfile}" ]; then
|
||||||
|
|
||||||
while read -r pair; do
|
while read -r pair; do
|
||||||
start=$(echo "${pair}" | cut -d':' -f1)
|
start=$(echo "${pair}" | cut -d':' -f1)
|
||||||
end=$(echo "${pair}" | cut -d':' -f2)
|
end=$(echo "${pair}" | cut -d':' -f2)
|
||||||
if awk "NR >= ${start} && NR <= ${end}" "${iface_filepath}" | grep -qP '^\s*(bridge[-_](ports|stp|fd|vlan-aware|vids)|ovs_type\s+OVSBridge)\b'; then
|
if awk "NR >= ${start} && NR <= ${end}" "${iface_filepath}" | grep -qP '^\s*(bridge[-_](ports|stp|fd|vlan-aware|vids)|ovs_type\s+OVSBridge)\b'; then
|
||||||
iface_name=$(sed "${start}q;d" "${iface_filepath}" | awk '{print $2}')
|
iface_name=$(sed "${start}q;d" "${iface_filepath}" | awk '{print $2}')
|
||||||
BRIDGES="${iface_name}"$'\n'"${BRIDGES}"
|
BRIDGES="${iface_name}"$'\n'"${BRIDGES}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
done < "${iface_indexes_tmpfile}"
|
done <"${iface_indexes_tmpfile}"
|
||||||
rm -f "${iface_indexes_tmpfile}"
|
rm -f "${iface_indexes_tmpfile}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
done
|
done
|
||||||
@ -296,7 +295,7 @@ config_file() {
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
elif [[ "$NET" == *-* ]]; then
|
elif [[ "$NET" == *-* ]]; then
|
||||||
IFS="-" read -r ip_start ip_end <<< "$NET"
|
IFS="-" read -r ip_start ip_end <<<"$NET"
|
||||||
|
|
||||||
if [[ ! "$ip_start" =~ $ip_cidr_regex ]] || [[ ! "$ip_end" =~ $ip_cidr_regex ]]; then
|
if [[ ! "$ip_start" =~ $ip_cidr_regex ]] || [[ ! "$ip_end" =~ $ip_cidr_regex ]]; then
|
||||||
msg_error "Invalid IP range format, was $NET should be 0.0.0.0/0-0.0.0.0/0"
|
msg_error "Invalid IP range format, was $NET should be 0.0.0.0/0-0.0.0.0/0"
|
||||||
@ -309,21 +308,21 @@ config_file() {
|
|||||||
|
|
||||||
ip_to_int() {
|
ip_to_int() {
|
||||||
local IFS=.
|
local IFS=.
|
||||||
read -r i1 i2 i3 i4 <<< "$1"
|
read -r i1 i2 i3 i4 <<<"$1"
|
||||||
echo $(( (i1 << 24) + (i2 << 16) + (i3 << 8) + i4 ))
|
echo $(((i1 << 24) + (i2 << 16) + (i3 << 8) + i4))
|
||||||
}
|
}
|
||||||
|
|
||||||
int_to_ip() {
|
int_to_ip() {
|
||||||
local ip=$1
|
local ip=$1
|
||||||
echo "$(( (ip >> 24) & 0xFF )).$(( (ip >> 16) & 0xFF )).$(( (ip >> 8) & 0xFF )).$(( ip & 0xFF ))"
|
echo "$(((ip >> 24) & 0xFF)).$(((ip >> 16) & 0xFF)).$(((ip >> 8) & 0xFF)).$((ip & 0xFF))"
|
||||||
}
|
}
|
||||||
|
|
||||||
start_int=$(ip_to_int "$ip1")
|
start_int=$(ip_to_int "$ip1")
|
||||||
end_int=$(ip_to_int "$ip2")
|
end_int=$(ip_to_int "$ip2")
|
||||||
|
|
||||||
for ((ip_int=start_int; ip_int<=end_int; ip_int++)); do
|
for ((ip_int = start_int; ip_int <= end_int; ip_int++)); do
|
||||||
ip=$(int_to_ip $ip_int)
|
ip=$(int_to_ip $ip_int)
|
||||||
msg_info "Checking IP: $ip"
|
msg_info "Checking IP: $ip"
|
||||||
if ! ping -c 2 -W 1 "$ip" >/dev/null 2>&1; then
|
if ! ping -c 2 -W 1 "$ip" >/dev/null 2>&1; then
|
||||||
NET="$ip/$cidr"
|
NET="$ip/$cidr"
|
||||||
msg_ok "Using free IP Address: ${BGN}$NET${CL}"
|
msg_ok "Using free IP Address: ${BGN}$NET${CL}"
|
||||||
@ -363,37 +362,37 @@ config_file() {
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
while true; do
|
while true; do
|
||||||
NET=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Static IPv4 CIDR Address (/24)" 8 58 dhcp --title "IP ADDRESS" 3>&1 1>&2 2>&3)
|
NET=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Static IPv4 CIDR Address (/24)" 8 58 dhcp --title "IP ADDRESS" 3>&1 1>&2 2>&3)
|
||||||
exit_status=$?
|
exit_status=$?
|
||||||
if [ $exit_status -eq 0 ]; then
|
if [ $exit_status -eq 0 ]; then
|
||||||
if [ "$NET" = "dhcp" ]; then
|
if [ "$NET" = "dhcp" ]; then
|
||||||
echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}"
|
|
||||||
break
|
|
||||||
else
|
|
||||||
if [[ "$NET" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$ ]]; then
|
|
||||||
echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}"
|
echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}"
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "$NET is an invalid IPv4 CIDR address. Please enter a valid IPv4 CIDR address or 'dhcp'" 8 58
|
if [[ "$NET" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$ ]]; then
|
||||||
|
echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "$NET is an invalid IPv4 CIDR address. Please enter a valid IPv4 CIDR address or 'dhcp'" 8 58
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
exit_script
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
exit_script
|
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
if [ "$NET" != "dhcp" ]; then
|
if [ "$NET" != "dhcp" ]; then
|
||||||
while true; do
|
while true; do
|
||||||
GATE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Enter gateway IP address" 8 58 --title "Gateway IP" 3>&1 1>&2 2>&3)
|
GATE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Enter gateway IP address" 8 58 --title "Gateway IP" 3>&1 1>&2 2>&3)
|
||||||
if [ -z "$GATE1" ]; then
|
if [ -z "$GATE1" ]; then
|
||||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "Gateway IP address cannot be empty" 8 58
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "Gateway IP address cannot be empty" 8 58
|
||||||
elif [[ ! "$GATE1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
elif [[ ! "$GATE1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "Invalid IP address format" 8 58
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "Invalid IP address format" 8 58
|
||||||
else
|
else
|
||||||
GATE=",gw=$GATE1"
|
GATE=",gw=$GATE1"
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE1${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE1${CL}"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
GATE=""
|
GATE=""
|
||||||
echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}Default${CL}"
|
echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}Default${CL}"
|
||||||
@ -406,8 +405,8 @@ config_file() {
|
|||||||
else
|
else
|
||||||
if [[ -n "${APT_CACHER_IP-}" ]]; then
|
if [[ -n "${APT_CACHER_IP-}" ]]; then
|
||||||
if [[ ! $APT_CACHER_IP == "none" ]]; then
|
if [[ ! $APT_CACHER_IP == "none" ]]; then
|
||||||
APT_CACHER="yes"
|
APT_CACHER="yes"
|
||||||
echo -e "${NETWORK}${BOLD}${DGN}APT-CACHER IP Address: ${BGN}$APT_CACHER_IP${CL}"
|
echo -e "${NETWORK}${BOLD}${DGN}APT-CACHER IP Address: ${BGN}$APT_CACHER_IP${CL}"
|
||||||
else
|
else
|
||||||
APT_CACHER=""
|
APT_CACHER=""
|
||||||
echo -e "${NETWORK}${BOLD}${DGN}APT-Cacher IP Address: ${BGN}No${CL}"
|
echo -e "${NETWORK}${BOLD}${DGN}APT-Cacher IP Address: ${BGN}No${CL}"
|
||||||
@ -416,7 +415,7 @@ config_file() {
|
|||||||
if APT_CACHER_IP=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set APT-Cacher IP (leave blank for none)" 8 58 --title "APT-Cacher IP" 3>&1 1>&2 2>&3); then
|
if APT_CACHER_IP=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set APT-Cacher IP (leave blank for none)" 8 58 --title "APT-Cacher IP" 3>&1 1>&2 2>&3); then
|
||||||
APT_CACHER="${APT_CACHER_IP:+yes}"
|
APT_CACHER="${APT_CACHER_IP:+yes}"
|
||||||
echo -e "${NETWORK}${BOLD}${DGN}APT-Cacher IP Address: ${BGN}${APT_CACHER_IP:-Default}${CL}"
|
echo -e "${NETWORK}${BOLD}${DGN}APT-Cacher IP Address: ${BGN}${APT_CACHER_IP:-Default}${CL}"
|
||||||
if [[ -n $APT_CACHER_IP ]]; then
|
if [[ -n $APT_CACHER_IP ]]; then
|
||||||
APT_CACHER_IP="none"
|
APT_CACHER_IP="none"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
@ -506,7 +505,7 @@ config_file() {
|
|||||||
fi
|
fi
|
||||||
echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}$NX${CL}"
|
echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}$NX${CL}"
|
||||||
else
|
else
|
||||||
exit_script
|
exit_script
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -533,7 +532,7 @@ config_file() {
|
|||||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
exit_script
|
exit_script
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -582,7 +581,7 @@ config_file() {
|
|||||||
fi
|
fi
|
||||||
echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}"
|
echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}"
|
||||||
else
|
else
|
||||||
exit_script
|
exit_script
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -646,7 +645,7 @@ config_file() {
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then
|
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then
|
||||||
VERBOSE="yes"
|
VERBOSE="yes"
|
||||||
else
|
else
|
||||||
VERBOSE="no"
|
VERBOSE="no"
|
||||||
|
|||||||
@ -46,15 +46,26 @@ load_functions() {
|
|||||||
on_error() {
|
on_error() {
|
||||||
local exit_code="$1"
|
local exit_code="$1"
|
||||||
local lineno="$2"
|
local lineno="$2"
|
||||||
msg_error "Script failed at line $lineno with exit code $exit_code"
|
|
||||||
# Optionally log to your API or file here
|
stop_spinner
|
||||||
|
|
||||||
|
case "$exit_code" in
|
||||||
|
1) msg_error "Generic error occurred (line $lineno)" ;;
|
||||||
|
2) msg_error "Shell misuse (line $lineno)" ;;
|
||||||
|
126) msg_error "Command cannot execute (line $lineno)" ;;
|
||||||
|
127) msg_error "Command not found (line $lineno)" ;;
|
||||||
|
128) msg_error "Invalid exit argument (line $lineno)" ;;
|
||||||
|
130) msg_error "Script aborted by user (CTRL+C)" ;;
|
||||||
|
143) msg_error "Script terminated by SIGTERM" ;;
|
||||||
|
*) msg_error "Script failed at line $lineno with exit code $exit_code" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
exit "$exit_code"
|
exit "$exit_code"
|
||||||
}
|
}
|
||||||
|
|
||||||
on_exit() {
|
on_exit() {
|
||||||
# Always called on script exit, success or failure
|
cleanup_spinner || true
|
||||||
cleanup_temp_files || true
|
[[ "${VERBOSE:-no}" == "yes" ]] && msg_info "Script exited"
|
||||||
msg_info "Script exited"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
on_interrupt() {
|
on_interrupt() {
|
||||||
@ -184,6 +195,7 @@ icons() {
|
|||||||
CREATING="${TAB}🚀${TAB}${CL}"
|
CREATING="${TAB}🚀${TAB}${CL}"
|
||||||
ADVANCED="${TAB}🧩${TAB}${CL}"
|
ADVANCED="${TAB}🧩${TAB}${CL}"
|
||||||
FUSE="${TAB}🗂️${TAB}${CL}"
|
FUSE="${TAB}🗂️${TAB}${CL}"
|
||||||
|
HOURGLASS="${TAB}⏳${TAB}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@ -429,8 +441,14 @@ msg_info() {
|
|||||||
local msg="$1"
|
local msg="$1"
|
||||||
[[ -z "$msg" || -n "${MSG_INFO_SHOWN["$msg"]+x}" ]] && return
|
[[ -z "$msg" || -n "${MSG_INFO_SHOWN["$msg"]+x}" ]] && return
|
||||||
MSG_INFO_SHOWN["$msg"]=1
|
MSG_INFO_SHOWN["$msg"]=1
|
||||||
|
|
||||||
stop_spinner
|
stop_spinner
|
||||||
start_spinner "$msg"
|
|
||||||
|
if [[ "${VERBOSE:-no}" == "no" && -t 2 ]]; then
|
||||||
|
start_spinner "$msg"
|
||||||
|
else
|
||||||
|
printf "\r\e[2K%s %b" "$HOURGLASS" "${YW}${msg}${CL}" >&2
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_ok() {
|
msg_ok() {
|
||||||
|
|||||||
@ -3,32 +3,20 @@
|
|||||||
# Copyright (c) 2021-2025 tteck
|
# Copyright (c) 2021-2025 tteck
|
||||||
# Author: tteck (tteckster)
|
# Author: tteck (tteckster)
|
||||||
# Co-Author: MickLesk
|
# Co-Author: MickLesk
|
||||||
# License: MIT
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
|
|
||||||
# This sets verbose mode if the global variable is set to "yes"
|
# This sets verbose mode if the global variable is set to "yes"
|
||||||
# if [ "$VERBOSE" == "yes" ]; then set -x; fi
|
# if [ "$VERBOSE" == "yes" ]; then set -x; fi
|
||||||
|
|
||||||
# This function sets color variables for formatting output in the terminal
|
if command -v curl >/dev/null 2>&1; then
|
||||||
# Colors
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||||
YW=$(echo "\033[33m")
|
load_functions
|
||||||
YWB=$(echo "\033[93m")
|
#echo "(create-lxc.sh) Loaded core.func via curl"
|
||||||
BL=$(echo "\033[36m")
|
elif command -v wget >/dev/null 2>&1; then
|
||||||
RD=$(echo "\033[01;31m")
|
source <(wget -qO- https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||||
GN=$(echo "\033[1;92m")
|
load_functions
|
||||||
|
#echo "(create-lxc.sh) Loaded core.func via wget"
|
||||||
# Formatting
|
fi
|
||||||
CL=$(echo "\033[m")
|
|
||||||
UL=$(echo "\033[4m")
|
|
||||||
BOLD=$(echo "\033[1m")
|
|
||||||
BFR="\\r\\033[K"
|
|
||||||
HOLD=" "
|
|
||||||
TAB=" "
|
|
||||||
|
|
||||||
# Icons
|
|
||||||
CM="${TAB}✔️${TAB}${CL}"
|
|
||||||
CROSS="${TAB}✖️${TAB}${CL}"
|
|
||||||
INFO="${TAB}💡${TAB}${CL}"
|
|
||||||
|
|
||||||
# This sets error handling options and defines the error_handler function to handle errors
|
# This sets error handling options and defines the error_handler function to handle errors
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
@ -36,7 +24,6 @@ trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
|||||||
|
|
||||||
# This function handles errors
|
# This function handles errors
|
||||||
function error_handler() {
|
function error_handler() {
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
|
|
||||||
printf "\e[?25h"
|
printf "\e[?25h"
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
@ -46,53 +33,6 @@ function error_handler() {
|
|||||||
exit 200
|
exit 200
|
||||||
}
|
}
|
||||||
|
|
||||||
# This function displays a spinner.
|
|
||||||
function spinner() {
|
|
||||||
local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
|
|
||||||
local spin_i=0
|
|
||||||
local interval=0.1
|
|
||||||
printf "\e[?25l"
|
|
||||||
|
|
||||||
local color="${YWB}"
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
printf "\r ${color}%s${CL}" "${frames[spin_i]}"
|
|
||||||
spin_i=$(((spin_i + 1) % ${#frames[@]}))
|
|
||||||
sleep "$interval"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function displays an informational message with a yellow color.
|
|
||||||
function msg_info() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
|
||||||
spinner &
|
|
||||||
SPINNER_PID=$!
|
|
||||||
}
|
|
||||||
|
|
||||||
function msg_warn() {
|
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
|
|
||||||
printf "\e[?25h"
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${BFR}${INFO}${YWB}${msg}${CL}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function displays a success message with a green color.
|
|
||||||
function msg_ok() {
|
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
|
|
||||||
printf "\e[?25h"
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function displays a error message with a red color.
|
|
||||||
function msg_error() {
|
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
|
|
||||||
printf "\e[?25h"
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This checks for the presence of valid Container Storage and Template Storage locations
|
# This checks for the presence of valid Container Storage and Template Storage locations
|
||||||
msg_info "Validating Storage"
|
msg_info "Validating Storage"
|
||||||
VALIDCT=$(pvesm status -content rootdir | awk 'NR>1')
|
VALIDCT=$(pvesm status -content rootdir | awk 'NR>1')
|
||||||
@ -126,40 +66,44 @@ function select_storage() {
|
|||||||
} ;;
|
} ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# This Queries all storage locations
|
# Collect storage options
|
||||||
local -a MENU
|
local -a MENU
|
||||||
while read -r line; do
|
local MSG_MAX_LENGTH=0
|
||||||
local TAG=$(echo $line | awk '{print $1}')
|
|
||||||
local TYPE=$(echo $line | awk '{printf "%-10s", $2}')
|
|
||||||
local FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
|
|
||||||
local ITEM="Type: $TYPE Free: $FREE "
|
|
||||||
local OFFSET=2
|
|
||||||
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
|
|
||||||
local MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
|
|
||||||
fi
|
|
||||||
MENU+=("$TAG" "$ITEM" "OFF")
|
|
||||||
done < <(pvesm status -content $CONTENT | awk 'NR>1')
|
|
||||||
|
|
||||||
# Select storage location
|
while read -r TAG TYPE _ _ _ FREE _; do
|
||||||
if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
|
local TYPE_PADDED
|
||||||
printf ${MENU[0]}
|
local FREE_FMT
|
||||||
else
|
|
||||||
local STORAGE
|
TYPE_PADDED=$(printf "%-10s" "$TYPE")
|
||||||
while [ -z "${STORAGE:+x}" ]; do
|
FREE_FMT=$(numfmt --to=iec --from-unit=K --format %.2f <<<"$FREE")B
|
||||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
local ITEM="Type: $TYPE_PADDED Free: $FREE_FMT"
|
||||||
"Which storage pool would you like to use for the ${CONTENT_LABEL,,}?\nTo make a selection, use the Spacebar.\n" \
|
|
||||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
((${#ITEM} + 2 > MSG_MAX_LENGTH)) && MSG_MAX_LENGTH=$((${#ITEM} + 2))
|
||||||
"${MENU[@]}" 3>&1 1>&2 2>&3) || {
|
|
||||||
msg_error "Menu aborted."
|
MENU+=("$TAG" "$ITEM" "OFF")
|
||||||
exit 202
|
done < <(pvesm status -content "$CONTENT" | awk 'NR>1')
|
||||||
}
|
|
||||||
if [ $? -ne 0 ]; then
|
local OPTION_COUNT=$((${#MENU[@]} / 3))
|
||||||
echo -e "${CROSS}${RD} Menu aborted by user.${CL}"
|
|
||||||
exit 0
|
# Auto-select if only one option available
|
||||||
fi
|
if [[ "$OPTION_COUNT" -eq 1 ]]; then
|
||||||
done
|
echo "${MENU[0]}"
|
||||||
printf "%s" "$STORAGE"
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Display selection menu
|
||||||
|
local STORAGE
|
||||||
|
while [[ -z "${STORAGE:+x}" ]]; do
|
||||||
|
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||||
|
"Select the storage pool to use for the ${CONTENT_LABEL,,}.\nUse the spacebar to make a selection.\n" \
|
||||||
|
16 $((MSG_MAX_LENGTH + 23)) 6 \
|
||||||
|
"${MENU[@]}" 3>&1 1>&2 2>&3) || {
|
||||||
|
msg_error "Storage selection cancelled."
|
||||||
|
exit 202
|
||||||
|
}
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$STORAGE"
|
||||||
}
|
}
|
||||||
# Test if required variables are set
|
# Test if required variables are set
|
||||||
[[ "${CTID:-}" ]] || {
|
[[ "${CTID:-}" ]] || {
|
||||||
@ -177,20 +121,6 @@ function select_storage() {
|
|||||||
exit 205
|
exit 205
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check for network connectivity (IPv4 & IPv6)
|
|
||||||
#function check_network() {
|
|
||||||
# local CHECK_URLS=("8.8.8.8" "1.1.1.1" "9.9.9.9" "2606:4700:4700::1111" "2001:4860:4860::8888" "2620:fe::fe")
|
|
||||||
#
|
|
||||||
# for url in "${CHECK_URLS[@]}"; do
|
|
||||||
# if ping -c 1 -W 2 "$url" &>/dev/null; then
|
|
||||||
# return 0 # Success: At least one connection works
|
|
||||||
# fi
|
|
||||||
# done
|
|
||||||
#
|
|
||||||
# msg_error "No network connection detected. Check your internet connection."
|
|
||||||
# exit 101
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Test if ID is in use
|
# Test if ID is in use
|
||||||
if qm status "$CTID" &>/dev/null || pct status "$CTID" &>/dev/null; then
|
if qm status "$CTID" &>/dev/null || pct status "$CTID" &>/dev/null; then
|
||||||
echo -e "ID '$CTID' is already in use."
|
echo -e "ID '$CTID' is already in use."
|
||||||
@ -207,6 +137,13 @@ msg_ok "Using ${BL}$TEMPLATE_STORAGE${CL} ${GN}for Template Storage."
|
|||||||
CONTAINER_STORAGE=$(select_storage container)
|
CONTAINER_STORAGE=$(select_storage container)
|
||||||
msg_ok "Using ${BL}$CONTAINER_STORAGE${CL} ${GN}for Container Storage."
|
msg_ok "Using ${BL}$CONTAINER_STORAGE${CL} ${GN}for Container Storage."
|
||||||
|
|
||||||
|
# Check free space on selected container storage
|
||||||
|
STORAGE_FREE=$(pvesm status | awk -v s="$CONTAINER_STORAGE" '$1 == s { print $6 }')
|
||||||
|
REQUIRED_KB=$((${PCT_DISK_SIZE:-8} * 1024 * 1024))
|
||||||
|
if [ "$STORAGE_FREE" -lt "$REQUIRED_KB" ]; then
|
||||||
|
msg_error "Not enough space on '$CONTAINER_STORAGE'. Needed: ${PCT_DISK_SIZE:-8}G."
|
||||||
|
exit 214
|
||||||
|
fi
|
||||||
# Check Cluster Quorum if in Cluster
|
# Check Cluster Quorum if in Cluster
|
||||||
if [ -f /etc/pve/corosync.conf ]; then
|
if [ -f /etc/pve/corosync.conf ]; then
|
||||||
msg_info "Checking Proxmox cluster quorum status"
|
msg_info "Checking Proxmox cluster quorum status"
|
||||||
@ -220,44 +157,48 @@ fi
|
|||||||
|
|
||||||
# Update LXC template list
|
# Update LXC template list
|
||||||
msg_info "Updating LXC Template List"
|
msg_info "Updating LXC Template List"
|
||||||
#check_network
|
|
||||||
pveam update >/dev/null
|
if ! timeout 10 pveam update >/dev/null 2>&1; then
|
||||||
msg_ok "Updated LXC Template List"
|
msg_error "Failed to update LXC template list. Please check your Proxmox host's internet connection and DNS resolution."
|
||||||
|
exit 201
|
||||||
|
fi
|
||||||
|
$STD msg_ok "LXC Template List Updated"
|
||||||
|
|
||||||
# Get LXC template string
|
# Get LXC template string
|
||||||
TEMPLATE_SEARCH=${PCT_OSTYPE}-${PCT_OSVERSION:-}
|
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
|
||||||
mapfile -t TEMPLATES < <(pveam available -section system | sed -n "s/.*\($TEMPLATE_SEARCH.*\)/\1/p" | sort -t - -k 2 -V)
|
mapfile -t TEMPLATES < <(pveam available -section system | sed -n "s/.*\($TEMPLATE_SEARCH.*\)/\1/p" | sort -t - -k 2 -V)
|
||||||
[ ${#TEMPLATES[@]} -gt 0 ] || {
|
|
||||||
msg_error "Unable to find a template when searching for '$TEMPLATE_SEARCH'."
|
|
||||||
exit 207
|
|
||||||
}
|
|
||||||
TEMPLATE="${TEMPLATES[-1]}"
|
|
||||||
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE)"
|
|
||||||
# Without NAS/Mount: TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
|
|
||||||
# Check if template exists, if corrupt remove and redownload
|
|
||||||
if ! pveam list "$TEMPLATE_STORAGE" | grep -q "$TEMPLATE" || ! zstdcat "$TEMPLATE_PATH" | tar -tf - >/dev/null 2>&1; then
|
|
||||||
msg_warn "Template $TEMPLATE not found in storage or seems to be corrupted. Redownloading."
|
|
||||||
[[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
|
|
||||||
|
|
||||||
# Download with 3 attempts
|
if [ ${#TEMPLATES[@]} -eq 0 ]; then
|
||||||
|
msg_error "No matching LXC template found for '${TEMPLATE_SEARCH}'. Make sure your host can reach the Proxmox template repository."
|
||||||
|
exit 207
|
||||||
|
fi
|
||||||
|
|
||||||
|
TEMPLATE="${TEMPLATES[-1]}"
|
||||||
|
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || echo "/var/lib/vz/template/cache/$TEMPLATE")"
|
||||||
|
|
||||||
|
# Check if template exists and is valid
|
||||||
|
if ! pveam list "$TEMPLATE_STORAGE" | grep -q "$TEMPLATE" || ! zstdcat "$TEMPLATE_PATH" | tar -tf - >/dev/null 2>&1; then
|
||||||
|
msg_warn "Template $TEMPLATE not found or appears to be corrupted. Re-downloading."
|
||||||
|
|
||||||
|
[[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
|
||||||
for attempt in {1..3}; do
|
for attempt in {1..3}; do
|
||||||
msg_info "Attempt $attempt: Downloading LXC template..."
|
msg_info "Attempt $attempt: Downloading LXC template..."
|
||||||
|
|
||||||
if timeout 120 pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null; then
|
if timeout 120 pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1; then
|
||||||
msg_ok "Template download successful."
|
msg_ok "Template download successful."
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $attempt -eq 3 ]; then
|
if [ $attempt -eq 3 ]; then
|
||||||
msg_error "Three failed attempts. Aborting."
|
msg_error "Failed after 3 attempts. Please check your Proxmox host’s internet access or manually run:\n pveam download $TEMPLATE_STORAGE $TEMPLATE"
|
||||||
exit 208
|
exit 208
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sleep $((attempt * 5))
|
sleep $((attempt * 5))
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
msg_ok "LXC Template is ready to use."
|
|
||||||
|
|
||||||
|
msg_ok "LXC Template '$TEMPLATE' is ready to use."
|
||||||
# Check and fix subuid/subgid
|
# Check and fix subuid/subgid
|
||||||
grep -q "root:100000:65536" /etc/subuid || echo "root:100000:65536" >>/etc/subuid
|
grep -q "root:100000:65536" /etc/subuid || echo "root:100000:65536" >>/etc/subuid
|
||||||
grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgid
|
grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgid
|
||||||
@ -266,28 +207,55 @@ grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgi
|
|||||||
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
|
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
|
||||||
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}")
|
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}")
|
||||||
|
|
||||||
|
# Secure creation of the LXC container with lock and template check
|
||||||
|
lockfile="/tmp/template.${TEMPLATE}.lock"
|
||||||
|
exec 9>"$lockfile"
|
||||||
|
flock -w 60 9 || {
|
||||||
|
msg_error "Timeout while waiting for template lock"
|
||||||
|
exit 211
|
||||||
|
}
|
||||||
msg_info "Creating LXC Container"
|
msg_info "Creating LXC Container"
|
||||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
|
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
|
||||||
msg_error "Container creation failed. Checking if template is corrupted."
|
msg_error "Container creation failed. Checking if template is corrupted or incomplete."
|
||||||
|
|
||||||
if ! zstdcat "$TEMPLATE_PATH" | tar -tf - >/dev/null 2>&1; then
|
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
|
||||||
msg_error "Template appears to be corrupted. Removing and re-downloading."
|
msg_error "Template file too small or missing – re-downloading."
|
||||||
|
rm -f "$TEMPLATE_PATH"
|
||||||
|
elif ! zstdcat "$TEMPLATE_PATH" | tar -tf - &>/dev/null; then
|
||||||
|
msg_error "Template appears to be corrupted – re-downloading."
|
||||||
rm -f "$TEMPLATE_PATH"
|
rm -f "$TEMPLATE_PATH"
|
||||||
|
|
||||||
if ! timeout 120 pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null; then
|
|
||||||
msg_error "Failed to re-download template."
|
|
||||||
exit 208
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg_ok "Re-downloaded LXC Template"
|
|
||||||
|
|
||||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
|
|
||||||
msg_error "Container creation failed after re-downloading template."
|
|
||||||
exit 200
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
msg_error "Container creation failed, but template is not corrupted."
|
msg_error "Template is valid, but container creation still failed."
|
||||||
exit 209
|
exit 209
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Retry download
|
||||||
|
for attempt in {1..3}; do
|
||||||
|
msg_info "Attempt $attempt: Re-downloading template..."
|
||||||
|
if timeout 120 pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null; then
|
||||||
|
msg_ok "Template re-download successful."
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$attempt" -eq 3 ]; then
|
||||||
|
msg_error "Three failed attempts. Aborting."
|
||||||
|
exit 208
|
||||||
|
fi
|
||||||
|
sleep $((attempt * 5))
|
||||||
|
done
|
||||||
|
|
||||||
|
sleep 1 # I/O-Sync-Delay
|
||||||
|
|
||||||
|
msg_ok "Re-downloaded LXC Template"
|
||||||
|
|
||||||
|
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
|
||||||
|
msg_error "Container creation failed after re-downloading template."
|
||||||
|
exit 200
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! pct status "$CTID" &>/dev/null; then
|
||||||
|
msg_error "Container not found after pct create – assuming failure."
|
||||||
|
exit 210
|
||||||
|
fi
|
||||||
|
|
||||||
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
|
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
|
||||||
|
|||||||
@ -4,53 +4,13 @@
|
|||||||
# License: MIT
|
# License: MIT
|
||||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
|
||||||
# This function sets color variables for formatting output in the terminal
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
color() {
|
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||||
# Colors
|
apt-get update >/dev/null 2>&1
|
||||||
YW=$(echo "\033[33m")
|
apt-get install -y curl >/dev/null 2>&1
|
||||||
YWB=$(echo "\033[93m")
|
fi
|
||||||
BL=$(echo "\033[36m")
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||||
RD=$(echo "\033[01;31m")
|
load_functions
|
||||||
GN=$(echo "\033[1;92m")
|
|
||||||
|
|
||||||
# Formatting
|
|
||||||
CL=$(echo "\033[m")
|
|
||||||
BFR="\\r\\033[K"
|
|
||||||
BOLD=$(echo "\033[1m")
|
|
||||||
HOLD=" "
|
|
||||||
TAB=" "
|
|
||||||
TAB3=" "
|
|
||||||
|
|
||||||
# System
|
|
||||||
RETRY_NUM=10
|
|
||||||
RETRY_EVERY=3
|
|
||||||
|
|
||||||
# Icons
|
|
||||||
CM="${TAB}✔️${TAB}${CL}"
|
|
||||||
CROSS="${TAB}✖️${TAB}${CL}"
|
|
||||||
INFO="${TAB}💡${TAB}${CL}"
|
|
||||||
NETWORK="${TAB}📡${TAB}${CL}"
|
|
||||||
OS="${TAB}🖥️${TAB}${CL}"
|
|
||||||
OSVERSION="${TAB}🌟${TAB}${CL}"
|
|
||||||
HOSTNAME="${TAB}🏠${TAB}${CL}"
|
|
||||||
GATEWAY="${TAB}🌐${TAB}${CL}"
|
|
||||||
DEFAULT="${TAB}⚙️${TAB}${CL}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to set STD mode based on verbosity
|
|
||||||
set_std_mode() {
|
|
||||||
if [ "$VERBOSE" = "yes" ]; then
|
|
||||||
STD=""
|
|
||||||
else
|
|
||||||
STD="silent"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Silent execution function
|
|
||||||
silent() {
|
|
||||||
"$@" >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function enables IPv6 if it's not disabled and sets verbose mode
|
# This function enables IPv6 if it's not disabled and sets verbose mode
|
||||||
verb_ip6() {
|
verb_ip6() {
|
||||||
set_std_mode # Set STD mode based on VERBOSE
|
set_std_mode # Set STD mode based on VERBOSE
|
||||||
@ -70,7 +30,6 @@ catch_errors() {
|
|||||||
# This function handles errors
|
# This function handles errors
|
||||||
error_handler() {
|
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/main/misc/api.func)
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p "$SPINNER_PID" >/dev/null; then kill "$SPINNER_PID" >/dev/null; fi
|
|
||||||
printf "\e[?25h"
|
printf "\e[?25h"
|
||||||
local exit_code="$?"
|
local exit_code="$?"
|
||||||
local line_number="$1"
|
local line_number="$1"
|
||||||
@ -85,62 +44,15 @@ error_handler() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# This function displays a spinner.
|
|
||||||
spinner() {
|
|
||||||
local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
|
|
||||||
local spin_i=0
|
|
||||||
local interval=0.1
|
|
||||||
printf "\e[?25l"
|
|
||||||
|
|
||||||
local color="${YWB}"
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
printf "\r ${color}%s${CL}" "${frames[spin_i]}"
|
|
||||||
spin_i=$(((spin_i + 1) % ${#frames[@]}))
|
|
||||||
sleep "$interval"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function displays an informational message with a yellow color.
|
|
||||||
msg_info() {
|
|
||||||
local msg="$1"
|
|
||||||
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
|
|
||||||
spinner &
|
|
||||||
SPINNER_PID=$!
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function displays a success message with a green color.
|
|
||||||
msg_ok() {
|
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p "$SPINNER_PID" >/dev/null; then kill "$SPINNER_PID" >/dev/null; fi
|
|
||||||
printf "\e[?25h"
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${BFR}${CM}${GN}${msg}${CL}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function displays a error message with a red color.
|
|
||||||
msg_error() {
|
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p "$SPINNER_PID" >/dev/null; then kill "$SPINNER_PID" >/dev/null; fi
|
|
||||||
printf "\e[?25h"
|
|
||||||
local msg="$1"
|
|
||||||
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This function sets up the Container OS by generating the locale, setting the timezone, and checking the network connection
|
# This function sets up the Container OS by generating the locale, setting the timezone, and checking the network connection
|
||||||
setting_up_container() {
|
setting_up_container() {
|
||||||
msg_info "Setting up Container OS"
|
msg_info "Setting up Container OS"
|
||||||
sed -i "/$LANG/ s/\(^# \)//" /etc/locale.gen
|
|
||||||
locale_line=$(grep -v '^#' /etc/locale.gen | grep -E '^[a-zA-Z]' | awk '{print $1}' | head -n 1)
|
|
||||||
echo "LANG=${locale_line}" >/etc/default/locale
|
|
||||||
locale-gen >/dev/null
|
|
||||||
export LANG=${locale_line}
|
|
||||||
echo "$tz" >/etc/timezone
|
|
||||||
ln -sf /usr/share/zoneinfo/"$tz" /etc/localtime
|
|
||||||
for ((i = RETRY_NUM; i > 0; i--)); do
|
for ((i = RETRY_NUM; i > 0; i--)); do
|
||||||
if [ "$(hostname -I)" != "" ]; then
|
if [ "$(hostname -I)" != "" ]; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
echo 1>&2 -en "${CROSS}${RD} No Network! "
|
echo 1>&2 -en "${CROSS}${RD} No Network! "
|
||||||
sleep "$RETRY_EVERY"
|
sleep $RETRY_EVERY
|
||||||
done
|
done
|
||||||
if [ "$(hostname -I)" = "" ]; then
|
if [ "$(hostname -I)" = "" ]; then
|
||||||
echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}"
|
echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}"
|
||||||
@ -150,7 +62,7 @@ setting_up_container() {
|
|||||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
||||||
systemctl disable -q --now systemd-networkd-wait-online.service
|
systemctl disable -q --now systemd-networkd-wait-online.service
|
||||||
msg_ok "Set up Container OS"
|
msg_ok "Set up Container OS"
|
||||||
msg_ok "Network Connected: ${BL}$(hostname -I)"
|
msg_custom "${CM}" "${GN}" "Network Connected: ${BL}$(hostname -I)"
|
||||||
}
|
}
|
||||||
|
|
||||||
# This function checks the network connection by pinging a known IP address and prompts the user to continue if the internet is not connected
|
# This function checks the network connection by pinging a known IP address and prompts the user to continue if the internet is not connected
|
||||||
@ -178,7 +90,7 @@ network_check() {
|
|||||||
|
|
||||||
# If both IPv4 and IPv6 checks fail, prompt the user
|
# If both IPv4 and IPv6 checks fail, prompt the user
|
||||||
if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then
|
if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then
|
||||||
read -r -p "No Internet detected,would you like to continue anyway? <y/N> " prompt
|
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt
|
||||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||||
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
|
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
|
||||||
else
|
else
|
||||||
@ -187,8 +99,26 @@ network_check() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }')
|
# DNS resolution checks for GitHub-related domains (IPv4 and/or IPv6)
|
||||||
if [[ -z "$RESOLVEDIP" ]]; then msg_error "DNS Lookup Failure"; else msg_ok "DNS Resolved github.com to ${BL}$RESOLVEDIP${CL}"; fi
|
GITHUB_HOSTS=("github.com" "raw.githubusercontent.com" "api.github.com")
|
||||||
|
GITHUB_STATUS="GitHub DNS:"
|
||||||
|
DNS_FAILED=false
|
||||||
|
|
||||||
|
for HOST in "${GITHUB_HOSTS[@]}"; do
|
||||||
|
RESOLVEDIP=$(getent hosts "$HOST" | awk '{ print $1 }' | grep -E '(^([0-9]{1,3}\.){3}[0-9]{1,3}$)|(^[a-fA-F0-9:]+$)' | head -n1)
|
||||||
|
if [[ -z "$RESOLVEDIP" ]]; then
|
||||||
|
GITHUB_STATUS+="$HOST:($DNSFAIL)"
|
||||||
|
DNS_FAILED=true
|
||||||
|
else
|
||||||
|
GITHUB_STATUS+=" $HOST:($DNSOK)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$DNS_FAILED" == true ]]; then
|
||||||
|
fatal "$GITHUB_STATUS"
|
||||||
|
else
|
||||||
|
msg_ok "$GITHUB_STATUS"
|
||||||
|
fi
|
||||||
set -e
|
set -e
|
||||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
||||||
}
|
}
|
||||||
@ -213,11 +143,7 @@ EOF
|
|||||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
||||||
msg_ok "Updated Container OS"
|
msg_ok "Updated Container OS"
|
||||||
|
|
||||||
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/main/misc/tools.func)
|
||||||
msg_ok "Core dependencies installed"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# This function modifies the message of the day (motd) and SSH settings
|
# This function modifies the message of the day (motd) and SSH settings
|
||||||
|
|||||||
@ -79,6 +79,7 @@ mediaserver Media Server
|
|||||||
nextcloud Nextcloud
|
nextcloud Nextcloud
|
||||||
observium Observium
|
observium Observium
|
||||||
odoo Odoo
|
odoo Odoo
|
||||||
|
openldap OpenLDAP
|
||||||
openvpn OpenVPN
|
openvpn OpenVPN
|
||||||
owncloud ownCloud
|
owncloud ownCloud
|
||||||
phpbb phpBB
|
phpbb phpBB
|
||||||
@ -201,7 +202,7 @@ echo "TurnKey ${turnkey} password: ${PASS}" >>~/turnkey-${turnkey}.creds # file
|
|||||||
# Start container
|
# Start container
|
||||||
msg "Starting LXC Container..."
|
msg "Starting LXC Container..."
|
||||||
pct start "$CTID"
|
pct start "$CTID"
|
||||||
sleep 5
|
sleep 10
|
||||||
|
|
||||||
# Get container IP
|
# Get container IP
|
||||||
set +euo pipefail # Turn off error checking
|
set +euo pipefail # Turn off error checking
|
||||||
|
|||||||
Reference in New Issue
Block a user