Compare commits

...

48 Commits

Author SHA1 Message Date
community-scripts-pr-app[bot]
f6d411b992
Update CHANGELOG.md (#4525)
Some checks are pending
Create Changelog Pull Request / update-changelog-pull-request (push) Waiting to run
Close Discussion on PR Merge / close-discussion (push) Waiting to run
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-16 08:49:51 +01:00
Michel Roegl-Brunner
9359f6d883
Enable SSH_KEY without password (#4523) 2025-05-16 09:49:16 +02:00
community-scripts-pr-app[bot]
b021a2c139
Update CHANGELOG.md (#4524)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-16 08:39:54 +01:00
Michel Roegl-Brunner
4de228d41b
Fix Bridge detection (#4522) 2025-05-16 09:39:29 +02:00
community-scripts-pr-app[bot]
7d2e8eaaad
Update CHANGELOG.md (#4521)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-16 06:25:07 +01:00
Slaviša Arežina
ce69a571bc
Updated contributor docs (#4518) 2025-05-16 07:24:38 +02:00
community-scripts-pr-app[bot]
1fdda378ac
Update CHANGELOG.md (#4520)
Some checks failed
Frontend CI/CD / build (push) Waiting to run
Frontend CI/CD / deploy (push) Blocked by required conditions
Create Changelog Pull Request / update-changelog-pull-request (push) Has been cancelled
Close Discussion on PR Merge / close-discussion (push) Has been cancelled
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-16 01:15:21 +01:00
community-scripts-pr-app[bot]
7b62fd4866
Update versions.json (#4519)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-16 02:14:49 +02:00
Slaviša Arežina
0da24e2651
Fix tags (#4513)
Some checks failed
Auto Update .app-files / update-app-files (push) Waiting to run
Create Changelog Pull Request / update-changelog-pull-request (push) Has been cancelled
Close Discussion on PR Merge / close-discussion (push) Has been cancelled
Frontend CI/CD / build (push) Has been cancelled
Frontend CI/CD / deploy (push) Has been cancelled
Crawl Versions from newreleases.io / crawl-versions (push) Has been cancelled
2025-05-15 17:54:10 +02:00
community-scripts-pr-app[bot]
fd689e94ed
Update CHANGELOG.md (#4512)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-15 14:24:23 +01:00
community-scripts-pr-app[bot]
47155ac280
Update .app files (#4510)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2025-05-15 15:23:30 +02:00
community-scripts-pr-app[bot]
aa57bac96d
Update CHANGELOG.md (#4511)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-15 14:22:59 +01:00
community-scripts-pr-app[bot]
24d730c120
Update date in json (#4509)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2025-05-15 14:22:51 +01:00
push-app-to-main[bot]
de9ae6eaa9
bitmagnet (#4493)
* 'Add new script'

* -fsSL

* -fsSL

* add alpine bitmagnet

* add alpine bitmagnet

* Update alpine-bitmagnet.sh

* Update alpine-bitmagnet-install.sh

* Update alpine-bitmagnet.sh

* Update bitmagnet.sh

* Update bitmagnet.json

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ <47820557+MickLesk@users.noreply.github.com>
Co-authored-by: Slaviša Arežina <58952836+tremor021@users.noreply.github.com>
2025-05-15 15:22:16 +02:00
community-scripts-pr-app[bot]
4fd065a4bd
Update CHANGELOG.md (#4508)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-15 14:19:08 +01:00
CanbiZ
e26aac187b
Update tools.func (#4507) 2025-05-15 15:18:41 +02:00
community-scripts-pr-app[bot]
5e63b70e83
Update CHANGELOG.md (#4504)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-15 13:08:19 +01:00
community-scripts-pr-app[bot]
292ab6e54b
Update versions.json (#4503)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-15 14:07:39 +02:00
community-scripts-pr-app[bot]
7d924fac27
Update CHANGELOG.md (#4502)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-15 11:53:46 +01:00
Michel Roegl-Brunner
4b31957617
Fix Bridge detection (#4495) 2025-05-15 12:53:21 +02:00
community-scripts-pr-app[bot]
35c99ae503
Update CHANGELOG.md (#4499)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-15 10:14:39 +01:00
Slaviša Arežina
62189321cc
Update scripts that use read -p (#4498) 2025-05-15 11:13:57 +02:00
community-scripts-pr-app[bot]
59dfdc9af6
Update CHANGELOG.md (#4497)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-15 09:32:13 +01:00
Slaviša Arežina
19cf4d3dc2
Add TAB3 formatting var to core (#4496) 2025-05-15 10:31:37 +02:00
community-scripts-pr-app[bot]
369265a6d5
Update versions.json (#4492)
Some checks failed
Create Changelog Pull Request / update-changelog-pull-request (push) Has been cancelled
Close Discussion on PR Merge / close-discussion (push) Has been cancelled
Frontend CI/CD / build (push) Has been cancelled
Frontend CI/CD / deploy (push) Has been cancelled
Crawl Versions from newreleases.io / crawl-versions (push) Has been cancelled
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-15 02:13:53 +02:00
community-scripts-pr-app[bot]
56f8306960
Update CHANGELOG.md (#4490)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-15 01:11:05 +01:00
CanbiZ
3daf3c3325
HomeAssistant-Core: add Deprecation-Warning for August 2025 (#4489)
Some checks failed
Create Changelog Pull Request / update-changelog-pull-request (push) Has been cancelled
Close Discussion on PR Merge / close-discussion (push) Has been cancelled
Frontend CI/CD / build (push) Has been cancelled
Frontend CI/CD / deploy (push) Has been cancelled
Create Daily Release / create-daily-release (push) Has been cancelled
2025-05-14 22:11:10 +02:00
community-scripts-pr-app[bot]
c36000a6aa
Update CHANGELOG.md (#4488)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-14 18:38:06 +01:00
Maciej Matczak
12265b92e7
Add make installation dependency (#4485) 2025-05-14 19:37:38 +02:00
community-scripts-pr-app[bot]
4e31445038
Update .app files (#4482)
Some checks failed
Create Changelog Pull Request / update-changelog-pull-request (push) Has been cancelled
Close Discussion on PR Merge / close-discussion (push) Has been cancelled
Frontend CI/CD / build (push) Has been cancelled
Frontend CI/CD / deploy (push) Has been cancelled
Crawl Versions from newreleases.io / crawl-versions (push) Has been cancelled
Auto Update .app-files / update-app-files (push) Has been cancelled
Build and Publish Docker Image / build (push) Has been cancelled
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2025-05-14 16:56:33 +02:00
Tobias
c30f96912d
quickfix: fix homarr folder (#4481) 2025-05-14 16:52:46 +02:00
community-scripts-pr-app[bot]
e3860c065e
Update CHANGELOG.md (#4480)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-14 15:09:05 +01:00
community-scripts-pr-app[bot]
110b64df85
Update CHANGELOG.md (#4479)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-14 15:08:46 +01:00
Tobias
e17f7aa6f1
fix fetch_release_and_deploy (#4478) 2025-05-14 16:08:21 +02:00
push-app-to-main[bot]
b4d98b1dd2
odoo (#4477)
* 'Add new script'

* Update ct/odoo.sh

Co-authored-by: Michel Roegl-Brunner <73236783+michelroegl-brunner@users.noreply.github.com>

* Update odoo.sh

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ <47820557+MickLesk@users.noreply.github.com>
Co-authored-by: Michel Roegl-Brunner <73236783+michelroegl-brunner@users.noreply.github.com>
2025-05-14 16:07:57 +02:00
push-app-to-main[bot]
e24636133d
asterisk (#4468)
* 'Add new script'

* Update asterisk.json

* Update asterisk.json

* Update asterisk-install.sh

* Update asterisk.sh

* Update asterisk-install.sh

* Update asterisk-install.sh

* Update asterisk.sh

* noob STD service call

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ <47820557+MickLesk@users.noreply.github.com>
Co-authored-by: Michel Roegl-Brunner <73236783+michelroegl-brunner@users.noreply.github.com>
2025-05-14 14:28:37 +02:00
community-scripts-pr-app[bot]
7d0a964918
Update versions.json (#4470)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-14 14:07:30 +02:00
community-scripts-pr-app[bot]
38c7e747bc
Update CHANGELOG.md (#4469)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-14 12:32:13 +01:00
Slaviša Arežina
180e003978
Alpine-Rclone: Fix location of passwords file (#4465)
* Fix install and update

* Update
2025-05-14 13:31:31 +02:00
community-scripts-pr-app[bot]
4762ea8fae
Update CHANGELOG.md (#4464)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-14 10:03:39 +01:00
community-scripts-pr-app[bot]
4ec3af8e45
Update CHANGELOG.md (#4463)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-14 10:03:18 +01:00
CanbiZ
b816ca6788
Bookstack: fix copy of themes/uploads/storage (#4457) 2025-05-14 11:02:50 +02:00
Michel Roegl-Brunner
d703a8abb2
Add App to do the merging (#4461) 2025-05-14 11:02:41 +02:00
community-scripts-pr-app[bot]
4a1f87727b
Update CHANGELOG.md (#4462)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-14 11:01:22 +02:00
Konstantin Krastev
16c0d09d6b
Update monitor-all.sh (#4437)
 Summary of Changes from the Initial Version
🧩 1. Tag-Based Filtering (Core Feature)
New feature: Only restart instances (VMs or containers) that have the mon-restart tag.

This makes monitoring and auto-restart controllable directly from the Proxmox Web UI, without editing scripts or services.

Set via GUI: VM → Options → Tags → mon-restart

Set via CLI: qm set <vmid> -tags mon-restart or pct set <ctid> -tags mon-restart

This is the primary new control mechanism, making the script safer, more flexible, and user-friendly.

🧰 2. Backward-Compatible Exclusion Mechanism
The original feature that lets you exclude instances via CLI arguments is preserved:

bash
Copy
Edit
./ping-instances.sh 101 300
These IDs will always be skipped regardless of tag.

🧠 3. Intelligent Responsiveness Checks
For VMs:

Uses qm guest cmd <id> ping to check responsiveness via the QEMU guest agent.

No longer relies on network-level ping, which can be misleading or blocked.

For containers (CTs):

Uses traditional ping to IP addresses obtained from pct exec, since CTs don’t support QEMU agent.

 4. Instance Skipping Improvements
Instances are now skipped if:

They are explicitly excluded via CLI.

They are templates.

They are configured with onboot: 0 or missing.

They lack the mon-restart tag, regardless of other status.

🪵 5. Same Logging Behavior
All output continues to go to /var/log/ping-instances.log for persistent tracking.

Verbose messages were added for traceability (e.g., why a VM or CT was skipped).

🎯 Why This Matters
With tag-based control, admins can now manage restart behavior dynamically from the Proxmox Web UI, making the script:

More secure (no accidental restarts).

More maintainable (no script edits needed).

More user-friendly (integrated with the UI workflow).
2025-05-14 11:00:57 +02:00
community-scripts-pr-app[bot]
7740ab68f7
Update CHANGELOG.md (#4459)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-05-14 10:02:15 +02:00
community-scripts-pr-app[bot]
cd61025295
Update date in json (#4458)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2025-05-14 10:01:13 +02:00
CanbiZ
2695e2de1a
Website: re-add documenso & some little bugfixes (#4456) 2025-05-14 10:00:41 +02:00
82 changed files with 1832 additions and 730 deletions

View File

@ -108,13 +108,13 @@ Example:
```bash ```bash
APP="SnipeIT" APP="SnipeIT"
var_tags="asset-management;foss" var_tags="${var_tags:-asset-management;foss}"
var_cpu="2" var_cpu="${var_cpu:-2}"
var_ram="2048" var_ram="${var_ram:-2048}"
var_disk="4" var_disk="${var_disk:-4}"
var_os="debian" var_os="${var_os:-debian}"
var_version="12" var_version="${var_version:-12}"
var_unprivileged="1" var_unprivileged="${var_unprivileged:-1}"
``` ```
## 2.2 **📋 App output & base settings** ## 2.2 **📋 App output & base settings**

View File

@ -6,22 +6,22 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Source: [SOURCE_URL] # Source: [SOURCE_URL]
# App Default Values # App Default Values
APP="[APP_NAME]"
# Name of the app (e.g. Google, Adventurelog, Apache-Guacamole" # Name of the app (e.g. Google, Adventurelog, Apache-Guacamole"
var_tags="[TAGS]" APP="[APP_NAME]"
# Tags for Proxmox VE, maximum 2 pcs., no spaces allowed, separated by a semicolon ; (e.g. database | adblock;dhcp) # Tags for Proxmox VE, maximum 2 pcs., no spaces allowed, separated by a semicolon ; (e.g. database | adblock;dhcp)
var_cpu="[CPU]" var_tags="${var_tags:-[TAGS]}"
# Number of cores (1-X) (e.g. 4) - default are 2 # Number of cores (1-X) (e.g. 4) - default are 2
var_ram="[RAM]" var_cpu="${var_cpu:-[CPU]}"
# Amount of used RAM in MB (e.g. 2048 or 4096) # Amount of used RAM in MB (e.g. 2048 or 4096)
var_disk="[DISK]" var_ram="${var_ram:-[RAM]}"
# Amount of used disk space in GB (e.g. 4 or 10) # Amount of used disk space in GB (e.g. 4 or 10)
var_os="[OS]" var_disk="${var_disk:-[DISK]}"
# Default OS (e.g. debian, ubuntu, alpine) # Default OS (e.g. debian, ubuntu, alpine)
var_version="[VERSION]" var_os="${var_os:-[OS]}"
# Default OS version (e.g. 12 for debian, 24.04 for ubuntu, 3.20 for alpine) # Default OS version (e.g. 12 for debian, 24.04 for ubuntu, 3.20 for alpine)
var_unprivileged="[UNPRIVILEGED]" var_version="${var_version:-[VERSION]}"
# 1 = unprivileged container, 0 = privileged container # 1 = unprivileged container, 0 = privileged container
var_unprivileged="${var_unprivileged:-[UNPRIVILEGED]}"
header_info "$APP" header_info "$APP"
variables variables

View File

@ -152,7 +152,7 @@ Example for a git release:
```bash ```bash
RELEASE=$(curl -fsSL https://api.github.com/repos/snipe/snipe-it/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') RELEASE=$(curl -fsSL https://api.github.com/repos/snipe/snipe-it/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
wget -q "https://github.com/snipe/snipe-it/archive/refs/tags/v${RELEASE}.zip" curl -fsSL "https://github.com/snipe/snipe-it/archive/refs/tags/v${RELEASE}.zip" -o "v${RELEASE}.zip"
``` ```
### 5.2 **Save the version for update checks** ### 5.2 **Save the version for update checks**
@ -163,7 +163,7 @@ wget -q "https://github.com/snipe/snipe-it/archive/refs/tags/v${RELEASE}.zip"
Example: Example:
```bash ```bash
echo "${RELEASE}" >"/opt/AppName_version.txt" echo "${RELEASE}" >/opt/${APPLICATION}_version.txt
``` ```
--- ---
@ -184,7 +184,7 @@ msg_info "Installing Dependencies"
$STD apt-get install -y ... $STD apt-get install -y ...
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
read -p "Do you wish to enable HTTPS mode? (y/N): " httpschoice read -p "${TAB3}Do you wish to enable HTTPS mode? (y/N): " httpschoice
``` ```
### 6.2 **Verbosity** ### 6.2 **Verbosity**

View File

@ -35,11 +35,9 @@ $STD mysql -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH
echo "Database User: $DB_USER" echo "Database User: $DB_USER"
echo "Database Password: $DB_PASS" echo "Database Password: $DB_PASS"
echo "Database Name: $DB_NAME" echo "Database Name: $DB_NAME"
} >> ~/$APP_NAME.creds } >>~/"$APP_NAME".creds
msg_ok "Set up Database" msg_ok "Set up Database"
# Temp
# Setup App # Setup App
msg_info "Setup ${APPLICATION}" msg_info "Setup ${APPLICATION}"
RELEASE=$(curl -fsSL https://api.github.com/repos/[REPO]/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') RELEASE=$(curl -fsSL https://api.github.com/repos/[REPO]/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
@ -49,12 +47,12 @@ mv "${APPLICATION}-${RELEASE}/" "/opt/${APPLICATION}"
# #
# #
# #
echo "${RELEASE}" >/opt/${APPLICATION}_version.txt echo "${RELEASE}" >/opt/"${APPLICATION}"_version.txt
msg_ok "Setup ${APPLICATION}" msg_ok "Setup ${APPLICATION}"
# Creating Service (if needed) # Creating Service (if needed)
msg_info "Creating Service" msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/${APPLICATION}.service cat <<EOF >/etc/systemd/system/"${APPLICATION}".service
[Unit] [Unit]
Description=${APPLICATION} Service Description=${APPLICATION} Service
After=network.target After=network.target
@ -66,7 +64,7 @@ Restart=always
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
EOF EOF
systemctl enable -q --now ${APPLICATION} systemctl enable -q --now "${APPLICATION}"
msg_ok "Created Service" msg_ok "Created Service"
motd_ssh motd_ssh
@ -74,7 +72,7 @@ customize
# Cleanup # Cleanup
msg_info "Cleaning up" msg_info "Cleaning up"
rm -f ${RELEASE}.zip rm -f "${RELEASE}".zip
$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"

View File

@ -5,7 +5,7 @@ on:
branches: branches:
- main - main
paths: paths:
- 'ct/**.sh' - "ct/**.sh"
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@ -25,6 +25,13 @@ jobs:
app-id: ${{ vars.APP_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }} private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Generate a token for PR approval and merge
id: generate-token-merge
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID_APPROVE_AND_MERGE }}
private-key: ${{ secrets.APP_KEY_APPROVE_AND_MERGE }}
# Step 1: Checkout repository # Step 1: Checkout repository
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v2
@ -94,9 +101,11 @@ jobs:
- name: Approve pull request and merge - name: Approve pull request and merge
if: env.changed == 'true' if: env.changed == 'true'
env: env:
GH_TOKEN: ${{ secrets.PAT_AUTOMERGE }} GH_TOKEN: ${{ steps.generate-token-merge.outputs.token }}
run: | run: |
PR_NUMBER=$(gh pr list --head "pr-update-app-files" --json number --jq '.[].number') git config --global user.name "github-actions-automege[bot]"
git config --global user.email "github-actions-automege[bot]@users.noreply.github.com"
PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve gh pr review $PR_NUMBER --approve
gh pr merge $PR_NUMBER --squash --admin gh pr merge $PR_NUMBER --squash --admin

View File

@ -24,6 +24,13 @@ jobs:
app-id: ${{ vars.APP_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }} private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Generate a token for PR approval and merge
id: generate-token-merge
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID_APPROVE_AND_MERGE }}
private-key: ${{ secrets.APP_KEY_APPROVE_AND_MERGE }}
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
@ -267,20 +274,12 @@ jobs:
- name: Approve pull request and merge - name: Approve pull request and merge
if: env.changed == 'true' if: env.changed == 'true'
env: env:
GH_TOKEN: ${{ secrets.PAT_AUTOMERGE }} GH_TOKEN: ${{ steps.generate-token-merge.outputs.token }}
run: | run: |
git config --global user.name "github-actions-automege[bot]"
git config --global user.email "github-actions-automege[bot]@users.noreply.github.com"
PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number') PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve gh pr review $PR_NUMBER --approve
gh pr merge $PR_NUMBER --squash --admin gh pr merge $PR_NUMBER --squash --admin
fi fi
- name: Re-approve pull request after update
if: env.changed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve
fi

View File

@ -5,7 +5,7 @@ on:
branches: branches:
- main - main
paths: paths:
- 'frontend/public/json/**.json' - "frontend/public/json/**.json"
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@ -25,6 +25,13 @@ jobs:
app-id: ${{ vars.APP_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }} private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Generate a token for PR approval and merge
id: generate-token-merge
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID_APPROVE_AND_MERGE }}
private-key: ${{ secrets.APP_KEY_APPROVE_AND_MERGE }}
- name: Generate dynamic branch name - name: Generate dynamic branch name
id: timestamp id: timestamp
run: echo "BRANCH_NAME=pr-update-json-$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV run: echo "BRANCH_NAME=pr-update-json-$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV
@ -126,12 +133,15 @@ jobs:
if [ -n "$PR_NUMBER" ]; then if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve gh pr review $PR_NUMBER --approve
fi fi
- name: Approve pull request and merge - name: Approve pull request and merge
if: env.changed == 'true' if: env.changed == 'true'
env: env:
GH_TOKEN: ${{ secrets.PAT_AUTOMERGE }} GH_TOKEN: ${{ steps.generate-token-merge.outputs.token }}
run: | run: |
PR_NUMBER=$(gh pr list --head "${{ env.BRANCH_NAME }}" --json number --jq '.[].number') git config --global user.name "github-actions-automege[bot]"
git config --global user.email "github-actions-automege[bot]@users.noreply.github.com"
PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
if [ -n "$PR_NUMBER" ]; then if [ -n "$PR_NUMBER" ]; then
gh pr review $PR_NUMBER --approve gh pr review $PR_NUMBER --approve
gh pr merge $PR_NUMBER --squash --admin gh pr merge $PR_NUMBER --squash --admin

View File

@ -14,8 +14,68 @@ 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-05-16
### 🧰 Maintenance
- #### 💾 Core
- [core] Enable SSH_KEY and SSH without password [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#4523](https://github.com/community-scripts/ProxmoxVE/pull/4523))
- [core] Fix Bridge detection in Advanced Mode [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#4522](https://github.com/community-scripts/ProxmoxVE/pull/4522))
- #### 📂 Github
- Updates to contributor docs/guide [@tremor021](https://github.com/tremor021) ([#4518](https://github.com/community-scripts/ProxmoxVE/pull/4518))
## 2025-05-15
### 🆕 New Scripts
- bitmagnet ([#4493](https://github.com/community-scripts/ProxmoxVE/pull/4493))
### 🚀 Updated Scripts
- core: Add TAB3 formatting var to core [@tremor021](https://github.com/tremor021) ([#4496](https://github.com/community-scripts/ProxmoxVE/pull/4496))
- Update scripts that use "read -p" to properly indent text [@tremor021](https://github.com/tremor021) ([#4498](https://github.com/community-scripts/ProxmoxVE/pull/4498))
- #### ✨ New Features
- tools.func: fix some things & add ruby default function [@MickLesk](https://github.com/MickLesk) ([#4507](https://github.com/community-scripts/ProxmoxVE/pull/4507))
### 🧰 Maintenance
- #### 💾 Core
- core: fix bridge detection for OVS [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#4495](https://github.com/community-scripts/ProxmoxVE/pull/4495))
## 2025-05-14 ## 2025-05-14
### 🆕 New Scripts
- odoo ([#4477](https://github.com/community-scripts/ProxmoxVE/pull/4477))
- asterisk ([#4468](https://github.com/community-scripts/ProxmoxVE/pull/4468))
### 🚀 Updated Scripts
- fix: fetch_release_and_deploy function [@CrazyWolf13](https://github.com/CrazyWolf13) ([#4478](https://github.com/community-scripts/ProxmoxVE/pull/4478))
- Website: re-add documenso & some little bugfixes [@MickLesk](https://github.com/MickLesk) ([#4456](https://github.com/community-scripts/ProxmoxVE/pull/4456))
- #### 🐞 Bug Fixes
- Add make installation dependency to Actual Budget script [@maciejmatczak](https://github.com/maciejmatczak) ([#4485](https://github.com/community-scripts/ProxmoxVE/pull/4485))
- Bookstack: fix copy of themes/uploads/storage [@MickLesk](https://github.com/MickLesk) ([#4457](https://github.com/community-scripts/ProxmoxVE/pull/4457))
- Alpine-Rclone: Fix location of passwords file [@tremor021](https://github.com/tremor021) ([#4465](https://github.com/community-scripts/ProxmoxVE/pull/4465))
- #### ✨ New Features
- monitor-all: improvements - tag based filtering [@grizmin](https://github.com/grizmin) ([#4437](https://github.com/community-scripts/ProxmoxVE/pull/4437))
### 🧰 Maintenance
- #### 📂 Github
- Add Github app for auto PR merge [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#4461](https://github.com/community-scripts/ProxmoxVE/pull/4461))
## 2025-05-13 ## 2025-05-13
### 🆕 New Scripts ### 🆕 New Scripts

89
ct/alpine-bitmagnet.sh Normal file
View File

@ -0,0 +1,89 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/bitmagnet-io/bitmagnet
APP="Alpine-bitmagnet"
var_tags="${var_tags:-alpine;torrent}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-3}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.21}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
if [[ ! -d /opt/bitmagnet ]]; then
msg_error "No ${APP} Installation Found!"
exit 1
fi
RELEASE=$(curl -fsSL https://api.github.com/repos/bitmagnet-io/bitmagnet/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
if [ "${RELEASE}" != "$(cat /opt/bitmagnet_version.txt)" ] || [ ! -f /opt/bitmagnet_version.txt ]; then
msg_info "Backing up database"
rm -f /tmp/backup.sql
$STD sudo -u postgres pg_dump \
--column-inserts \
--data-only \
--on-conflict-do-nothing \
--rows-per-insert=1000 \
--table=metadata_sources \
--table=content \
--table=content_attributes \
--table=content_collections \
--table=content_collections_content \
--table=torrent_sources \
--table=torrents \
--table=torrent_files \
--table=torrent_hints \
--table=torrent_contents \
--table=torrent_tags \
--table=torrents_torrent_sources \
--table=key_values \
bitmagnet \
>/tmp/backup.sql
mv /tmp/backup.sql /opt/
msg_ok "Database backed up"
msg_info "Updating ${APP} from $(cat /opt/bitmagnet_version.txt) to ${RELEASE}"
$STD apk -U upgrade
$STD service bitmagnet stop
[ -f /opt/bitmagnet/.env ] && cp /opt/bitmagnet/.env /opt/
[ -f /opt/bitmagnet/config.yml ] && cp /opt/bitmagnet/config.yml /opt/
rm -rf /opt/bitmagnet/*
temp_file=$(mktemp)
curl -fsSL "https://github.com/bitmagnet-io/bitmagnet/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
tar zxf "$temp_file" --strip-components=1 -C /opt/bitmagnet
cd /opt/bitmagnet
VREL=v$RELEASE
$STD go build -ldflags "-s -w -X github.com/bitmagnet-io/bitmagnet/internal/version.GitTag=$VREL"
chmod +x bitmagnet
[ -f "/opt/.env" ] && cp "/opt/.env" /opt/bitmagnet/
[ -f "/opt/config.yml" ] && cp "/opt/config.yml" /opt/bitmagnet/
rm -f "$temp_file"
echo "${RELEASE}" >/opt/bitmagnet_version.txt
$STD service bitmagnet start
msg_ok "Updated Successfully"
else
msg_ok "No update required. ${APP} is already at ${RELEASE}"
fi
exit 0
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following IP:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3333${CL}"

View File

@ -28,7 +28,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit 1 exit 1
fi fi
RELEASE=$(curl -s https://api.github.com/repos/rclone/rclone/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') RELEASE=$(curl -s https://api.github.com/repos/rclone/rclone/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
if [ "${RELEASE}" != "$(cat /opt/rclone_version.txt)" ] || [ ! -f /opt/rclone_version.txt ]; then if [ "${RELEASE}" != "$(cat /opt/rclone_version.txt)" ] || [ ! -f /opt/rclone_version.txt ]; then
msg_info "Updating ${APP} LXC" msg_info "Updating ${APP} LXC"

35
ct/asterisk.sh Normal file
View File

@ -0,0 +1,35 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://asterisk.org/
APP="Asterisk"
var_tags="${var_tags:-telephone;pbx}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
msg_error "No Update function provided for ${APP} LXC"
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"

98
ct/bitmagnet.sh Normal file
View File

@ -0,0 +1,98 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/bitmagnet/bitmagnet
APP="Bitmagnet"
var_tags="${var_tags:-os}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/bitmagnet ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
RELEASE=$(curl -fsSL https://api.github.com/repos/bitmagnet-io/bitmagnet/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
msg_info "Stopping Service"
systemctl stop bitmagnet-web
msg_ok "Stopped Service"
msg_info "Backing up database"
rm -f /tmp/backup.sql
$STD sudo -u postgres pg_dump \
--column-inserts \
--data-only \
--on-conflict-do-nothing \
--rows-per-insert=1000 \
--table=metadata_sources \
--table=content \
--table=content_attributes \
--table=content_collections \
--table=content_collections_content \
--table=torrent_sources \
--table=torrents \
--table=torrent_files \
--table=torrent_hints \
--table=torrent_contents \
--table=torrent_tags \
--table=torrents_torrent_sources \
--table=key_values \
bitmagnet \
>/tmp/backup.sql
mv /tmp/backup.sql /opt/
msg_ok "Database backed up"
msg_info "Updating ${APP} to v${RELEASE}"
[ -f /opt/bitmagnet/.env ] && cp /opt/bitmagnet/.env /opt/
[ -f /opt/bitmagnet/config.yml ] && cp /opt/bitmagnet/config.yml /opt/
rm -rf /opt/bitmagnet/*
temp_file=$(mktemp)
curl -fsSL "https://github.com/bitmagnet-io/bitmagnet/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
tar zxf "$temp_file" --strip-components=1 -C /opt/bitmagnet
cd /opt/bitmagnet
VREL=v$RELEASE
$STD go build -ldflags "-s -w -X github.com/bitmagnet-io/bitmagnet/internal/version.GitTag=$VREL"
chmod +x bitmagnet
[ -f "/opt/.env" ] && cp "/opt/.env" /opt/bitmagnet/
[ -f "/opt/config.yml" ] && cp "/opt/config.yml" /opt/bitmagnet/
echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated $APP to v${RELEASE}"
msg_info "Starting Service"
systemctl start bitmagnet-web
msg_ok "Started Service"
msg_info "Cleaning up"
rm -f "$temp_file"
msg_ok "Cleaned"
msg_ok "Updated Successfully"
else
msg_ok "No update required. ${APP} is already at v${RELEASE}"
fi
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3333${CL}"

View File

@ -39,9 +39,9 @@ function update_script() {
unzip -q "/opt/BookStack-${RELEASE}.zip" -d /opt unzip -q "/opt/BookStack-${RELEASE}.zip" -d /opt
mv "/opt/BookStack-${RELEASE}" /opt/bookstack mv "/opt/BookStack-${RELEASE}" /opt/bookstack
cp /opt/bookstack-backup/.env /opt/bookstack/.env cp /opt/bookstack-backup/.env /opt/bookstack/.env
cp -r /opt/bookstack-backup/public/uploads/* /opt/bookstack/public/uploads/ || true [[ -d /opt/bookstack-backup/public/uploads ]] && cp -a /opt/bookstack-backup/public/uploads/. /opt/bookstack/public/uploads/
cp -r /opt/bookstack-backup/storage/uploads/* /opt/bookstack/storage/uploads/ || true [[ -d /opt/bookstack-backup/storage/uploads ]] && cp -a /opt/bookstack-backup/storage/uploads/. /opt/bookstack/storage/uploads/
cp -r /opt/bookstack-backup/themes/* /opt/bookstack/themes/ || true [[ -d /opt/bookstack-backup/themes ]] && cp -a /opt/bookstack-backup/themes/. /opt/bookstack/themes/
cd /opt/bookstack cd /opt/bookstack
export COMPOSER_ALLOW_SUPERUSER=1 export COMPOSER_ALLOW_SUPERUSER=1
$STD composer install --no-dev $STD composer install --no-dev

View File

@ -6,7 +6,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Source: https://github.com/AlexxIT/go2rtc # Source: https://github.com/AlexxIT/go2rtc
APP="go2rtc" APP="go2rtc"
var_tags="${var_tags:-recorder;video}" var_tags="${var_tags:-streaming;video}"
var_cpu="${var_cpu:-2}" var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}" var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}" var_disk="${var_disk:-4}"

View File

@ -0,0 +1,6 @@
___ __ _ __ _ __ __
/ | / /___ (_)___ ___ / /_ (_) /_____ ___ ____ _____ _____ ___ / /_
/ /| | / / __ \/ / __ \/ _ \______/ __ \/ / __/ __ `__ \/ __ `/ __ `/ __ \/ _ \/ __/
/ ___ |/ / /_/ / / / / / __/_____/ /_/ / / /_/ / / / / / /_/ / /_/ / / / / __/ /_
/_/ |_/_/ .___/_/_/ /_/\___/ /_.___/_/\__/_/ /_/ /_/\__,_/\__, /_/ /_/\___/\__/
/_/ /____/

6
ct/headers/asterisk Normal file
View File

@ -0,0 +1,6 @@
___ __ _ __
/ | _____/ /____ _____(_)____/ /__
/ /| | / ___/ __/ _ \/ ___/ / ___/ //_/
/ ___ |(__ ) /_/ __/ / / (__ ) ,<
/_/ |_/____/\__/\___/_/ /_/____/_/|_|

6
ct/headers/bitmagnet Normal file
View File

@ -0,0 +1,6 @@
____ _ __ __
/ __ )(_) /_____ ___ ____ _____ _____ ___ / /_
/ __ / / __/ __ `__ \/ __ `/ __ `/ __ \/ _ \/ __/
/ /_/ / / /_/ / / / / / /_/ / /_/ / / / / __/ /_
/_____/_/\__/_/ /_/ /_/\__,_/\__, /_/ /_/\___/\__/
/____/

View File

@ -1,6 +1,6 @@
__ __ __
/ / / /___ ____ ___ ____ ___________ / /_ ____ ____ ___ ____ ___________
/ /_/ / __ \/ __ `__ \/ __ `/ ___/ ___/ / __ \/ __ \/ __ `__ \/ __ `/ ___/ ___/
/ __ / /_/ / / / / / / /_/ / / / / / / / / /_/ / / / / / / /_/ / / / /
/_/ /_/\____/_/ /_/ /_/\__,_/_/ /_/ /_/ /_/\____/_/ /_/ /_/\__,_/_/ /_/

6
ct/headers/odoo Normal file
View File

@ -0,0 +1,6 @@
____ __
/ __ \____/ /___ ____
/ / / / __ / __ \/ __ \
/ /_/ / /_/ / /_/ / /_/ /
\____/\__,_/\____/\____/

View File

@ -5,7 +5,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://homarr.dev/ # Source: https://homarr.dev/
APP="Homarr" APP="homarr"
var_tags="${var_tags:-arr;dashboard}" var_tags="${var_tags:-arr;dashboard}"
var_cpu="${var_cpu:-2}" var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}" var_ram="${var_ram:-4096}"
@ -151,7 +151,7 @@ EOF
systemctl start homarr systemctl start homarr
msg_ok "Started Services" msg_ok "Started Services"
msg_ok "Updated Successfully" msg_ok "Updated Successfully"
read -p "It's recommended to reboot the LXC after an update, would you like to reboot the LXC now ? (y/n): " choice read -p "${TAB3}It's recommended to reboot the LXC after an update, would you like to reboot the LXC now ? (y/n): " choice
if [[ "$choice" =~ ^[Yy]$ ]]; then if [[ "$choice" =~ ^[Yy]$ ]]; then
reboot reboot
fi fi

View File

@ -114,7 +114,7 @@ function update_script() {
if [ "$UPD" == "3" ]; then if [ "$UPD" == "3" ]; then
set +Eeuo pipefail set +Eeuo pipefail
read -r -p "Would you like to use No Authentication? <y/N> " prompt read -r -p "${TAB3}Would you like to use No Authentication? <y/N> " prompt
msg_info "Installing FileBrowser" msg_info "Installing FileBrowser"
RELEASE=$(curl -fsSL https://api.github.com/repos/filebrowser/filebrowser/releases/latest | grep -o '"tag_name": ".*"' | sed 's/"//g' | sed 's/tag_name: //g') RELEASE=$(curl -fsSL https://api.github.com/repos/filebrowser/filebrowser/releases/latest | grep -o '"tag_name": ".*"' | sed 's/"//g' | sed 's/tag_name: //g')
$STD curl -fsSL https://github.com/filebrowser/filebrowser/releases/download/$RELEASE/linux-amd64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin $STD curl -fsSL https://github.com/filebrowser/filebrowser/releases/download/$RELEASE/linux-amd64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin

71
ct/odoo.sh Normal file
View File

@ -0,0 +1,71 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/odoo/odoo
APP="Odoo"
var_tags="${var_tags:-erp}"
var_disk="${var_disk:-6}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/odoo/odoo.conf ]]; then
msg_error "No ${APP} Installation Found!"
exit 1
fi
RELEASE=$(curl -fsSL https://nightly.odoo.com/ | grep -oE 'href="[0-9]+\.[0-9]+/nightly"' | head -n1 | cut -d'"' -f2 | cut -d/ -f1)
LATEST_VERSION=$(curl -fsSL "https://nightly.odoo.com/${RELEASE}/nightly/deb/" |
grep -oP "odoo_${RELEASE}\.\d+_all\.deb" |
sed -E "s/odoo_(${RELEASE}\.[0-9]+)_all\.deb/\1/" |
sort -V |
tail -n1)
if [[ "${LATEST_VERSION}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
msg_info "Stopping ${APP} service"
systemctl stop odoo
msg_ok "Stopped ${APP}"
msg_info "Updating ${APP} to ${LATEST_VERSION}"
curl -fsSL https://nightly.odoo.com/${RELEASE}/nightly/deb/odoo_${RELEASE}.latest_all.deb -o /opt/odoo.deb
$STD apt install -y /opt/odoo.deb
echo "$LATEST_VERSION" >/opt/${APP}_version.txt
msg_ok "Updated ${APP} to ${LATEST_VERSION}"
msg_info "Starting ${APP} service"
systemctl start odoo
msg_ok "Started ${APP}"
msg_info "Cleaning Up"
rm -f /opt/odoo.deb
msg_ok "Cleaned"
msg_ok "Updated Successfully"
else
msg_ok "No update required. ${APP} is already at ${LATEST_VERSION}"
fi
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8069${CL}"

View File

@ -49,7 +49,7 @@
}, },
{ {
"type": "info", "type": "info",
"text": "`htpasswd -b -B /opt/rclone/login.pwd newuser newuserpassword` to add more users." "text": "`htpasswd -b -B /opt/login.pwd newuser newuserpassword` to add more users."
} }
] ]
} }

View File

@ -0,0 +1,33 @@
{
"name": "Asterisk",
"slug": "asterisk",
"categories": [0],
"date_created": "2025-05-14",
"type": "ct",
"updateable": false,
"privileged": false,
"interface_port": null,
"documentation": "https://docs.asterisk.org/",
"config_path": "/etc/asterisk",
"website": "https://asterisk.org/",
"logo": "https://docs.asterisk.org/favicon.ico",
"description": "Asterisk is an open-source framework for building communications applications, most commonly used as a phone system (PBX). Developed by Digium (now part of Sangoma), it turns a standard computer into a powerful telephony server.",
"install_methods": [
{
"type": "default",
"script": "ct/asterisk.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 4,
"os": "Debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@ -0,0 +1,51 @@
{
"name": "Bitmagnet",
"slug": "bitmagnet",
"categories": [
11
],
"date_created": "2025-05-15",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3333,
"documentation": "https://bitmagnet.io/setup.html",
"website": "https://bitmagnet.io/",
"logo": "https://raw.githubusercontent.com/selfhst/icons/refs/heads/main/webp/bitmagnet.webp",
"config_path": "`/opt/bitmagnet/config.yml` or `/opt/bitmagnet/.env`",
"description": "A self-hosted BitTorrent indexer, DHT crawler, content classifier and torrent search engine with web UI, GraphQL API and Servarr stack integration.",
"install_methods": [
{
"type": "default",
"script": "ct/bitmagnet.sh",
"resources": {
"cpu": 2,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
},
{
"type": "alpine",
"script": "ct/alpine-bitmagnet.sh",
"resources": {
"cpu": 2,
"ram": 1024,
"hdd": 3,
"os": "alpine",
"version": "3.21"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "During installation you will be asked to enter your TMDB API key, if you wanna use it. Make sure you have it ready.",
"type": "info"
}
]
}

View File

@ -0,0 +1,35 @@
{
"name": "Documenso",
"slug": "documenso",
"categories": [
12
],
"date_created": "2025-05-14",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://documenso.com/",
"website": "https://documenso.com/",
"logo": "https://raw.githubusercontent.com/selfhst/icons/refs/heads/main/svg/documenso.svg",
"config_path": "/opt/documenso/.env",
"description": "Signing documents digitally should be fast and easy and should be the best practice for every document signed worldwide. This is technically quite easy today, but it also introduces a new party to every signature: The signing tool providers. While this is not a problem in itself, it should make us think about how we want these providers of trust to work. Documenso aims to be the world's most trusted document-signing tool. This trust is built by empowering you to self-host Documenso and review how it works under the hood.",
"install_methods": [
{
"type": "default",
"script": "ct/documenso.sh",
"resources": {
"cpu": 4,
"ram": 6144,
"hdd": 10,
"os": "Debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "helper-scripts@local.com",
"password": "helper-scripts"
},
"notes": []
}

View File

@ -41,7 +41,7 @@
"type": "warning" "type": "warning"
}, },
{ {
"text": "Use Ubuntu 24.10 ONLY", "text": "Deprecation-Warning: This Core-based setup will be deprecated by August 2025. Use Home Assistant OS is strongly recommended to ensure long-term stability and updates.",
"type": "warning" "type": "warning"
}, },
{ {

View File

@ -0,0 +1,40 @@
{
"name": "Odoo",
"slug": "odoo",
"categories": [
25
],
"date_created": "2025-05-14",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8069,
"documentation": "https://www.odoo.com/en_EN/page/docs",
"website": "https://www.odoo.com/",
"logo": "https://raw.githubusercontent.com/selfhst/icons/refs/heads/main/svg/odoo.svg",
"config_path": "/etc/odoo/odoo.conf",
"description": "Odoo is a comprehensive open-source business platform made up of modular apps that cover key areas such as CRM, accounting, inventory, sales, project management, HR, helpdesk, and e-commerce. All modules are tightly integrated, allowing businesses to fully digitize and automate their workflows. Its modular design makes it suitable for both small companies and large enterprises, with flexibility to adapt to different industries. Odoo combines user-friendliness with powerful functionality, offering a unified solution for managing a wide range of business operations.",
"install_methods": [
{
"type": "default",
"script": "ct/odoo.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 6,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "admin",
"password": "admin"
},
"notes": [
{
"text": "Database Credentials: `cat ~/odoo.creds`",
"type": "info"
}
]
}

View File

@ -1,18 +1,163 @@
[ [
{ {
"name": "netbox-community/netbox", "name": "ipfs/kubo",
"version": "v4.3.1", "version": "v0.34.1",
"date": "2025-05-13T19:45:00Z" "date": "2025-03-25T18:11:12Z"
},
{
"name": "coder/code-server",
"version": "v4.100.2",
"date": "2025-05-15T23:02:46Z"
},
{
"name": "influxdata/influxdb",
"version": "v3.0.3",
"date": "2025-05-15T19:56:23Z"
},
{
"name": "clusterzx/paperless-ai",
"version": "v2.7.8",
"date": "2025-05-15T18:04:54Z"
},
{
"name": "goauthentik/authentik",
"version": "version/2025.4.1",
"date": "2025-05-15T17:48:29Z"
},
{
"name": "cloudflare/cloudflared",
"version": "2025.5.0",
"date": "2025-05-15T17:09:50Z"
},
{
"name": "apache/cassandra",
"version": "4.1.9-tentative",
"date": "2025-05-15T15:52:53Z"
},
{
"name": "VictoriaMetrics/VictoriaMetrics",
"version": "pmm-6401-v1.117.1",
"date": "2025-05-15T15:45:22Z"
},
{
"name": "ellite/Wallos",
"version": "v3.1.1",
"date": "2025-05-15T15:17:57Z"
},
{
"name": "bunkerity/bunkerweb",
"version": "v1.6.1",
"date": "2025-03-15T17:29:17Z"
},
{
"name": "Checkmk/checkmk",
"version": "v2.4.0p1",
"date": "2025-05-15T12:41:12Z"
},
{
"name": "zwave-js/zwave-js-ui",
"version": "v10.5.1",
"date": "2025-05-15T09:59:28Z"
},
{
"name": "theonedev/onedev",
"version": "v11.9.7",
"date": "2025-05-15T07:03:28Z"
},
{
"name": "mattermost/mattermost",
"version": "v10.6.5",
"date": "2025-05-15T07:06:52Z"
},
{
"name": "cross-seed/cross-seed",
"version": "v6.12.4",
"date": "2025-05-11T11:41:32Z"
},
{
"name": "morpheus65535/bazarr",
"version": "v1.5.2",
"date": "2025-05-11T16:40:55Z"
},
{
"name": "Jackett/Jackett",
"version": "v0.22.1900",
"date": "2025-05-15T06:01:04Z"
},
{
"name": "FlowiseAI/Flowise",
"version": "flowise@3.0.0",
"date": "2025-05-15T01:49:47Z"
},
{
"name": "ollama/ollama",
"version": "v0.7.0-rc1",
"date": "2025-05-14T03:58:02Z"
},
{
"name": "advplyr/audiobookshelf",
"version": "v2.22.0",
"date": "2025-05-14T22:30:59Z"
}, },
{ {
"name": "glanceapp/glance", "name": "glanceapp/glance",
"version": "v0.8.1", "version": "v0.8.2",
"date": "2025-05-13T19:42:42Z" "date": "2025-05-14T21:34:41Z"
}, },
{ {
"name": "pocketbase/pocketbase", "name": "Ombi-app/Ombi",
"version": "v0.28.1", "version": "v4.47.1",
"date": "2025-05-13T18:45:47Z" "date": "2025-01-05T21:14:23Z"
},
{
"name": "Luligu/matterbridge",
"version": "3.0.2",
"date": "2025-05-14T20:38:06Z"
},
{
"name": "NodeBB/NodeBB",
"version": "v4.4.0",
"date": "2025-05-14T20:36:37Z"
},
{
"name": "esphome/esphome",
"version": "2025.4.2",
"date": "2025-05-11T22:18:43Z"
},
{
"name": "keycloak/keycloak",
"version": "26.2.4",
"date": "2025-05-08T09:10:10Z"
},
{
"name": "MediaBrowser/Emby.Releases",
"version": "4.8.11.0",
"date": "2025-03-10T06:39:11Z"
},
{
"name": "Athou/commafeed",
"version": "5.9.0",
"date": "2025-05-14T15:29:48Z"
},
{
"name": "juanfont/headscale",
"version": "v0.26.0",
"date": "2025-05-14T15:12:14Z"
},
{
"name": "mongodb/mongo",
"version": "r6.0.24-alpha0",
"date": "2025-05-14T14:52:41Z"
},
{
"name": "motioneye-project/motioneye",
"version": "0.42.1",
"date": "2020-06-07T07:27:04Z"
},
{
"name": "firefly-iii/firefly-iii",
"version": "v6.2.12",
"date": "2025-04-20T19:22:17Z"
}, },
{ {
"name": "jenkinsci/jenkins", "name": "jenkinsci/jenkins",
@ -20,9 +165,39 @@
"date": "2025-05-13T18:33:42Z" "date": "2025-05-13T18:33:42Z"
}, },
{ {
"name": "mongodb/mongo", "name": "nzbgetcom/nzbget",
"version": "r6.0.23", "version": "v25.0",
"date": "2025-05-13T18:28:23Z" "date": "2025-05-12T09:12:04Z"
},
{
"name": "wazuh/wazuh",
"version": "coverity-w20-4.13.0",
"date": "2025-05-14T12:06:20Z"
},
{
"name": "blakeblackshear/frigate",
"version": "v0.14.1",
"date": "2024-08-29T22:32:51Z"
},
{
"name": "runtipi/runtipi",
"version": "nightly",
"date": "2025-05-14T06:48:39Z"
},
{
"name": "TandoorRecipes/recipes",
"version": "2.0.0-alpha-4",
"date": "2025-05-14T05:01:45Z"
},
{
"name": "netbox-community/netbox",
"version": "v4.3.1",
"date": "2025-05-13T19:45:00Z"
},
{
"name": "pocketbase/pocketbase",
"version": "v0.28.1",
"date": "2025-05-13T18:45:47Z"
}, },
{ {
"name": "OctoPrint/OctoPrint", "name": "OctoPrint/OctoPrint",
@ -34,11 +209,6 @@
"version": "8.0.1", "version": "8.0.1",
"date": "2025-05-13T13:31:53Z" "date": "2025-05-13T13:31:53Z"
}, },
{
"name": "theonedev/onedev",
"version": "v11.9.6",
"date": "2025-05-13T12:16:17Z"
},
{ {
"name": "element-hq/synapse", "name": "element-hq/synapse",
"version": "v1.129.0", "version": "v1.129.0",
@ -54,46 +224,16 @@
"version": "6.3.0-alpha.4", "version": "6.3.0-alpha.4",
"date": "2025-05-13T11:18:29Z" "date": "2025-05-13T11:18:29Z"
}, },
{
"name": "firefly-iii/firefly-iii",
"version": "v6.2.12",
"date": "2025-04-20T19:22:17Z"
},
{
"name": "cross-seed/cross-seed",
"version": "v6.12.4",
"date": "2025-05-11T11:41:32Z"
},
{
"name": "Jackett/Jackett",
"version": "v0.22.1893",
"date": "2025-05-13T05:57:50Z"
},
{ {
"name": "zitadel/zitadel", "name": "zitadel/zitadel",
"version": "v2.65.9", "version": "v2.65.9",
"date": "2025-05-13T05:14:39Z" "date": "2025-05-13T05:14:39Z"
}, },
{
"name": "ollama/ollama",
"version": "v0.6.9-rc0",
"date": "2025-05-10T18:57:30Z"
},
{ {
"name": "go-gitea/gitea", "name": "go-gitea/gitea",
"version": "v1.23.8", "version": "v1.23.8",
"date": "2025-05-12T22:40:50Z" "date": "2025-05-12T22:40:50Z"
}, },
{
"name": "MediaBrowser/Emby.Releases",
"version": "4.8.11.0",
"date": "2025-03-10T06:39:11Z"
},
{
"name": "keycloak/keycloak",
"version": "26.2.4",
"date": "2025-05-08T09:10:10Z"
},
{ {
"name": "leiweibau/Pi.Alert", "name": "leiweibau/Pi.Alert",
"version": "v2025-05-11", "version": "v2025-05-11",
@ -104,16 +244,6 @@
"version": "v2.1.0.118-2.1.0.118_canary_2025-05-12", "version": "v2.1.0.118-2.1.0.118_canary_2025-05-12",
"date": "2025-05-12T18:50:44Z" "date": "2025-05-12T18:50:44Z"
}, },
{
"name": "runtipi/runtipi",
"version": "nightly",
"date": "2025-05-12T18:39:33Z"
},
{
"name": "coder/code-server",
"version": "v4.100.0",
"date": "2025-05-12T18:23:47Z"
},
{ {
"name": "neo4j/neo4j", "name": "neo4j/neo4j",
"version": "4.4.43", "version": "4.4.43",
@ -124,11 +254,6 @@
"version": "v0.24.3", "version": "v0.24.3",
"date": "2025-05-12T15:23:21Z" "date": "2025-05-12T15:23:21Z"
}, },
{
"name": "NodeBB/NodeBB",
"version": "v2.8.18",
"date": "2025-05-12T15:08:09Z"
},
{ {
"name": "n8n-io/n8n", "name": "n8n-io/n8n",
"version": "n8n@1.91.3", "version": "n8n@1.91.3",
@ -139,26 +264,11 @@
"version": "v1.1.0", "version": "v1.1.0",
"date": "2025-05-12T14:40:27Z" "date": "2025-05-12T14:40:27Z"
}, },
{
"name": "VictoriaMetrics/VictoriaMetrics",
"version": "pmm-6401-v1.117.0",
"date": "2025-05-12T13:24:20Z"
},
{ {
"name": "apache/tika", "name": "apache/tika",
"version": "3.2.0-rc1", "version": "3.2.0-rc1",
"date": "2025-05-12T13:06:47Z" "date": "2025-05-12T13:06:47Z"
}, },
{
"name": "mattermost/mattermost",
"version": "v10.7.2",
"date": "2025-05-12T10:42:32Z"
},
{
"name": "nzbgetcom/nzbget",
"version": "v25.0",
"date": "2025-05-12T09:12:04Z"
},
{ {
"name": "dgtlmoon/changedetection.io", "name": "dgtlmoon/changedetection.io",
"version": "0.49.17", "version": "0.49.17",
@ -174,16 +284,6 @@
"version": "v2.18.1", "version": "v2.18.1",
"date": "2025-05-12T07:16:12Z" "date": "2025-05-12T07:16:12Z"
}, },
{
"name": "esphome/esphome",
"version": "2025.4.2",
"date": "2025-05-11T22:18:43Z"
},
{
"name": "morpheus65535/bazarr",
"version": "v1.5.2",
"date": "2025-05-11T16:40:55Z"
},
{ {
"name": "outline/outline", "name": "outline/outline",
"version": "v0.84.0", "version": "v0.84.0",
@ -224,11 +324,6 @@
"version": "v0.46.1", "version": "v0.46.1",
"date": "2025-05-10T15:39:10Z" "date": "2025-05-10T15:39:10Z"
}, },
{
"name": "juanfont/headscale",
"version": "v0.25.1",
"date": "2025-02-25T17:30:48Z"
},
{ {
"name": "pelican-dev/wings", "name": "pelican-dev/wings",
"version": "v1.0.0-beta13", "version": "v1.0.0-beta13",
@ -259,31 +354,16 @@
"version": "v0.53.0", "version": "v0.53.0",
"date": "2025-05-08T19:56:55Z" "date": "2025-05-08T19:56:55Z"
}, },
{
"name": "ellite/Wallos",
"version": "v3.1.0",
"date": "2025-05-08T15:33:17Z"
},
{ {
"name": "BookStackApp/BookStack", "name": "BookStackApp/BookStack",
"version": "v25.02.4", "version": "v25.02.4",
"date": "2025-05-08T15:03:17Z" "date": "2025-05-08T15:03:17Z"
}, },
{
"name": "wazuh/wazuh",
"version": "v4.12.0",
"date": "2025-05-08T13:27:46Z"
},
{ {
"name": "apache/tomcat", "name": "apache/tomcat",
"version": "10.1.41", "version": "10.1.41",
"date": "2025-05-08T12:45:44Z" "date": "2025-05-08T12:45:44Z"
}, },
{
"name": "zwave-js/zwave-js-ui",
"version": "v10.4.2",
"date": "2025-05-08T08:11:27Z"
},
{ {
"name": "semaphoreui/semaphore", "name": "semaphoreui/semaphore",
"version": "v2.14.10", "version": "v2.14.10",
@ -299,11 +379,6 @@
"version": "v5.36.3", "version": "v5.36.3",
"date": "2025-05-07T17:22:07Z" "date": "2025-05-07T17:22:07Z"
}, },
{
"name": "ipfs/kubo",
"version": "v0.34.1",
"date": "2025-03-25T18:11:12Z"
},
{ {
"name": "donaldzou/WGDashboard", "name": "donaldzou/WGDashboard",
"version": "v4.2.3", "version": "v4.2.3",
@ -334,11 +409,6 @@
"version": "v2.36.0", "version": "v2.36.0",
"date": "2025-05-07T11:54:14Z" "date": "2025-05-07T11:54:14Z"
}, },
{
"name": "Checkmk/checkmk",
"version": "v2.2.0p42-rc1",
"date": "2025-05-07T11:50:30Z"
},
{ {
"name": "openobserve/openobserve", "name": "openobserve/openobserve",
"version": "v0.14.7", "version": "v0.14.7",
@ -359,16 +429,6 @@
"version": "@jupyter-notebook/ui-components@7.5.0-alpha.0", "version": "@jupyter-notebook/ui-components@7.5.0-alpha.0",
"date": "2025-05-07T09:12:08Z" "date": "2025-05-07T09:12:08Z"
}, },
{
"name": "influxdata/influxdb",
"version": "v1.12.1rc0",
"date": "2025-05-06T20:56:30Z"
},
{
"name": "Athou/commafeed",
"version": "5.8.0",
"date": "2025-05-06T18:33:07Z"
},
{ {
"name": "sysadminsmedia/homebox", "name": "sysadminsmedia/homebox",
"version": "v0.19.0", "version": "v0.19.0",
@ -389,11 +449,6 @@
"version": "v0.107.61", "version": "v0.107.61",
"date": "2025-04-22T12:42:26Z" "date": "2025-04-22T12:42:26Z"
}, },
{
"name": "Luligu/matterbridge",
"version": "3.0.1",
"date": "2025-05-06T10:24:43Z"
},
{ {
"name": "syncthing/syncthing", "name": "syncthing/syncthing",
"version": "v1.29.6", "version": "v1.29.6",
@ -489,11 +544,6 @@
"version": "v2.0.111", "version": "v2.0.111",
"date": "2025-05-03T16:25:30Z" "date": "2025-05-03T16:25:30Z"
}, },
{
"name": "blakeblackshear/frigate",
"version": "v0.14.1",
"date": "2024-08-29T22:32:51Z"
},
{ {
"name": "kimai/kimai", "name": "kimai/kimai",
"version": "2.33.0", "version": "2.33.0",
@ -524,11 +574,6 @@
"version": "v3.5.4", "version": "v3.5.4",
"date": "2025-05-02T13:42:06Z" "date": "2025-05-02T13:42:06Z"
}, },
{
"name": "motioneye-project/motioneye",
"version": "0.42.1",
"date": "2020-06-07T07:27:04Z"
},
{ {
"name": "emqx/emqx", "name": "emqx/emqx",
"version": "e5.9.0", "version": "e5.9.0",
@ -549,21 +594,11 @@
"version": "1.6.13", "version": "1.6.13",
"date": "2025-04-30T16:38:35Z" "date": "2025-04-30T16:38:35Z"
}, },
{
"name": "cloudflare/cloudflared",
"version": "2025.4.2",
"date": "2025-04-30T14:16:11Z"
},
{ {
"name": "docmost/docmost", "name": "docmost/docmost",
"version": "v0.20.4", "version": "v0.20.4",
"date": "2025-04-30T14:15:16Z" "date": "2025-04-30T14:15:16Z"
}, },
{
"name": "goauthentik/authentik",
"version": "version/2025.4.0",
"date": "2025-04-30T12:34:14Z"
},
{ {
"name": "hivemq/hivemq-community-edition", "name": "hivemq/hivemq-community-edition",
"version": "2025.3", "version": "2025.3",
@ -599,21 +634,11 @@
"version": "v1.132.3", "version": "v1.132.3",
"date": "2025-04-28T14:11:06Z" "date": "2025-04-28T14:11:06Z"
}, },
{
"name": "FlowiseAI/Flowise",
"version": "flowise@2.2.8",
"date": "2025-04-28T08:27:00Z"
},
{ {
"name": "karakeep-app/karakeep", "name": "karakeep-app/karakeep",
"version": "v0.24.1", "version": "v0.24.1",
"date": "2025-04-28T08:21:37Z" "date": "2025-04-28T08:21:37Z"
}, },
{
"name": "advplyr/audiobookshelf",
"version": "v2.21.0",
"date": "2025-04-27T16:31:14Z"
},
{ {
"name": "gotify/server", "name": "gotify/server",
"version": "v2.6.3", "version": "v2.6.3",
@ -629,11 +654,6 @@
"version": "v3.1.9", "version": "v3.1.9",
"date": "2025-03-01T02:24:33Z" "date": "2025-03-01T02:24:33Z"
}, },
{
"name": "TandoorRecipes/recipes",
"version": "1.5.34",
"date": "2025-03-27T16:17:38Z"
},
{ {
"name": "openhab/openhab-core", "name": "openhab/openhab-core",
"version": "4.3.5", "version": "4.3.5",
@ -739,11 +759,6 @@
"version": "15.2", "version": "15.2",
"date": "2025-04-14T15:37:12Z" "date": "2025-04-14T15:37:12Z"
}, },
{
"name": "Ombi-app/Ombi",
"version": "v4.47.1",
"date": "2025-01-05T21:14:23Z"
},
{ {
"name": "Tautulli/Tautulli", "name": "Tautulli/Tautulli",
"version": "v2.15.2", "version": "v2.15.2",
@ -764,11 +779,6 @@
"version": "4.5.1", "version": "4.5.1",
"date": "2025-04-11T09:57:47Z" "date": "2025-04-11T09:57:47Z"
}, },
{
"name": "apache/cassandra",
"version": "cassandra-5.0.4",
"date": "2025-04-10T16:32:00Z"
},
{ {
"name": "Threadfin/Threadfin", "name": "Threadfin/Threadfin",
"version": "1.2.32", "version": "1.2.32",
@ -854,11 +864,6 @@
"version": "v4.7.0", "version": "v4.7.0",
"date": "2025-03-29T03:50:50Z" "date": "2025-03-29T03:50:50Z"
}, },
{
"name": "bunkerity/bunkerweb",
"version": "v1.6.1",
"date": "2025-03-15T17:29:17Z"
},
{ {
"name": "grocy/grocy", "name": "grocy/grocy",
"version": "v4.5.0", "version": "v4.5.0",
@ -899,11 +904,6 @@
"version": "v4.3.1", "version": "v4.3.1",
"date": "2025-03-23T09:02:54Z" "date": "2025-03-23T09:02:54Z"
}, },
{
"name": "clusterzx/paperless-ai",
"version": "v2.7.6",
"date": "2025-03-21T19:24:53Z"
},
{ {
"name": "seanmorley15/AdventureLog", "name": "seanmorley15/AdventureLog",
"version": "v0.9.0", "version": "v0.9.0",

View File

@ -13,6 +13,11 @@ setting_up_container
network_check network_check
update_os update_os
msg_info "Installing Dependencies"
$STD apt-get install -y \
make
msg_ok "Installed Dependencies"
msg_info "Installing Actual Budget" msg_info "Installing Actual Budget"
cd /opt cd /opt
RELEASE=$(curl -fsSL https://api.github.com/repos/actualbudget/actual/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') RELEASE=$(curl -fsSL https://api.github.com/repos/actualbudget/actual/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')

View File

@ -0,0 +1,85 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/bitmagnet-io/bitmagnet
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing dependencies"
$STD apk add --no-cache \
gcc \
musl-dev \
git \
iproute2-ss \
sudo
$STD apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community go
msg_ok "Installed dependencies"
msg_info "Installing PostgreSQL"
$STD apk add --no-cache \
postgresql16 \
postgresql16-contrib \
postgresql16-openrc
$STD rc-update add postgresql
$STD rc-service postgresql start
msg_ok "Installed PostreSQL"
RELEASE=$(curl -fsSL https://api.github.com/repos/bitmagnet-io/bitmagnet/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
msg_info "Installing bitmagnet v${RELEASE}"
mkdir -p /opt/bitmagnet
temp_file=$(mktemp)
curl -fsSL "https://github.com/bitmagnet-io/bitmagnet/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
tar zxf "$temp_file" --strip-components=1 -C /opt/bitmagnet
cd /opt/bitmagnet
VREL=v$RELEASE
$STD go build -ldflags "-s -w -X github.com/bitmagnet-io/bitmagnet/internal/version.GitTag=$VREL"
chmod +x bitmagnet
$STD su - postgres -c "psql -c 'CREATE DATABASE bitmagnet;'"
echo "${RELEASE}" >/opt/bitmagnet_version.txt
msg_ok "Installed bitmagnet v${RELEASE}"
read -rp "${TAB3}Enter your TMDB API key if you have one: " tmdbapikey
msg_info "Enabling bitmagnet Service"
cat <<EOF >/etc/init.d/bitmagnet
#!/sbin/openrc-run
description="bitmagnet Service"
directory="/opt/bitmagnet"
command="/opt/bitmagnet/bitmagnet"
command_args="worker run --all"
command_background="true"
command_user="root"
pidfile="/var/run/bitmagnet.pid"
depend() {
use net
}
start_pre() {
export TMDB_API_KEY="$tmdbapikey"
}
EOF
chmod +x /etc/init.d/bitmagnet
$STD rc-update add bitmagnet default
msg_ok "Enabled bitmagnet Service"
msg_info "Starting bitmagnet"
$STD service bitmagnet start
msg_ok "Started bitmagnet"
motd_ssh
customize
msg_info "Cleaning up"
rm -f "$temp_file"
$STD apk cache clean
msg_ok "Cleaned"

View File

@ -29,13 +29,13 @@ $STD rc-update add docker default
msg_ok "Installed Docker" msg_ok "Installed Docker"
get_latest_release() { get_latest_release() {
curl -fsSL https://api.github.com/repos/$1/releases/latest | grep '"tag_name":' | cut -d'"' -f4 curl -fsSL https://api.github.com/repos/"$1"/releases/latest | grep '"tag_name":' | cut -d'"' -f4
} }
PORTAINER_LATEST_VERSION=$(get_latest_release "portainer/portainer") PORTAINER_LATEST_VERSION=$(get_latest_release "portainer/portainer")
DOCKER_COMPOSE_LATEST_VERSION=$(get_latest_release "docker/compose") DOCKER_COMPOSE_LATEST_VERSION=$(get_latest_release "docker/compose")
PORTAINER_AGENT_LATEST_VERSION=$(get_latest_release "portainer/agent") PORTAINER_AGENT_LATEST_VERSION=$(get_latest_release "portainer/agent")
read -r -p "Would you like to add Portainer? <y/N> " prompt read -r -p "${TAB3}Would you like to add Portainer? <y/N> " prompt
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Installing Portainer $PORTAINER_LATEST_VERSION" msg_info "Installing Portainer $PORTAINER_LATEST_VERSION"
docker volume create portainer_data >/dev/null docker volume create portainer_data >/dev/null
@ -49,7 +49,7 @@ if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
portainer/portainer-ce:latest portainer/portainer-ce:latest
msg_ok "Installed Portainer $PORTAINER_LATEST_VERSION" msg_ok "Installed Portainer $PORTAINER_LATEST_VERSION"
else else
read -r -p "Would you like to add the Portainer Agent? <y/N> " prompt read -r -p "${TAB3}Would you like to add the Portainer Agent? <y/N> " prompt
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Installing Portainer agent $PORTAINER_AGENT_LATEST_VERSION" msg_info "Installing Portainer agent $PORTAINER_AGENT_LATEST_VERSION"
$STD docker run -d \ $STD docker run -d \
@ -62,13 +62,13 @@ else
msg_ok "Installed Portainer Agent $PORTAINER_AGENT_LATEST_VERSION" msg_ok "Installed Portainer Agent $PORTAINER_AGENT_LATEST_VERSION"
fi fi
fi fi
read -r -p "Would you like to add Docker Compose? <y/N> " prompt read -r -p "${TAB3}Would you like to add Docker Compose? <y/N> " prompt
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Installing Docker Compose $DOCKER_COMPOSE_LATEST_VERSION" msg_info "Installing Docker Compose $DOCKER_COMPOSE_LATEST_VERSION"
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins mkdir -p "$DOCKER_CONFIG"/cli-plugins
curl -fsSL https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_LATEST_VERSION/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose curl -fsSL https://github.com/docker/compose/releases/download/"$DOCKER_COMPOSE_LATEST_VERSION"/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose chmod +x "$DOCKER_CONFIG"/cli-plugins/docker-compose
msg_ok "Installed Docker Compose $DOCKER_COMPOSE_LATEST_VERSION" msg_ok "Installed Docker Compose $DOCKER_COMPOSE_LATEST_VERSION"
fi fi

View File

@ -26,11 +26,11 @@ $STD rc-update add docker boot
$STD service docker start $STD service docker start
msg_ok "Enabled Docker Service" msg_ok "Enabled Docker Service"
echo "Choose the database for Komodo installation:" echo "${TAB3}Choose the database for Komodo installation:"
echo "1) MongoDB (recommended)" echo "${TAB3}1) MongoDB (recommended)"
echo "2) SQLite" echo "${TAB3}2) SQLite"
echo "3) PostgreSQL" echo "${TAB3}3) PostgreSQL"
read -rp "Enter your choice (default: 1): " DB_CHOICE read -rp "${TAB3}Enter your choice (default: 1): " DB_CHOICE
DB_CHOICE=${DB_CHOICE:-1} DB_CHOICE=${DB_CHOICE:-1}
case $DB_CHOICE in case $DB_CHOICE in

View File

@ -29,7 +29,7 @@ mysql_install_db --user=mysql --basedir=/usr --datadir=/var/lib/mysql >/dev/null
$STD rc-service mariadb start $STD rc-service mariadb start
msg_ok "MariaDB Configured" msg_ok "MariaDB Configured"
read -r -p "Would you like to install Adminer with lighttpd? <y/N>: " prompt read -r -p "${TAB3}Would you like to install Adminer with lighttpd? <y/N>: " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Adminer and dependencies" msg_info "Installing Adminer and dependencies"
$STD apk add --no-cache \ $STD apk add --no-cache \

View File

@ -33,7 +33,7 @@ sed -i '/^host\s\+all\s\+all\s\+127.0.0.1\/32\s\+md5/ s/.*/host all all 0.0.0.0\
$STD rc-service postgresql restart $STD rc-service postgresql restart
msg_ok "Configured and Restarted PostgreSQL" msg_ok "Configured and Restarted PostgreSQL"
read -r -p "Would you like to install Adminer with lighttpd? <y/N>: " prompt read -r -p "${TAB3}Would you like to install Adminer with lighttpd? <y/N>: " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Adminer and dependencies" msg_info "Installing Adminer and dependencies"
$STD apk add --no-cache \ $STD apk add --no-cache \

View File

@ -27,7 +27,7 @@ curl -fsSL "https://github.com/rclone/rclone/releases/download/v${RELEASE}/rclon
$STD unzip -j "$temp_file" '*/**' -d /opt/rclone $STD unzip -j "$temp_file" '*/**' -d /opt/rclone
cd /opt/rclone cd /opt/rclone
RCLONE_PASSWORD=$(head -c 16 /dev/urandom | xxd -p -c 16) RCLONE_PASSWORD=$(head -c 16 /dev/urandom | xxd -p -c 16)
$STD htpasswd -cb -B login.pwd admin "$RCLONE_PASSWORD" $STD htpasswd -cb -B /opt/login.pwd admin "$RCLONE_PASSWORD"
{ {
echo "rclone-Credentials" echo "rclone-Credentials"
echo "rclone User Name: admin" echo "rclone User Name: admin"
@ -42,7 +42,7 @@ cat <<EOF >/etc/init.d/rclone
#!/sbin/openrc-run #!/sbin/openrc-run
description="rclone Service" description="rclone Service"
command="/opt/rclone/rclone" command="/opt/rclone/rclone"
command_args="rcd --rc-web-gui --rc-web-gui-no-open-browser --rc-addr :3000 --rc-htpasswd /opt/rclone/login.pwd" command_args="rcd --rc-web-gui --rc-web-gui-no-open-browser --rc-addr :3000 --rc-htpasswd /opt/login.pwd"
command_background="true" command_background="true"
command_user="root" command_user="root"
pidfile="/var/run/rclone.pid" pidfile="/var/run/rclone.pid"

View File

@ -21,7 +21,7 @@ msg_info "Installing Traefik"
$STD apk add traefik --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community $STD apk add traefik --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community
msg_ok "Installed Traefik" msg_ok "Installed Traefik"
read -p "Enable Traefik WebUI (Port 8080)? [y/N]: " enable_webui read -p "${TAB3}Enable Traefik WebUI (Port 8080)? [y/N]: " enable_webui
if [[ "$enable_webui" =~ ^[Yy]$ ]]; then if [[ "$enable_webui" =~ ^[Yy]$ ]]; then
msg_info "Configuring Traefik WebUI" msg_info "Configuring Traefik WebUI"
mkdir -p /etc/traefik/config mkdir -p /etc/traefik/config

View File

@ -46,7 +46,7 @@ $STD rc-update add sysctl
$STD sysctl -p /etc/sysctl.conf $STD sysctl -p /etc/sysctl.conf
msg_ok "Installed WireGuard" msg_ok "Installed WireGuard"
read -rp "Do you want to install WGDashboard? (y/N): " INSTALL_WGD read -rp "${TAB3}Do you want to install WGDashboard? (y/N): " INSTALL_WGD
if [[ "$INSTALL_WGD" =~ ^[Yy]$ ]]; then if [[ "$INSTALL_WGD" =~ ^[Yy]$ ]]; then
msg_info "Installing additional dependencies for WGDashboard" msg_info "Installing additional dependencies for WGDashboard"
$STD apk add --no-cache \ $STD apk add --no-cache \

View File

@ -28,7 +28,7 @@ echo "deb https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_COD
$STD apt-get update $STD apt-get update
msg_ok "Set up Adoptium Repository" msg_ok "Set up Adoptium Repository"
read -r -p "Which Tomcat version would you like to install? (9, 10.1, 11): " version read -r -p "${TAB3}Which Tomcat version would you like to install? (9, 10.1, 11): " version
case $version in case $version in
9) 9)
TOMCAT_VERSION="9" TOMCAT_VERSION="9"

View File

@ -17,7 +17,7 @@ msg_info "Installing Aria2"
$STD apt-get install -y aria2 $STD apt-get install -y aria2
msg_ok "Installed Aria2" msg_ok "Installed Aria2"
read -r -p "Would you like to add AriaNG? <y/N> " prompt read -r -p "${TAB3}Would you like to add AriaNG? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing AriaNG" msg_info "Installing AriaNG"
$STD apt-get install -y nginx $STD apt-get install -y nginx

View File

@ -0,0 +1,56 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://asterisk.org
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt-get install -y \
libsrtp2-dev \
build-essential \
libedit-dev \
uuid-dev \
libjansson-dev \
libxml2-dev \
libsqlite3-dev
msg_ok "Installed Dependencies"
msg_info "Downloading Asterisk"
RELEASE=$(curl -fsSL https://downloads.asterisk.org/pub/telephony/asterisk/ | grep -o 'asterisk-[0-9]\+-current\.tar\.gz' | sort -V | tail -n1)
temp_file=$(mktemp)
curl -fsSL "https://downloads.asterisk.org/pub/telephony/asterisk/${RELEASE}" -o "$temp_file"
mkdir -p /opt/asterisk
tar zxf "$temp_file" --strip-components=1 -C /opt/asterisk
cd /opt/asterisk
msg_ok "Downloaded Asterisk"
msg_info "Installing Asterisk"
$STD ./contrib/scripts/install_prereq install
$STD ./configure
$STD make -j$(nproc)
$STD make install
$STD make config
$STD make install-logrotate
$STD make samples
mkdir -p /etc/radiusclient-ng/
ln /etc/radcli/radiusclient.conf /etc/radiusclient-ng/radiusclient.conf
systemctl enable -q --now asterisk
msg_ok "Installed Asterisk"
motd_ssh
customize
msg_info "Cleaning up"
rm -f "$temp_file"
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleaned"

View File

@ -19,7 +19,7 @@ curl -fsSL "https://github.com/authelia/authelia/releases/download/${RELEASE}/au
$STD dpkg -i "authelia_${RELEASE}_amd64.deb" $STD dpkg -i "authelia_${RELEASE}_amd64.deb"
msg_ok "Install Authelia completed" msg_ok "Install Authelia completed"
read -p "Enter your domain (ex. example.com): " DOMAIN read -p "${TAB3}Enter your domain (ex. example.com): " DOMAIN
msg_info "Setting Authelia up" msg_info "Setting Authelia up"
touch /etc/authelia/emails.txt touch /etc/authelia/emails.txt

View File

@ -0,0 +1,78 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/bitmagnet-io/bitmagnet
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt-get install -y \
iproute2 \
gcc \
musl-dev
msg_ok "Installed Dependencies"
PG_VERSION="16" install_postgresql
install_go
RELEASE=$(curl -fsSL https://api.github.com/repos/bitmagnet-io/bitmagnet/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
msg_info "Installing bitmagnet v${RELEASE}"
mkdir -p /opt/bitmagnet
temp_file=$(mktemp)
curl -fsSL "https://github.com/bitmagnet-io/bitmagnet/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
tar zxf "$temp_file" --strip-components=1 -C /opt/bitmagnet
cd /opt/bitmagnet
VREL=v$RELEASE
$STD go build -ldflags "-s -w -X github.com/bitmagnet-io/bitmagnet/internal/version.GitTag=$VREL"
chmod +x bitmagnet
POSTGRES_PASSWORD=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
$STD sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '$POSTGRES_PASSWORD';"
$STD sudo -u postgres psql -c "CREATE DATABASE bitmagnet;"
{
echo "PostgreSQL Credentials"
echo ""
echo "postgres user password: $POSTGRES_PASSWORD"
} >>~/postgres.creds
echo "${RELEASE}" >/opt/bitmagnet_version.txt
msg_ok "Installed bitmagnet v${RELEASE}"
read -r -p "${TAB3}Enter your TMDB API key if you have one: " tmdbapikey
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/bitmagnet-web.service
[Unit]
Description=bitmagnet Web GUI
After=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/bitmagnet
ExecStart=/opt/bitmagnet/bitmagnet worker run --all
Environment=POSTGRES_HOST=localhost
Environment=POSTGRES_PASSWORD=$POSTGRES_PASSWORD
Environment=TMDB_API_KEY=$tmdbapikey
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now bitmagnet-web
msg_ok "Created Service"
motd_ssh
customize
msg_info "Cleaning up"
rm -f "$temp_file"
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleaned"

View File

@ -43,7 +43,7 @@ $STD npm install
echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt" echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt"
msg_ok "Installed ByteStash" msg_ok "Installed ByteStash"
read -p "Do you want to allow registration of multiple accounts? [y/n]: " allowreg read -p "${TAB3}Do you want to allow registration of multiple accounts? [y/n]: " allowreg
msg_info "Creating Service" msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/bytestash-backend.service cat <<EOF >/etc/systemd/system/bytestash-backend.service

View File

@ -28,7 +28,7 @@ $STD apt-get update
$STD apt-get install -y caddy $STD apt-get install -y caddy
msg_ok "Installed Caddy" msg_ok "Installed Caddy"
read -r -p "Would you like to install xCaddy Addon? <y/N> " prompt read -r -p "${TAB3}Would you like to install xCaddy Addon? <y/N> " prompt
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Installing Golang" msg_info "Installing Golang"
set +o pipefail set +o pipefail
@ -46,7 +46,7 @@ if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
cd /opt cd /opt
RELEASE=$(curl -fsSL https://api.github.com/repos/caddyserver/xcaddy/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') RELEASE=$(curl -fsSL https://api.github.com/repos/caddyserver/xcaddy/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
curl -fsSL "https://github.com/caddyserver/xcaddy/releases/download/${RELEASE}/xcaddy_${RELEASE:1}_linux_amd64.deb" -o $(basename "https://github.com/caddyserver/xcaddy/releases/download/${RELEASE}/xcaddy_${RELEASE:1}_linux_amd64.deb") curl -fsSL "https://github.com/caddyserver/xcaddy/releases/download/${RELEASE}/xcaddy_${RELEASE:1}_linux_amd64.deb" -o $(basename "https://github.com/caddyserver/xcaddy/releases/download/${RELEASE}/xcaddy_${RELEASE:1}_linux_amd64.deb")
$STD dpkg -i xcaddy_${RELEASE:1}_linux_amd64.deb $STD dpkg -i xcaddy_"${RELEASE:1}"_linux_amd64.deb
rm -rf /opt/xcaddy* rm -rf /opt/xcaddy*
$STD xcaddy build $STD xcaddy build
msg_ok "Setup xCaddy" msg_ok "Setup xCaddy"

View File

@ -22,7 +22,7 @@ $STD apt-get update
$STD apt-get install -y cloudflared $STD apt-get install -y cloudflared
msg_ok "Installed Cloudflared" msg_ok "Installed Cloudflared"
read -r -p "Would you like to configure cloudflared as a DNS-over-HTTPS (DoH) proxy? <y/N> " prompt read -r -p "${TAB3}Would you like to configure cloudflared as a DNS-over-HTTPS (DoH) proxy? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Creating Service" msg_info "Creating Service"
cat <<EOF >/usr/local/etc/cloudflared/config.yml cat <<EOF >/usr/local/etc/cloudflared/config.yml

View File

@ -30,7 +30,7 @@ $STD apt-get update
$STD apt-get install -y nodejs $STD apt-get install -y nodejs
msg_ok "Setup Node.js" msg_ok "Setup Node.js"
read -p "Install OnlyOffice components instead of CKEditor? (Y/N): " onlyoffice read -p "${TAB3}Install OnlyOffice components instead of CKEditor? (Y/N): " onlyoffice
msg_info "Setup ${APPLICATION}" msg_info "Setup ${APPLICATION}"
temp_file=$(mktemp) temp_file=$(mktemp)

View File

@ -14,7 +14,7 @@ network_check
update_os update_os
get_latest_release() { get_latest_release() {
curl -fsSL https://api.github.com/repos/$1/releases/latest | grep '"tag_name":' | cut -d'"' -f4 curl -fsSL https://api.github.com/repos/"$1"/releases/latest | grep '"tag_name":' | cut -d'"' -f4
} }
DOCKER_LATEST_VERSION=$(get_latest_release "moby/moby") DOCKER_LATEST_VERSION=$(get_latest_release "moby/moby")
@ -29,7 +29,7 @@ echo -e '{\n "log-driver": "journald"\n}' >/etc/docker/daemon.json
$STD sh <(curl -fsSL https://get.docker.com) $STD sh <(curl -fsSL https://get.docker.com)
msg_ok "Installed Docker $DOCKER_LATEST_VERSION" msg_ok "Installed Docker $DOCKER_LATEST_VERSION"
read -r -p "Would you like to add Portainer? <y/N> " prompt read -r -p "${TAB3}Would you like to add Portainer? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Portainer $PORTAINER_LATEST_VERSION" msg_info "Installing Portainer $PORTAINER_LATEST_VERSION"
docker volume create portainer_data >/dev/null docker volume create portainer_data >/dev/null
@ -43,7 +43,7 @@ if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
portainer/portainer-ce:latest portainer/portainer-ce:latest
msg_ok "Installed Portainer $PORTAINER_LATEST_VERSION" msg_ok "Installed Portainer $PORTAINER_LATEST_VERSION"
else else
read -r -p "Would you like to add the Portainer Agent? <y/N> " prompt read -r -p "${TAB3}Would you like to add the Portainer Agent? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Portainer agent $PORTAINER_AGENT_LATEST_VERSION" msg_info "Installing Portainer agent $PORTAINER_AGENT_LATEST_VERSION"
$STD docker run -d \ $STD docker run -d \

View File

@ -41,7 +41,7 @@ cd /opt/dockge
$STD docker compose up -d $STD docker compose up -d
msg_ok "Installed Dockge" msg_ok "Installed Dockge"
read -r -p "Would you like to add Immich? <y/N> " prompt read -r -p "${TAB3}Would you like to add Immich? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Adding Immich compose.yaml" msg_info "Adding Immich compose.yaml"
mkdir -p /opt/stacks/immich mkdir -p /opt/stacks/immich
@ -50,7 +50,7 @@ if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_ok "Added Immich compose.yaml" msg_ok "Added Immich compose.yaml"
fi fi
read -r -p "Would you like to add Home Assistant? <y/N> " prompt read -r -p "${TAB3}Would you like to add Home Assistant? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Adding Home Assistant compose.yaml" msg_info "Adding Home Assistant compose.yaml"
mkdir -p /opt/stacks/homeassistant mkdir -p /opt/stacks/homeassistant

View File

@ -20,27 +20,16 @@ msg_ok "Setup Functions"
msg_info "Installing Dependencies" msg_info "Installing Dependencies"
$STD apt-get install -y \ $STD apt-get install -y \
gpg \
libc6 \ libc6 \
make \ make \
cmake \ cmake \
jq \ jq \
postgresql \
python3 \ python3 \
python3-bcrypt python3-bcrypt
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
msg_info "Setting up Node.js Repository" NODE_VERSION="22" NODE_MODULE="turbo@1.9.3" install_node_and_modules
mkdir -p /etc/apt/keyrings PG_VERSION="16" install_postgresql
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" >/etc/apt/sources.list.d/nodesource.list
msg_ok "Set up Node.js Repository"
msg_info "Installing Node.js"
$STD apt-get update
$STD apt-get install -y nodejs
$STD npm install -g turbo@1.9.3
msg_ok "Installed Node.js"
msg_info "Setting up PostgreSQL" msg_info "Setting up PostgreSQL"
DB_NAME="documenso_db" DB_NAME="documenso_db"
@ -90,7 +79,7 @@ msg_ok "Installed Documenso"
msg_info "Create User" msg_info "Create User"
PASSWORD_HASH=$(python3 -c "import bcrypt; print(bcrypt.hashpw(b'helper-scripts', bcrypt.gensalt(rounds=12)).decode())") PASSWORD_HASH=$(python3 -c "import bcrypt; print(bcrypt.hashpw(b'helper-scripts', bcrypt.gensalt(rounds=12)).decode())")
sudo -u postgres psql -d documenso_db -c "INSERT INTO \"User\" (name, email, \"emailVerified\", password, \"identityProvider\", roles, \"createdAt\", \"lastSignedIn\", \"updatedAt\", \"customerId\") VALUES ('helper-scripts', 'helper-scripts@local.com', '2025-01-20 17:14:45.058', '$PASSWORD_HASH', 'DOCUMENSO', ARRAY['USER', 'ADMIN']::\"Role\"[], '2025-01-20 16:04:05.543', '2025-01-20 16:14:55.249', '2025-01-20 16:14:55.25', NULL) RETURNING id;" $STD sudo -u postgres psql -d documenso_db -c "INSERT INTO \"User\" (name, email, \"emailVerified\", password, \"identityProvider\", roles, \"createdAt\", \"lastSignedIn\", \"updatedAt\", \"customerId\") VALUES ('helper-scripts', 'helper-scripts@local.com', '2025-01-20 17:14:45.058', '$PASSWORD_HASH', 'DOCUMENSO', ARRAY['USER', 'ADMIN']::\"Role\"[], '2025-01-20 16:04:05.543', '2025-01-20 16:14:55.249', '2025-01-20 16:14:55.25', NULL) RETURNING id;"
$STD npm run prisma:migrate-deploy $STD npm run prisma:migrate-deploy
msg_ok "User created" msg_ok "User created"

View File

@ -28,7 +28,7 @@ msg_ok "Installed Dependencies"
msg_info "Configure Application" msg_info "Configure Application"
var_project_name="default" var_project_name="default"
read -r -p "Type the assembly name of the project: " var_project_name read -r -p "${TAB3}Type the assembly name of the project: " var_project_name
echo "Target assembly: '${var_project_name}'" echo "Target assembly: '${var_project_name}'"
msg_ok "Application Configured" msg_ok "Application Configured"

View File

@ -33,7 +33,7 @@ $STD apt-get install -y nodejs
$STD npm install -g yarn $STD npm install -g yarn
msg_ok "Installed Node.js" msg_ok "Installed Node.js"
read -p "Please enter the name for your server: " servername read -p "${TAB3}Please enter the name for your server: " servername
msg_info "Installing Element Synapse" msg_info "Installing Element Synapse"
curl -fsSL "https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg" -o "/usr/share/keyrings/matrix-org-archive-keyring.gpg" curl -fsSL "https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg" -o "/usr/share/keyrings/matrix-org-archive-keyring.gpg"

View File

@ -21,7 +21,7 @@ $STD apt-get install -y \
imagemagick imagemagick
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
read -r -p "Do you need the intel-media-va-driver-non-free driver for HW encoding (Debian 12 only)? <y/N> " prompt read -r -p "${TAB3}Do you need the intel-media-va-driver-non-free driver for HW encoding (Debian 12 only)? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Intel Hardware Acceleration (non-free)" msg_info "Installing Intel Hardware Acceleration (non-free)"
cat <<EOF >/etc/apt/sources.list.d/non-free.list cat <<EOF >/etc/apt/sources.list.d/non-free.list

View File

@ -24,7 +24,7 @@ curl -fsSL "https://repos.influxdata.com/influxdata-archive_compat.key" | gpg --
echo "deb [signed-by=/etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg] https://repos.influxdata.com/debian stable main" >/etc/apt/sources.list.d/influxdata.list echo "deb [signed-by=/etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg] https://repos.influxdata.com/debian stable main" >/etc/apt/sources.list.d/influxdata.list
msg_ok "Set up InfluxDB Repository" msg_ok "Set up InfluxDB Repository"
read -r -p "Which version of InfluxDB to install? (1 or 2) " prompt read -r -p "${TAB3}Which version of InfluxDB to install? (1 or 2) " prompt
if [[ $prompt == "2" ]]; then if [[ $prompt == "2" ]]; then
INFLUX="2" INFLUX="2"
else else
@ -43,7 +43,7 @@ fi
$STD systemctl enable --now influxdb $STD systemctl enable --now influxdb
msg_ok "Installed InfluxDB" msg_ok "Installed InfluxDB"
read -r -p "Would you like to add Telegraf? <y/N> " prompt read -r -p "${TAB3}Would you like to add Telegraf? <y/N> " prompt
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Installing Telegraf" msg_info "Installing Telegraf"
$STD apt-get install -y telegraf $STD apt-get install -y telegraf

View File

@ -21,9 +21,9 @@ msg_ok "Setup Python 3"
msg_info "Setup Kometa" msg_info "Setup Kometa"
temp_file=$(mktemp) temp_file=$(mktemp)
RELEASE=$(curl -fsSL https://api.github.com/repos/Kometa-Team/Kometa/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') RELEASE=$(curl -fsSL https://api.github.com/repos/Kometa-Team/Kometa/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
curl -fsSL "https://github.com/Kometa-Team/Kometa/archive/refs/tags/v${RELEASE}.tar.gz" -o ""$temp_file"" curl -fsSL "https://github.com/Kometa-Team/Kometa/archive/refs/tags/v${RELEASE}.tar.gz" -o """$temp_file"""
tar -xzf "$temp_file" tar -xzf "$temp_file"
mv Kometa-${RELEASE} /opt/kometa mv Kometa-"${RELEASE}" /opt/kometa
cd /opt/kometa cd /opt/kometa
$STD pip install -r requirements.txt --ignore-installed $STD pip install -r requirements.txt --ignore-installed
mkdir -p config/assets mkdir -p config/assets
@ -31,9 +31,9 @@ cp config/config.yml.template config/config.yml
echo "${RELEASE}" >/opt/kometa_version.txt echo "${RELEASE}" >/opt/kometa_version.txt
msg_ok "Setup Kometa" msg_ok "Setup Kometa"
read -p "Enter your TMDb API key: " TMDBKEY read -p "${TAB3}nter your TMDb API key: " TMDBKEY
read -p "Enter your Plex URL: " PLEXURL read -p "${TAB3}Enter your Plex URL: " PLEXURL
read -p "Enter your Plex token: " PLEXTOKEN read -p "${TAB3}Enter your Plex token: " PLEXTOKEN
sed -i -e "s#url: http://192.168.1.12:32400#url: $PLEXURL #g" /opt/kometa/config/config.yml sed -i -e "s#url: http://192.168.1.12:32400#url: $PLEXURL #g" /opt/kometa/config/config.yml
sed -i -e "s/token: ####################/token: $PLEXTOKEN/g" /opt/kometa/config/config.yml sed -i -e "s/token: ####################/token: $PLEXTOKEN/g" /opt/kometa/config/config.yml
sed -i -e "s/apikey: ################################/apikey: $TMDBKEY/g" /opt/kometa/config/config.yml sed -i -e "s/apikey: ################################/apikey: $TMDBKEY/g" /opt/kometa/config/config.yml
@ -61,7 +61,7 @@ motd_ssh
customize customize
msg_info "Cleaning up" msg_info "Cleaning up"
rm -f $temp_file rm -f "$temp_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"

View File

@ -37,11 +37,11 @@ $STD apt-get install -y \
docker-compose-plugin docker-compose-plugin
msg_ok "Installed Docker" msg_ok "Installed Docker"
echo "Choose the database for Komodo installation:" echo "${TAB3}Choose the database for Komodo installation:"
echo "1) MongoDB (recommended)" echo "${TAB3}1) MongoDB (recommended)"
echo "2) SQLite" echo "${TAB3}2) SQLite"
echo "3) PostgreSQL" echo "${TAB3}3) PostgreSQL"
read -rp "Enter your choice (default: 1): " DB_CHOICE read -rp "${TAB3}Enter your choice (default: 1): " DB_CHOICE
DB_CHOICE=${DB_CHOICE:-1} DB_CHOICE=${DB_CHOICE:-1}
case $DB_CHOICE in case $DB_CHOICE in

View File

@ -56,7 +56,7 @@ $STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC';"
} >>~/linkwarden.creds } >>~/linkwarden.creds
msg_ok "Set up PostgreSQL DB" msg_ok "Set up PostgreSQL DB"
read -r -p "Would you like to add Adminer? <y/N> " prompt read -r -p "${TAB3}Would you like to add Adminer? <y/N> " prompt
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Installing Adminer" msg_info "Installing Adminer"
$STD apt install -y adminer $STD apt install -y adminer

View File

@ -19,7 +19,7 @@ sed -i 's/^# *\(port *=.*\)/\1/' /etc/mysql/my.cnf
sed -i 's/^bind-address/#bind-address/g' /etc/mysql/mariadb.conf.d/50-server.cnf sed -i 's/^bind-address/#bind-address/g' /etc/mysql/mariadb.conf.d/50-server.cnf
msg_ok "Installed MariaDB" msg_ok "Installed MariaDB"
read -r -p "Would you like to add PhpMyAdmin? <y/N> " prompt read -r -p "${TAB3}Would you like to add PhpMyAdmin? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing phpMyAdmin" msg_info "Installing phpMyAdmin"
$STD apt-get install -y \ $STD apt-get install -y \

View File

@ -38,7 +38,7 @@ sed -i \
echo "${RELEASE}" >/opt/${APPLICATION}_version.txt echo "${RELEASE}" >/opt/${APPLICATION}_version.txt
msg_ok "Setup ${APPLICATION}" msg_ok "Setup ${APPLICATION}"
read -r -p "Do you want add meilisearch-ui? [y/n]: " prompt read -r -p "${TAB3}Do you want add meilisearch-ui? [y/n]: " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Setting up Node.js Repository" msg_info "Setting up Node.js Repository"
mkdir -p /etc/apt/keyrings mkdir -p /etc/apt/keyrings
@ -57,7 +57,7 @@ if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
tmp_dir=$(mktemp -d) tmp_dir=$(mktemp -d)
mkdir -p /opt/meilisearch-ui mkdir -p /opt/meilisearch-ui
RELEASE_UI=$(curl -s https://api.github.com/repos/riccox/meilisearch-ui/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') RELEASE_UI=$(curl -s https://api.github.com/repos/riccox/meilisearch-ui/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
curl -fsSL "https://github.com/riccox/meilisearch-ui/archive/refs/tags/${RELEASE_UI}.zip" -o $tmp_file curl -fsSL "https://github.com/riccox/meilisearch-ui/archive/refs/tags/${RELEASE_UI}.zip" -o "$tmp_file"
unzip -q "$tmp_file" -d "$tmp_dir" unzip -q "$tmp_file" -d "$tmp_dir"
mv "$tmp_dir"/*/* /opt/meilisearch-ui/ mv "$tmp_dir"/*/* /opt/meilisearch-ui/
cd /opt/meilisearch-ui cd /opt/meilisearch-ui
@ -112,7 +112,6 @@ fi
msg_ok "Set up Services" msg_ok "Set up Services"
motd_ssh motd_ssh
customize customize

View File

@ -17,7 +17,7 @@ msg_info "Installing Dependencies"
$STD apt-get install -y gnupg $STD apt-get install -y gnupg
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
read -p "Do you want to install MongoDB 8.0 instead of 7.0? [y/N]: " install_mongodb_8 read -p "${TAB3}Do you want to install MongoDB 8.0 instead of 7.0? [y/N]: " install_mongodb_8
if [[ "$install_mongodb_8" =~ ^[Yy]$ ]]; then if [[ "$install_mongodb_8" =~ ^[Yy]$ ]]; then
MONGODB_VERSION="8.0" MONGODB_VERSION="8.0"
else else

View File

@ -22,7 +22,7 @@ msg_ok "Installed Dependencies"
RELEASE_REPO="mysql-8.0" RELEASE_REPO="mysql-8.0"
RELEASE_AUTH="mysql_native_password" RELEASE_AUTH="mysql_native_password"
read -r -p "Would you like to install the MySQL 8.4 LTS release instead of MySQL 8.0 (bug fix track; EOL April-2026)? <y/N> " prompt read -r -p "${TAB3}Would you like to install the MySQL 8.4 LTS release instead of MySQL 8.0 (bug fix track; EOL April-2026)? <y/N> " prompt
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
RELEASE_REPO="mysql-8.4-lts" RELEASE_REPO="mysql-8.4-lts"
RELEASE_AUTH="caching_sha2_password" RELEASE_AUTH="caching_sha2_password"
@ -50,7 +50,7 @@ echo -e "MySQL user: root" >>~/mysql.creds
echo -e "MySQL password: $ADMIN_PASS" >>~/mysql.creds echo -e "MySQL password: $ADMIN_PASS" >>~/mysql.creds
msg_ok "MySQL Server configured" msg_ok "MySQL Server configured"
read -r -p "Would you like to add PhpMyAdmin? <y/N> " prompt read -r -p "${TAB3}Would you like to add PhpMyAdmin? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing phpMyAdmin" msg_info "Installing phpMyAdmin"
$STD apt-get install -y \ $STD apt-get install -y \

View File

@ -27,7 +27,7 @@ systemctl enable -q --now navidrome
echo "${RELEASE}" >/opt/Navidrome_version.txt echo "${RELEASE}" >/opt/Navidrome_version.txt
msg_ok "Installed Navidrome" msg_ok "Installed Navidrome"
read -p "Do you want to install filebrowser addon? (y/n) " -n 1 -r read -p "${TAB3}Do you want to install filebrowser addon? (y/n) " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]; then if [[ $REPLY =~ ^[Yy]$ ]]; then
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/filebrowser.sh)" bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/filebrowser.sh)"
fi fi

View File

@ -62,7 +62,7 @@ RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-
grep "tag_name" | grep "tag_name" |
awk '{print substr($2, 3, length($2)-4) }') awk '{print substr($2, 3, length($2)-4) }')
read -r -p "Would you like to install an older version (v2.10.4)? <y/N> " prompt read -r -p "${TAB3}Would you like to install an older version (v2.10.4)? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Downloading Nginx Proxy Manager v2.10.4" msg_info "Downloading Nginx Proxy Manager v2.10.4"
curl -fsSL "https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v2.10.4" | tar -xz curl -fsSL "https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v2.10.4" | tar -xz
@ -71,7 +71,7 @@ if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
else else
msg_info "Downloading Nginx Proxy Manager v${RELEASE}" msg_info "Downloading Nginx Proxy Manager v${RELEASE}"
curl -fsSL "https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE}" | tar -xz curl -fsSL "https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE}" | tar -xz
cd ./nginx-proxy-manager-${RELEASE} cd ./nginx-proxy-manager-"${RELEASE}"
msg_ok "Downloaded Nginx Proxy Manager v${RELEASE}" msg_ok "Downloaded Nginx Proxy Manager v${RELEASE}"
fi fi
msg_info "Setting up Environment" msg_info "Setting up Environment"

View File

@ -42,7 +42,7 @@ msg_ok "Fetched NPMplus"
attempts=0 attempts=0
while true; do while true; do
read -r -p "Enter your TZ Identifier (e.g., Europe/Berlin): " TZ_INPUT read -r -p "${TAB3}Enter your TZ Identifier (e.g., Europe/Berlin): " TZ_INPUT
if validate_tz "$TZ_INPUT"; then if validate_tz "$TZ_INPUT"; then
break break
fi fi
@ -55,7 +55,7 @@ while true; do
fi fi
done done
read -r -p "Enter your ACME Email: " ACME_EMAIL_INPUT read -r -p "${TAB3}Enter your ACME Email: " ACME_EMAIL_INPUT
yq -i " yq -i "
.services.npmplus.environment |= .services.npmplus.environment |=

74
install/odoo-install.sh Normal file
View File

@ -0,0 +1,74 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/tteck/Proxmox/raw/main/LICENSE
# Source: https://github.com/odoo/odoo
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt-get install -y \
build-essential \
make
msg_ok "Installed Dependencies"
RELEASE=$(curl -fsSL https://nightly.odoo.com/ | grep -oE 'href="[0-9]+\.[0-9]+/nightly"' | head -n1 | cut -d'"' -f2 | cut -d/ -f1)
LATEST_VERSION=$(curl -fsSL "https://nightly.odoo.com/${RELEASE}/nightly/deb/" |
grep -oP "odoo_${RELEASE}\.\d+_all\.deb" |
sed -E "s/odoo_(${RELEASE}\.[0-9]+)_all\.deb/\1/" |
sort -V |
tail -n1)
msg_info "Setup Odoo $RELEASE"
curl -fsSL https://nightly.odoo.com/${RELEASE}/nightly/deb/odoo_${RELEASE}.latest_all.deb -o /opt/odoo.deb
$STD apt install -y /opt/odoo.deb
msg_ok "Setup Odoo $RELEASE"
msg_info "Setup PostgreSQL Database"
DB_NAME="odoo"
DB_USER="odoo_usr"
DB_PASS="$(openssl rand -base64 18 | cut -c1-13)"
$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME;"
$STD sudo -u postgres psql -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASS';"
$STD sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;"
$STD sudo -u postgres psql -c "ALTER DATABASE $DB_NAME OWNER TO $DB_USER;"
$STD sudo -u postgres psql -c "ALTER USER $DB_USER WITH SUPERUSER;"
{
echo "Odoo-Credentials"
echo -e "Odoo Database User: $DB_USER"
echo -e "Odoo Database Password: $DB_PASS"
echo -e "Odoo Database Name: $DB_NAME"
} >>~/odoo.creds
msg_ok "Setup PostgreSQL"
msg_info "Configuring Odoo"
sed -i \
-e "s|^;*db_host *=.*|db_host = localhost|" \
-e "s|^;*db_port *=.*|db_port = 5432|" \
-e "s|^;*db_user *=.*|db_user = $DB_USER|" \
-e "s|^;*db_password *=.*|db_password = $DB_PASS|" \
/etc/odoo/odoo.conf
$STD sudo -u odoo odoo -c /etc/odoo/odoo.conf -d odoo -i base --stop-after-init
systemctl restart odoo
echo "${LATEST_VERSION}" >/opt/${APPLICATION}_version.txt
msg_ok "Configured Odoo"
msg_info "Restarting Odoo"
msg_ok "Restarted Odoo"
motd_ssh
customize
msg_info "Cleaning up"
rm -f /opt/odoo.deb
$STD apt-get autoremove
$STD apt-get autoclean
msg_ok "Cleaned"

View File

@ -55,7 +55,7 @@ export NODE_OPTIONS="--max-old-space-size=3584"
$STD npm run build $STD npm run build
msg_ok "Installed Open WebUI" msg_ok "Installed Open WebUI"
read -r -p "Would you like to add Ollama? <y/N> " prompt read -r -p "${TAB3}Would you like to add Ollama? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Ollama" msg_info "Installing Ollama"
curl -fsSLO https://ollama.com/download/ollama-linux-amd64.tgz curl -fsSLO https://ollama.com/download/ollama-linux-amd64.tgz

View File

@ -25,18 +25,18 @@ $STD apt-get update
$STD apt-get install -y openziti-controller openziti-console $STD apt-get install -y openziti-controller openziti-console
msg_ok "Installed openziti" msg_ok "Installed openziti"
read -r -p "Would you like to go through the auto configuration now? <y/N>" prompt read -r -p "${TAB3}Would you like to go through the auto configuration now? <y/N>" prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
IPADDRESS=$(hostname -I | awk '{print $1}') IPADDRESS=$(hostname -I | awk '{print $1}')
GEN_FQDN="controller.${IPADDRESS}.sslip.io" GEN_FQDN="controller.${IPADDRESS}.sslip.io"
read -r -p "Please enter the controller FQDN [${GEN_FQDN}]: " ZITI_CTRL_ADVERTISED_ADDRESS read -r -p "${TAB3}Please enter the controller FQDN [${GEN_FQDN}]: " ZITI_CTRL_ADVERTISED_ADDRESS
ZITI_CTRL_ADVERTISED_ADDRESS=${ZITI_CTRL_ADVERTISED_ADDRESS:-$GEN_FQDN} ZITI_CTRL_ADVERTISED_ADDRESS=${ZITI_CTRL_ADVERTISED_ADDRESS:-$GEN_FQDN}
read -r -p "Please enter the controller port [1280]: " ZITI_CTRL_ADVERTISED_PORT read -r -p "${TAB3}Please enter the controller port [1280]: " ZITI_CTRL_ADVERTISED_PORT
ZITI_CTRL_ADVERTISED_PORT=${ZITI_CTRL_ADVERTISED_PORT:-1280} ZITI_CTRL_ADVERTISED_PORT=${ZITI_CTRL_ADVERTISED_PORT:-1280}
read -r -p "Please enter the controller admin user [admin]: " ZITI_USER read -r -p "${TAB3}Please enter the controller admin user [admin]: " ZITI_USER
ZITI_USER=${ZITI_USER:-admin} ZITI_USER=${ZITI_USER:-admin}
GEN_PWD=$(head -c128 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9!@#$%^*_+~' | cut -c 1-12) GEN_PWD=$(head -c128 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9!@#$%^*_+~' | cut -c 1-12)
read -r -p "Please enter the controller admin password [${GEN_PWD}]:" ZITI_PWD read -r -p "${TAB3}Please enter the controller admin password [${GEN_PWD}]:" ZITI_PWD
ZITI_PWD=${ZITI_PWD:-$GEN_PWD} ZITI_PWD=${ZITI_PWD:-$GEN_PWD}
CONFIG_FILE="/opt/openziti/etc/controller/bootstrap.env" CONFIG_FILE="/opt/openziti/etc/controller/bootstrap.env"
sed -i "s|^ZITI_CTRL_ADVERTISED_ADDRESS=.*|ZITI_CTRL_ADVERTISED_ADDRESS='${ZITI_CTRL_ADVERTISED_ADDRESS}'|" "$CONFIG_FILE" sed -i "s|^ZITI_CTRL_ADVERTISED_ADDRESS=.*|ZITI_CTRL_ADVERTISED_ADDRESS='${ZITI_CTRL_ADVERTISED_ADDRESS}'|" "$CONFIG_FILE"

View File

@ -27,7 +27,7 @@ sed -i '0,/^ExecStart/ { /^ExecStart/ { n; s|^ExecStart.*|ExecStart=/opt/openzit
systemctl daemon-reload systemctl daemon-reload
msg_ok "Installed openziti" msg_ok "Installed openziti"
read -r -p "Please paste an identity enrollment token(JTW)" prompt read -r -p "${TAB3}Please paste an identity enrollment token(JTW)" prompt
if [[ ${prompt} ]]; then if [[ ${prompt} ]]; then
msg_info "Adding identity" msg_info "Adding identity"
echo "${prompt}" >/opt/openziti/etc/identities/identity.jwt echo "${prompt}" >/opt/openziti/etc/identities/identity.jwt

View File

@ -50,8 +50,8 @@ msg_info "Setup Paperless-GPT"
temp_file=$(mktemp) temp_file=$(mktemp)
RELEASE=$(curl -fsSL https://api.github.com/repos/icereed/paperless-gpt/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') RELEASE=$(curl -fsSL https://api.github.com/repos/icereed/paperless-gpt/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
curl -fsSL "https://github.com/icereed/paperless-gpt/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file" curl -fsSL "https://github.com/icereed/paperless-gpt/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
tar zxf $temp_file tar zxf "$temp_file"
mv paperless-gpt-${RELEASE} /opt/paperless-gpt mv paperless-gpt-"${RELEASE}" /opt/paperless-gpt
cd /opt/paperless-gpt/web-app cd /opt/paperless-gpt/web-app
$STD npm install $STD npm install
$STD npm run build $STD npm run build
@ -64,16 +64,16 @@ echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt"
msg_ok "Setup Paperless-GPT" msg_ok "Setup Paperless-GPT"
mkdir -p /opt/paperless-gpt-data mkdir -p /opt/paperless-gpt-data
read -p "Do you want to enter the Paperless local URL now? (y/n) " input_url read -p "${TAB3}Do you want to enter the Paperless local URL now? (y/n) " input_url
if [[ "$input_url" =~ ^[Yy]$ ]]; then if [[ "$input_url" =~ ^[Yy]$ ]]; then
read -p "Enter your Paperless-NGX instance URL (e.g., http://192.168.1.100:8000): " PAPERLESS_BASE_URL read -p "${TAB3}Enter your Paperless-NGX instance URL (e.g., http://192.168.1.100:8000): " PAPERLESS_BASE_URL
else else
PAPERLESS_BASE_URL="http://your_paperless_ngx_url" PAPERLESS_BASE_URL="http://your_paperless_ngx_url"
fi fi
read -p "Do you want to enter the Paperless API token now? (y/n) " input_token read -p "${TAB3}Do you want to enter the Paperless API token now? (y/n) " input_token
if [[ "$input_token" =~ ^[Yy]$ ]]; then if [[ "$input_token" =~ ^[Yy]$ ]]; then
read -p "Enter your Paperless API token: " PAPERLESS_API_TOKEN read -p "${TAB3}Enter your Paperless API token: " PAPERLESS_API_TOKEN
else else
PAPERLESS_API_TOKEN="your_paperless_api_token" PAPERLESS_API_TOKEN="your_paperless_api_token"
fi fi
@ -129,7 +129,7 @@ motd_ssh
customize customize
msg_info "Cleaning up" msg_info "Cleaning up"
rm -f $temp_file rm -f "$temp_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"

View File

@ -125,7 +125,7 @@ cd /opt/paperless/src
$STD python3 manage.py migrate $STD python3 manage.py migrate
msg_ok "Set up PostgreSQL database" msg_ok "Set up PostgreSQL database"
read -r -p "Would you like to add Adminer? <y/N> " prompt read -r -p "${TAB3}Would you like to add Adminer? <y/N> " prompt
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Installing Adminer" msg_info "Installing Adminer"
$STD apt install -y adminer $STD apt install -y adminer

View File

@ -54,9 +54,9 @@ $STD pihole-FTL --config ntp.sync.interval 0
systemctl restart pihole-FTL.service systemctl restart pihole-FTL.service
msg_ok "Installed Pi-hole" msg_ok "Installed Pi-hole"
read -r -p "Would you like to add Unbound? <y/N> " prompt read -r -p "${TAB3}Would you like to add Unbound? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
read -r -p "Unbound is configured as a recursive DNS server by default, would you like it to be configured as a forwarding DNS server (using DNS-over-TLS (DoT)) instead? <y/N> " prompt read -r -p "${TAB3}Unbound is configured as a recursive DNS server by default, would you like it to be configured as a forwarding DNS server (using DNS-over-TLS (DoT)) instead? <y/N> " prompt
msg_info "Installing Unbound" msg_info "Installing Unbound"
$STD apt-get install -y unbound $STD apt-get install -y unbound
cat <<EOF >/etc/unbound/unbound.conf.d/pi-hole.conf cat <<EOF >/etc/unbound/unbound.conf.d/pi-hole.conf

View File

@ -42,7 +42,7 @@ rm -f "$temp_file"
set -o pipefail set -o pipefail
msg_ok "Installed Golang" msg_ok "Installed Golang"
read -r -p "What public URL do you want to use (e.g. pocketid.mydomain.com)? " public_url read -r -p "${TAB3}What public URL do you want to use (e.g. pocketid.mydomain.com)? " public_url
msg_info "Setup Pocket ID" msg_info "Setup Pocket ID"
cd /opt cd /opt
RELEASE=$(curl -fsSL https://api.github.com/repos/pocket-id/pocket-id/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') RELEASE=$(curl -fsSL https://api.github.com/repos/pocket-id/pocket-id/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')

View File

@ -49,7 +49,7 @@ $STD systemctl enable --now podman.socket
echo -e 'unqualified-search-registries=["docker.io"]' >>/etc/containers/registries.conf echo -e 'unqualified-search-registries=["docker.io"]' >>/etc/containers/registries.conf
msg_ok "Installed Podman" msg_ok "Installed Podman"
read -r -p "Would you like to add Portainer? <y/N> " prompt read -r -p "${TAB3}Would you like to add Portainer? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Portainer $PORTAINER_LATEST_VERSION" msg_info "Installing Portainer $PORTAINER_LATEST_VERSION"
podman volume create portainer_data >/dev/null podman volume create portainer_data >/dev/null
@ -63,7 +63,7 @@ if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
portainer/portainer-ce:latest portainer/portainer-ce:latest
msg_ok "Installed Portainer $PORTAINER_LATEST_VERSION" msg_ok "Installed Portainer $PORTAINER_LATEST_VERSION"
else else
read -r -p "Would you like to add the Portainer Agent? <y/N> " prompt read -r -p "${TAB3}Would you like to add the Portainer Agent? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Portainer agent $PORTAINER_AGENT_LATEST_VERSION" msg_info "Installing Portainer agent $PORTAINER_AGENT_LATEST_VERSION"
podman volume create temp >/dev/null podman volume create temp >/dev/null

View File

@ -49,7 +49,7 @@ $STD systemctl enable --now podman.socket
echo -e 'unqualified-search-registries=["docker.io"]' >>/etc/containers/registries.conf echo -e 'unqualified-search-registries=["docker.io"]' >>/etc/containers/registries.conf
msg_ok "Installed Podman" msg_ok "Installed Podman"
read -r -p "Would you like to add Portainer? <y/N> " prompt read -r -p "${TAB3}Would you like to add Portainer? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Portainer $PORTAINER_LATEST_VERSION" msg_info "Installing Portainer $PORTAINER_LATEST_VERSION"
podman volume create portainer_data >/dev/null podman volume create portainer_data >/dev/null
@ -63,7 +63,7 @@ if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
portainer/portainer-ce:latest portainer/portainer-ce:latest
msg_ok "Installed Portainer $PORTAINER_LATEST_VERSION" msg_ok "Installed Portainer $PORTAINER_LATEST_VERSION"
else else
read -r -p "Would you like to add the Portainer Agent? <y/N> " prompt read -r -p "${TAB3}Would you like to add the Portainer Agent? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Portainer agent $PORTAINER_AGENT_LATEST_VERSION" msg_info "Installing Portainer agent $PORTAINER_AGENT_LATEST_VERSION"
podman volume create temp >/dev/null podman volume create temp >/dev/null

View File

@ -130,7 +130,7 @@ EOF
sudo systemctl restart postgresql sudo systemctl restart postgresql
msg_ok "Installed PostgreSQL" msg_ok "Installed PostgreSQL"
read -r -p "Would you like to add Adminer? <y/N> " prompt read -r -p "${TAB3}Would you like to add Adminer? <y/N> " prompt
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Installing Adminer" msg_info "Installing Adminer"
$STD apt install -y adminer $STD apt install -y adminer

View File

@ -53,9 +53,9 @@ $STD mysql -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH
} >>~/pterodactyl-panel.creds } >>~/pterodactyl-panel.creds
msg_ok "Set up MariaDB" msg_ok "Set up MariaDB"
read -p "Provide an email address for admin login, this should be a valid email address: " ADMIN_EMAIL read -p "${TAB3}Provide an email address for admin login, this should be a valid email address: " ADMIN_EMAIL
read -p "Enter your First Name: " NAME_FIRST read -p "${TAB3}nter your First Name: " NAME_FIRST
read -p "Enter your Last Name: " NAME_LAST read -p "${TAB3}Enter your Last Name: " NAME_LAST
msg_info "Installing pterodactyl Panel" msg_info "Installing pterodactyl Panel"
RELEASE=$(curl -fsSL https://api.github.com/repos/pterodactyl/panel/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') RELEASE=$(curl -fsSL https://api.github.com/repos/pterodactyl/panel/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')

View File

@ -39,7 +39,7 @@ echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >>~/.bash_profile
source ~/.bash_profile source ~/.bash_profile
msg_ok "Installed SQL Server Tools" msg_ok "Installed SQL Server Tools"
read -r -p "Do you want to run the SQL server setup now? (Later is also possible) <y/N>" prompt read -r -p "${TAB3}Do you want to run the SQL server setup now? (Later is also possible) <y/N>" prompt
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
/opt/mssql/bin/mssql-conf setup /opt/mssql/bin/mssql-conf setup
else else

View File

@ -17,6 +17,7 @@ color() {
BFR="\\r\\033[K" BFR="\\r\\033[K"
BOLD=$(echo "\033[1m") BOLD=$(echo "\033[1m")
TAB=" " TAB=" "
TAB3=" "
# System # System
RETRY_NUM=10 RETRY_NUM=10

View File

@ -32,6 +32,7 @@ color() {
BOLD=$(echo "\033[1m") BOLD=$(echo "\033[1m")
HOLD=" " HOLD=" "
TAB=" " TAB=" "
TAB3=" "
# Icons # Icons
CM="${TAB}✔️${TAB}" CM="${TAB}✔️${TAB}"
@ -528,23 +529,23 @@ advanced_settings() {
exit_script exit_script
fi fi
BRIDGES="" BRIDGES=""
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)
OLD_IFS=$IFS; IFS=$'\n' OLD_IFS=$IFS
IFS=$'\n'
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 ) | \ (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}" 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)\s+'; 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
@ -701,8 +702,14 @@ advanced_settings() {
exit_script exit_script
fi fi
if [[ "$PW" == -password* ]]; then SSH_AUTHORIZED_KEY="$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "SSH Authorized key for root (leave empty for none)" 8 58 --title "SSH Key" 3>&1 1>&2 2>&3)"
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH ACCESS" --yesno "Enable Root SSH Access?" 10 58); then
if [[ -z "${SSH_AUTHORIZED_KEY}" ]]; then
SSH_AUTHORIZED_KEY=""
fi
if [[ "$PW" == -password* || -n "$SSH_AUTHORIZED_KEY" ]]; then
if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "SSH ACCESS" --yesno "Enable Root SSH Access?" 10 58); then
SSH="yes" SSH="yes"
else else
SSH="no" SSH="no"
@ -713,15 +720,7 @@ advanced_settings() {
echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}" echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}"
fi fi
if [[ "${SSH}" == "yes" ]]; then
SSH_AUTHORIZED_KEY="$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "SSH Authorized key for root (leave empty for none)" 8 58 --title "SSH Key" 3>&1 1>&2 2>&3)"
if [[ -z "${SSH_AUTHORIZED_KEY}" ]]; then
echo "Warning: No SSH key provided."
fi
else
SSH_AUTHORIZED_KEY=""
fi
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" VERB="yes"
else else
@ -974,7 +973,6 @@ config_file() {
fi fi
fi fi
if [[ ! -z "$APT_CACHER_IP" ]]; then if [[ ! -z "$APT_CACHER_IP" ]]; then
if [[ "$APT_CACHER_IP" =~ $ip_regex ]]; then if [[ "$APT_CACHER_IP" =~ $ip_regex ]]; then
APT_CACHER="yes" APT_CACHER="yes"

View File

@ -19,6 +19,7 @@ color() {
BOLD=$(echo "\033[1m") BOLD=$(echo "\033[1m")
HOLD=" " HOLD=" "
TAB=" " TAB=" "
TAB3=" "
# System # System
RETRY_NUM=10 RETRY_NUM=10

View File

@ -1,4 +1,17 @@
#!/bin/bash #!/bin/bash
# ------------------------------------------------------------------------------
# Installs Node.js and optional global modules.
#
# Description:
# - Installs specified Node.js version using NodeSource APT repo
# - Optionally installs or updates global npm modules
#
# Variables:
# NODE_VERSION - Node.js version to install (default: 22)
# NODE_MODULE - Comma-separated list of global modules (e.g. "yarn,@vue/cli@5.0.0")
# ------------------------------------------------------------------------------
install_node_and_modules() { install_node_and_modules() {
local NODE_VERSION="${NODE_VERSION:-22}" local NODE_VERSION="${NODE_VERSION:-22}"
local NODE_MODULE="${NODE_MODULE:-}" local NODE_MODULE="${NODE_MODULE:-}"
@ -99,6 +112,19 @@ install_node_and_modules() {
fi fi
} }
# ------------------------------------------------------------------------------
# Installs or upgrades PostgreSQL and performs data migration.
#
# Description:
# - Detects existing PostgreSQL version
# - Dumps all databases before upgrade
# - Adds PGDG repo and installs specified version
# - Restores dumped data post-upgrade
#
# Variables:
# PG_VERSION - Major PostgreSQL version (e.g. 15, 16) (default: 16)
# ------------------------------------------------------------------------------
install_postgresql() { install_postgresql() {
local PG_VERSION="${PG_VERSION:-16}" local PG_VERSION="${PG_VERSION:-16}"
local CURRENT_PG_VERSION="" local CURRENT_PG_VERSION=""
@ -115,7 +141,7 @@ install_postgresql() {
msg_info "Detected PostgreSQL $CURRENT_PG_VERSION, preparing upgrade to $PG_VERSION" msg_info "Detected PostgreSQL $CURRENT_PG_VERSION, preparing upgrade to $PG_VERSION"
NEED_PG_INSTALL=true NEED_PG_INSTALL=true
else else
msg_info "PostgreSQL not installed, proceeding with fresh install of $PG_VERSION" msg_info "Setup PostgreSQL $PG_VERSION"
NEED_PG_INSTALL=true NEED_PG_INSTALL=true
fi fi
@ -123,10 +149,10 @@ install_postgresql() {
if [[ -n "$CURRENT_PG_VERSION" ]]; then if [[ -n "$CURRENT_PG_VERSION" ]]; then
msg_info "Dumping all PostgreSQL data from version $CURRENT_PG_VERSION" msg_info "Dumping all PostgreSQL data from version $CURRENT_PG_VERSION"
su - postgres -c "pg_dumpall > /var/lib/postgresql/backup_$(date +%F)_v${CURRENT_PG_VERSION}.sql" su - postgres -c "pg_dumpall > /var/lib/postgresql/backup_$(date +%F)_v${CURRENT_PG_VERSION}.sql"
fi
msg_info "Stopping PostgreSQL service" msg_info "Stopping PostgreSQL service"
systemctl stop postgresql || true systemctl stop postgresql
fi
msg_info "Removing pgdg repo and old GPG key" msg_info "Removing pgdg repo and old GPG key"
rm -f /etc/apt/sources.list.d/pgdg.list /etc/apt/trusted.gpg.d/postgresql.gpg rm -f /etc/apt/sources.list.d/pgdg.list /etc/apt/trusted.gpg.d/postgresql.gpg
@ -149,7 +175,7 @@ install_postgresql() {
fi fi
$STD msg_info "Starting PostgreSQL $PG_VERSION" $STD msg_info "Starting PostgreSQL $PG_VERSION"
systemctl enable --now postgresql systemctl enable -q --now postgresql
if [[ -n "$CURRENT_PG_VERSION" ]]; then if [[ -n "$CURRENT_PG_VERSION" ]]; then
$STD msg_info "Restoring dumped data" $STD msg_info "Restoring dumped data"
@ -160,6 +186,18 @@ install_postgresql() {
fi fi
} }
# ------------------------------------------------------------------------------
# Installs or updates MariaDB from official repo.
#
# Description:
# - Detects current MariaDB version and replaces it if necessary
# - Preserves existing database data
# - Dynamically determines latest GA version if "latest" is given
#
# Variables:
# MARIADB_VERSION - MariaDB version to install (e.g. 10.11, latest) (default: latest)
# ------------------------------------------------------------------------------
install_mariadb() { install_mariadb() {
local MARIADB_VERSION="${MARIADB_VERSION:-latest}" local MARIADB_VERSION="${MARIADB_VERSION:-latest}"
local DISTRO_CODENAME local DISTRO_CODENAME
@ -167,13 +205,18 @@ install_mariadb() {
# grab dynamic latest LTS version # grab dynamic latest LTS version
if [[ "$MARIADB_VERSION" == "latest" ]]; then if [[ "$MARIADB_VERSION" == "latest" ]]; then
msg_info "Resolving latest MariaDB version" $STD msg_info "Resolving latest GA MariaDB version"
MARIADB_VERSION=$(curl -fsSL https://mariadb.org | grep -oP 'MariaDB \K10\.[0-9]+' | head -n1) MARIADB_VERSION=$(curl -fsSL http://mirror.mariadb.org/repo/ |
grep -Eo '[0-9]+\.[0-9]+\.[0-9]+/' |
grep -vE 'rc/|rolling/' |
sed 's|/||' |
sort -Vr |
head -n1)
if [[ -z "$MARIADB_VERSION" ]]; then if [[ -z "$MARIADB_VERSION" ]]; then
msg_error "Could not determine latest MariaDB version" msg_error "Could not determine latest GA MariaDB version"
return 1 return 1
fi fi
msg_ok "Latest MariaDB version is $MARIADB_VERSION" $STD msg_ok "Latest GA MariaDB version is $MARIADB_VERSION"
fi fi
local CURRENT_VERSION="" local CURRENT_VERSION=""
@ -182,23 +225,23 @@ install_mariadb() {
fi fi
if [[ "$CURRENT_VERSION" == "$MARIADB_VERSION" ]]; then if [[ "$CURRENT_VERSION" == "$MARIADB_VERSION" ]]; then
msg_info "MariaDB $MARIADB_VERSION already installed, checking for upgrade" $STD msg_info "MariaDB $MARIADB_VERSION, upgrading"
$STD apt-get update $STD apt-get update
$STD apt-get install --only-upgrade -y mariadb-server mariadb-client $STD apt-get install --only-upgrade -y mariadb-server mariadb-client
msg_ok "MariaDB $MARIADB_VERSION upgraded if applicable" $STD msg_ok "MariaDB upgraded to $MARIADB_VERSION"
return 0 return 0
fi fi
if [[ -n "$CURRENT_VERSION" ]]; then if [[ -n "$CURRENT_VERSION" ]]; then
msg_info "Replacing MariaDB $CURRENT_VERSION with $MARIADB_VERSION (data will be preserved)" $STD msg_info "Replacing MariaDB $CURRENT_VERSION with $MARIADB_VERSION (data will be preserved)"
$STD systemctl stop mariadb >/dev/null 2>&1 || true $STD systemctl stop mariadb >/dev/null 2>&1 || true
$STD apt-get purge -y 'mariadb*' || true $STD apt-get purge -y 'mariadb*' || true
rm -f /etc/apt/sources.list.d/mariadb.list /etc/apt/trusted.gpg.d/mariadb.gpg rm -f /etc/apt/sources.list.d/mariadb.list /etc/apt/trusted.gpg.d/mariadb.gpg
else else
msg_info "Installing MariaDB $MARIADB_VERSION" msg_info "Setup MariaDB $MARIADB_VERSION"
fi fi
msg_info "Setting up MariaDB Repository" $STD msg_info "Setting up MariaDB Repository"
curl -fsSL "https://mariadb.org/mariadb_release_signing_key.asc" | curl -fsSL "https://mariadb.org/mariadb_release_signing_key.asc" |
gpg --dearmor -o /etc/apt/trusted.gpg.d/mariadb.gpg gpg --dearmor -o /etc/apt/trusted.gpg.d/mariadb.gpg
@ -208,9 +251,21 @@ install_mariadb() {
$STD apt-get update $STD apt-get update
$STD apt-get install -y mariadb-server mariadb-client $STD apt-get install -y mariadb-server mariadb-client
msg_ok "Installed MariaDB $MARIADB_VERSION" msg_ok "Setup MariaDB $MARIADB_VERSION"
} }
# ------------------------------------------------------------------------------
# Installs or upgrades MySQL and configures APT repo.
#
# Description:
# - Detects existing MySQL installation
# - Purges conflicting packages before installation
# - Supports clean upgrade
#
# Variables:
# MYSQL_VERSION - MySQL version to install (e.g. 5.7, 8.0) (default: 8.0)
# ------------------------------------------------------------------------------
install_mysql() { install_mysql() {
local MYSQL_VERSION="${MYSQL_VERSION:-8.0}" local MYSQL_VERSION="${MYSQL_VERSION:-8.0}"
local CURRENT_VERSION="" local CURRENT_VERSION=""
@ -248,11 +303,33 @@ install_mysql() {
fi fi
} }
# ------------------------------------------------------------------------------
# Installs PHP with selected modules and configures Apache/FPM support.
#
# Description:
# - Adds Sury PHP repo if needed
# - Installs default and user-defined modules
# - Patches php.ini for CLI, Apache, and FPM as needed
#
# Variables:
# PHP_VERSION - PHP version to install (default: 8.4)
# PHP_MODULE - Additional comma-separated modules
# PHP_APACHE - Set YES to enable PHP with Apache
# PHP_FPM - Set YES to enable PHP-FPM
# PHP_MEMORY_LIMIT - (default: 512M)
# PHP_UPLOAD_MAX_FILESIZE - (default: 128M)
# PHP_POST_MAX_SIZE - (default: 128M)
# PHP_MAX_EXECUTION_TIME - (default: 300)
# ------------------------------------------------------------------------------
install_php() { install_php() {
local PHP_VERSION="${PHP_VERSION:-8.4}" local PHP_VERSION="${PHP_VERSION:-8.4}"
local PHP_MODULE="${PHP_MODULE:-}" local PHP_MODULE="${PHP_MODULE:-}"
local PHP_APACHE="${PHP_APACHE:-NO}" local PHP_APACHE="${PHP_APACHE:-NO}"
local PHP_FPM="${PHP_FPM:-NO}" local PHP_FPM="${PHP_FPM:-NO}"
local DISTRO_CODENAME
DISTRO_CODENAME=$(awk -F= '/VERSION_CODENAME/ { print $2 }' /etc/os-release)
local DEFAULT_MODULES="bcmath,cli,curl,gd,intl,mbstring,opcache,readline,xml,zip" local DEFAULT_MODULES="bcmath,cli,curl,gd,intl,mbstring,opcache,readline,xml,zip"
local COMBINED_MODULES local COMBINED_MODULES
@ -279,11 +356,11 @@ install_php() {
fi fi
if [[ "$CURRENT_PHP" != "$PHP_VERSION" ]]; then if [[ "$CURRENT_PHP" != "$PHP_VERSION" ]]; then
$STD echo "PHP $CURRENT_PHP detected, migrating to PHP $PHP_VERSION" $STD msg_info "PHP $CURRENT_PHP detected, migrating to PHP $PHP_VERSION"
if [[ ! -f /etc/apt/sources.list.d/php.list ]]; then if [[ ! -f /etc/apt/sources.list.d/php.list ]]; then
$STD curl -fsSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb $STD curl -fsSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb
$STD dpkg -i /tmp/debsuryorg-archive-keyring.deb $STD dpkg -i /tmp/debsuryorg-archive-keyring.deb
echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" \ echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ ${DISTRO_CODENAME} main" \
>/etc/apt/sources.list.d/php.list >/etc/apt/sources.list.d/php.list
$STD apt-get update $STD apt-get update
fi fi
@ -329,16 +406,24 @@ install_php() {
for ini in "${PHP_INI_PATHS[@]}"; do for ini in "${PHP_INI_PATHS[@]}"; do
if [[ -f "$ini" ]]; then if [[ -f "$ini" ]]; then
msg_info "Patching $ini" $STD msg_info "Patching $ini"
sed -i "s|^memory_limit = .*|memory_limit = ${PHP_MEMORY_LIMIT}|" "$ini" sed -i "s|^memory_limit = .*|memory_limit = ${PHP_MEMORY_LIMIT}|" "$ini"
sed -i "s|^upload_max_filesize = .*|upload_max_filesize = ${PHP_UPLOAD_MAX_FILESIZE}|" "$ini" sed -i "s|^upload_max_filesize = .*|upload_max_filesize = ${PHP_UPLOAD_MAX_FILESIZE}|" "$ini"
sed -i "s|^post_max_size = .*|post_max_size = ${PHP_POST_MAX_SIZE}|" "$ini" sed -i "s|^post_max_size = .*|post_max_size = ${PHP_POST_MAX_SIZE}|" "$ini"
sed -i "s|^max_execution_time = .*|max_execution_time = ${PHP_MAX_EXECUTION_TIME}|" "$ini" sed -i "s|^max_execution_time = .*|max_execution_time = ${PHP_MAX_EXECUTION_TIME}|" "$ini"
msg_ok "Patched $ini" $STD msg_ok "Patched $ini"
fi fi
done done
} }
# ------------------------------------------------------------------------------
# Installs or updates Composer globally.
#
# Description:
# - Downloads latest version from getcomposer.org
# - Installs to /usr/local/bin/composer
# ------------------------------------------------------------------------------
install_composer() { install_composer() {
local COMPOSER_BIN="/usr/local/bin/composer" local COMPOSER_BIN="/usr/local/bin/composer"
export COMPOSER_ALLOW_SUPERUSER=1 export COMPOSER_ALLOW_SUPERUSER=1
@ -347,14 +432,14 @@ install_composer() {
if [[ -x "$COMPOSER_BIN" ]]; then if [[ -x "$COMPOSER_BIN" ]]; then
local CURRENT_VERSION local CURRENT_VERSION
CURRENT_VERSION=$("$COMPOSER_BIN" --version | awk '{print $3}') CURRENT_VERSION=$("$COMPOSER_BIN" --version | awk '{print $3}')
msg_info "Composer $CURRENT_VERSION found, updating to latest" $STD msg_info "Composer $CURRENT_VERSION found, updating to latest"
else else
msg_info "Composer not found, installing latest version" msg_info "Setup Composer"
fi fi
# Download and install latest composer # Download and install latest composer
curl -fsSL https://getcomposer.org/installer -o /tmp/composer-setup.php curl -fsSL https://getcomposer.org/installer -o /tmp/composer-setup.php
php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer >/dev/null 2>&1 php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer &>/dev/null
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
msg_error "Failed to install Composer" msg_error "Failed to install Composer"
@ -365,6 +450,17 @@ install_composer() {
msg_ok "Installed Composer $($COMPOSER_BIN --version | awk '{print $3}')" msg_ok "Installed Composer $($COMPOSER_BIN --version | awk '{print $3}')"
} }
# ------------------------------------------------------------------------------
# Installs Go (Golang) from official tarball.
#
# Description:
# - Determines system architecture
# - Downloads latest version if GO_VERSION not set
#
# Variables:
# GO_VERSION - Version to install (e.g. 1.22.2 or latest)
# ------------------------------------------------------------------------------
install_go() { install_go() {
local ARCH local ARCH
case "$(uname -m)" in case "$(uname -m)" in
@ -420,6 +516,17 @@ install_go() {
msg_ok "Installed Go $GO_VERSION" msg_ok "Installed Go $GO_VERSION"
} }
# ------------------------------------------------------------------------------
# Installs Temurin JDK via Adoptium APT repository.
#
# Description:
# - Removes previous JDK if version mismatch
# - Installs or upgrades to specified JAVA_VERSION
#
# Variables:
# JAVA_VERSION - Temurin JDK version to install (e.g. 17, 21)
# ------------------------------------------------------------------------------
install_java() { install_java() {
local JAVA_VERSION="${JAVA_VERSION:-21}" local JAVA_VERSION="${JAVA_VERSION:-21}"
local DISTRO_CODENAME local DISTRO_CODENAME
@ -460,6 +567,17 @@ install_java() {
fi fi
} }
# ------------------------------------------------------------------------------
# Installs or updates MongoDB to specified major version.
#
# Description:
# - Preserves data across installations
# - Adds official MongoDB repo
#
# Variables:
# MONGO_VERSION - MongoDB major version to install (e.g. 7.0, 8.0)
# ------------------------------------------------------------------------------
install_mongodb() { install_mongodb() {
local MONGO_VERSION="${MONGO_VERSION:-8.0}" local MONGO_VERSION="${MONGO_VERSION:-8.0}"
local DISTRO_CODENAME local DISTRO_CODENAME
@ -508,6 +626,19 @@ install_mongodb() {
msg_ok "MongoDB $MONGO_VERSION installed and started" msg_ok "MongoDB $MONGO_VERSION installed and started"
} }
# ------------------------------------------------------------------------------
# Downloads and deploys latest GitHub release tarball.
#
# Description:
# - Fetches latest release from GitHub API
# - Detects matching asset by architecture
# - Extracts to /opt/<app> and saves version
#
# Variables:
# APP - Override default application name (optional)
# GITHUB_TOKEN - (optional) GitHub token for private rate limits
# ------------------------------------------------------------------------------
fetch_and_deploy_gh_release() { fetch_and_deploy_gh_release() {
local repo="$1" local repo="$1"
local app=${APP:-$(echo "${APPLICATION,,}" | tr -d ' ')} local app=${APP:-$(echo "${APPLICATION,,}" | tr -d ' ')}
@ -518,13 +649,11 @@ fetch_and_deploy_gh_release() {
local api_response tag http_code local api_response tag http_code
local current_version="" local current_version=""
local curl_timeout="--connect-timeout 10 --max-time 30" local curl_timeout="--connect-timeout 10 --max-time 30"
# Check if the app directory exists and if there's a version file # Check if the app directory exists and if there's a version file
if [[ -f "/opt/${app}_version.txt" ]]; then if [[ -f "/opt/${app}_version.txt" ]]; then
current_version=$(cat "/opt/${app}_version.txt") current_version=$(cat "/opt/${app}_version.txt")
$STD msg_info "Current version: $current_version" $STD msg_info "Current version: $current_version"
fi fi
# ensure that jq is installed # ensure that jq is installed
if ! command -v jq &>/dev/null; then if ! command -v jq &>/dev/null; then
$STD msg_info "Installing jq..." $STD msg_info "Installing jq..."
@ -534,71 +663,57 @@ fetch_and_deploy_gh_release() {
return 1 return 1
} }
fi fi
[[ -n "${GITHUB_TOKEN:-}" ]] && header=(-H "Authorization: token $GITHUB_TOKEN") [[ -n "${GITHUB_TOKEN:-}" ]] && header=(-H "Authorization: token $GITHUB_TOKEN")
until [[ $attempt -ge $max_attempts ]]; do until [[ $attempt -ge $max_attempts ]]; do
((attempt++)) || true ((attempt++)) || true
$STD msg_info "[$attempt/$max_attempts] Fetching GitHub release for $repo...\n" $STD msg_info "[$attempt/$max_attempts] Fetching GitHub release for $repo...\n"
api_response=$(curl $curl_timeout -fsSL -w "%{http_code}" -o /tmp/gh_resp.json "${header[@]}" "$api_url") api_response=$(curl $curl_timeout -fsSL -w "%{http_code}" -o /tmp/gh_resp.json "${header[@]}" "$api_url")
http_code="${api_response:(-3)}" http_code="${api_response:(-3)}"
if [[ "$http_code" == "404" ]]; then if [[ "$http_code" == "404" ]]; then
msg_error "Repository $repo has no Release candidate (404)" msg_error "Repository $repo has no Release candidate (404)"
return 1 return 1
fi fi
if [[ "$http_code" != "200" ]]; then if [[ "$http_code" != "200" ]]; then
$STD msg_info "Request failed with HTTP $http_code, retrying...\n" $STD msg_info "Request failed with HTTP $http_code, retrying...\n"
sleep $((attempt * 2)) sleep $((attempt * 2))
continue continue
fi fi
api_response=$(</tmp/gh_resp.json) api_response=$(</tmp/gh_resp.json)
if echo "$api_response" | grep -q "API rate limit exceeded"; then if echo "$api_response" | grep -q "API rate limit exceeded"; then
msg_error "GitHub API rate limit exceeded." msg_error "GitHub API rate limit exceeded."
return 1 return 1
fi fi
if echo "$api_response" | jq -e '.message == "Not Found"' &>/dev/null; then if echo "$api_response" | jq -e '.message == "Not Found"' &>/dev/null; then
msg_error "Repository not found: $repo" msg_error "Repository not found: $repo"
return 1 return 1
fi fi
tag=$(echo "$api_response" | jq -r '.tag_name // .name // empty') tag=$(echo "$api_response" | jq -r '.tag_name // .name // empty')
[[ "$tag" =~ ^v[0-9] ]] && tag="${tag:1}"
version="${tag#v}" version="${tag#v}"
if [[ -z "$tag" ]]; then if [[ -z "$tag" ]]; then
$STD msg_info "Empty tag received, retrying...\n" $STD msg_info "Empty tag received, retrying...\n"
sleep $((attempt * 2)) sleep $((attempt * 2))
continue continue
fi fi
$STD msg_ok "Found release: $tag for $repo" $STD msg_ok "Found release: $tag for $repo"
break break
done done
if [[ -z "$tag" ]]; then if [[ -z "$tag" ]]; then
msg_error "Failed to fetch release for $repo after $max_attempts attempts." msg_error "Failed to fetch release for $repo after $max_attempts attempts."
exit 1 exit 1
fi fi
# Version comparison (if we already have this version, skip) # Version comparison (if we already have this version, skip)
if [[ "$current_version" == "$version" ]]; then if [[ "$current_version" == "$tag" ]]; then
$STD msg_info "Already running the latest version ($version). Skipping update." $STD msg_info "Already running the latest version ($tag). Skipping update."
return 0 return 0
fi fi
local base_url="https://github.com/$repo/releases/download/v$tag" local base_url="https://github.com/$repo/releases/download/v$tag"
local tmpdir local tmpdir
tmpdir=$(mktemp -d) || return 1 tmpdir=$(mktemp -d) || return 1
# Extract list of assets from the Release API # Extract list of assets from the Release API
local assets urls local assets urls
assets=$(echo "$api_response" | jq -r '.assets[].browser_download_url') || true assets=$(echo "$api_response" | jq -r '.assets[].browser_download_url') || true
# Detect current architecture # Detect current architecture
local arch local arch
if command -v dpkg &>/dev/null; then if command -v dpkg &>/dev/null; then
@ -615,7 +730,6 @@ fetch_and_deploy_gh_release() {
arch="unknown" arch="unknown"
fi fi
$STD msg_info "Detected system architecture: $arch" $STD msg_info "Detected system architecture: $arch"
# Try to find a matching asset for our architecture # Try to find a matching asset for our architecture
local url="" local url=""
for u in $assets; do for u in $assets; do
@ -625,7 +739,6 @@ fetch_and_deploy_gh_release() {
break break
fi fi
done done
# Fallback to other architectures if our specific one isn't found # Fallback to other architectures if our specific one isn't found
if [[ -z "$url" ]]; then if [[ -z "$url" ]]; then
for u in $assets; do for u in $assets; do
@ -636,7 +749,6 @@ fetch_and_deploy_gh_release() {
fi fi
done done
fi fi
# Fallback to any tar.gz # Fallback to any tar.gz
if [[ -z "$url" ]]; then if [[ -z "$url" ]]; then
for u in $assets; do for u in $assets; do
@ -647,24 +759,26 @@ fetch_and_deploy_gh_release() {
fi fi
done done
fi fi
# Final fallback to GitHub source tarball # Final fallback to GitHub source tarball
if [[ -z "$url" ]]; then if [[ -z "$url" ]]; then
url="https://github.com/$repo/archive/refs/tags/$version.tar.gz" # Use tarball_url directly from API response instead of constructing our own URL
$STD msg_info "Trying GitHub source tarball fallback: $url" url=$(echo "$api_response" | jq -r '.tarball_url // empty')
# If tarball_url is empty for some reason, fall back to a constructed URL as before
if [[ -z "$url" ]]; then
url="https://github.com/$repo/archive/refs/tags/v$version.tar.gz"
fi fi
$STD msg_info "Using GitHub source tarball: $url"
fi
local filename="${url##*/}" local filename="${url##*/}"
$STD msg_info "Downloading $url" $STD msg_info "Downloading $url"
if ! curl $curl_timeout -fsSL -o "$tmpdir/$filename" "$url"; then if ! curl $curl_timeout -fsSL -o "$tmpdir/$filename" "$url"; then
msg_error "Failed to download release asset from $url" msg_error "Failed to download release asset from $url"
rm -rf "$tmpdir" rm -rf "$tmpdir"
return 1 return 1
fi fi
mkdir -p "/opt/$app" mkdir -p "/opt/$app"
tar -xzf "$tmpdir/$filename" -C "$tmpdir" tar -xzf "$tmpdir/$filename" -C "$tmpdir"
local content_root local content_root
content_root=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d) content_root=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d)
@ -673,12 +787,19 @@ fetch_and_deploy_gh_release() {
else else
cp -r "$tmpdir"/* "/opt/$app/" cp -r "$tmpdir"/* "/opt/$app/"
fi fi
echo "$version" >"/opt/${app}_version.txt" echo "$version" >"/opt/${app}_version.txt"
$STD msg_ok "Deployed $app v$version to /opt/$app" $STD msg_ok "Deployed $app v$version to /opt/$app"
rm -rf "$tmpdir" rm -rf "$tmpdir"
} }
# ------------------------------------------------------------------------------
# Installs a local IP updater script using networkd-dispatcher.
#
# Description:
# - Stores current IP in /run/local-ip.env
# - Automatically runs on network changes
# ------------------------------------------------------------------------------
setup_local_ip_helper() { setup_local_ip_helper() {
local BASE_DIR="/usr/local/community-scripts/ip-management" local BASE_DIR="/usr/local/community-scripts/ip-management"
local SCRIPT_PATH="$BASE_DIR/update_local_ip.sh" local SCRIPT_PATH="$BASE_DIR/update_local_ip.sh"
@ -689,8 +810,8 @@ setup_local_ip_helper() {
# Install networkd-dispatcher if not present # Install networkd-dispatcher if not present
if ! dpkg -s networkd-dispatcher >/dev/null 2>&1; then if ! dpkg -s networkd-dispatcher >/dev/null 2>&1; then
apt-get update -qq $STD apt-get update -qq
apt-get install -yq networkd-dispatcher $STD apt-get install -yq networkd-dispatcher
fi fi
# Write update_local_ip.sh # Write update_local_ip.sh
@ -746,11 +867,18 @@ $SCRIPT_PATH
EOF EOF
chmod +x "$DISPATCHER_SCRIPT" chmod +x "$DISPATCHER_SCRIPT"
systemctl enable --now networkd-dispatcher.service systemctl enable -q --now networkd-dispatcher.service
$STD msg_ok "LOCAL_IP helper installed using networkd-dispatcher" $STD msg_ok "LOCAL_IP helper installed using networkd-dispatcher"
} }
# ------------------------------------------------------------------------------
# Loads LOCAL_IP from persistent store or detects if missing.
#
# Description:
# - Loads from /run/local-ip.env or performs runtime lookup
# ------------------------------------------------------------------------------
import_local_ip() { import_local_ip() {
local IP_FILE="/run/local-ip.env" local IP_FILE="/run/local-ip.env"
if [[ -f "$IP_FILE" ]]; then if [[ -f "$IP_FILE" ]]; then
@ -788,6 +916,14 @@ import_local_ip() {
export LOCAL_IP export LOCAL_IP
} }
# ------------------------------------------------------------------------------
# Downloads file with optional progress indicator using pv.
#
# Arguments:
# $1 - URL
# $2 - Destination path
# ------------------------------------------------------------------------------
function download_with_progress() { function download_with_progress() {
local url="$1" local url="$1"
local output="$2" local output="$2"
@ -816,6 +952,14 @@ function download_with_progress() {
fi fi
} }
# ------------------------------------------------------------------------------
# Installs or upgrades uv (Python package manager) from GitHub releases.
#
# Description:
# - Downloads architecture-specific tarball
# - Places binary in /usr/local/bin
# ------------------------------------------------------------------------------
function setup_uv() { function setup_uv() {
$STD msg_info "Checking uv installation..." $STD msg_info "Checking uv installation..."
UV_BIN="/usr/local/bin/uv" UV_BIN="/usr/local/bin/uv"
@ -869,6 +1013,13 @@ function setup_uv() {
msg_ok "uv installed/updated to $LATEST_VERSION" msg_ok "uv installed/updated to $LATEST_VERSION"
} }
# ------------------------------------------------------------------------------
# Ensures /usr/local/bin is permanently in system PATH.
#
# Description:
# - Adds to /etc/profile.d if not present
# ------------------------------------------------------------------------------
function ensure_usr_local_bin_persist() { function ensure_usr_local_bin_persist() {
local PROFILE_FILE="/etc/profile.d/custom_path.sh" local PROFILE_FILE="/etc/profile.d/custom_path.sh"
@ -878,6 +1029,14 @@ function ensure_usr_local_bin_persist() {
fi fi
} }
# ------------------------------------------------------------------------------
# Installs or updates Ghostscript (gs) from source.
#
# Description:
# - Fetches latest release
# - Builds and installs system-wide
# ------------------------------------------------------------------------------
function setup_gs() { function setup_gs() {
msg_info "Setup Ghostscript" msg_info "Setup Ghostscript"
mkdir -p /tmp mkdir -p /tmp
@ -931,3 +1090,93 @@ function setup_gs() {
msg_error "Ghostscript installation failed" msg_error "Ghostscript installation failed"
fi fi
} }
# ------------------------------------------------------------------------------
# Installs rbenv and ruby-build, installs Ruby and optionally Rails.
#
# Description:
# - Downloads rbenv and ruby-build from GitHub
# - Compiles and installs target Ruby version
# - Optionally installs Rails via gem
#
# Variables:
# RUBY_VERSION - Ruby version to install (default: 3.4.4)
# RUBY_INSTALL_RAILS - true/false to install Rails (default: true)
# ------------------------------------------------------------------------------
setup_rbenv_stack() {
local RUBY_VERSION="${RUBY_VERSION:-3.4.4}"
local RUBY_INSTALL_RAILS="${RUBY_INSTALL_RAILS:-true}"
local RBENV_DIR="$HOME/.rbenv"
local RBENV_BIN="$RBENV_DIR/bin/rbenv"
local PROFILE_FILE="$HOME/.profile"
local TMP_DIR
TMP_DIR=$(mktemp -d)
$STD msg_info "Installing rbenv + ruby-build + Ruby $RUBY_VERSION"
# Fetch latest rbenv release tag from GitHub (e.g. v1.3.2 → 1.3.2)
local RBENV_RELEASE
RBENV_RELEASE=$(curl -fsSL https://api.github.com/repos/rbenv/rbenv/releases/latest | grep '"tag_name":' | cut -d '"' -f4 | sed 's/^v//')
if [[ -z "$RBENV_RELEASE" ]]; then
msg_error "Failed to fetch latest rbenv version"
rm -rf "$TMP_DIR"
return 1
fi
# Download and extract rbenv release
curl -fsSL "https://github.com/rbenv/rbenv/archive/refs/tags/v${RBENV_RELEASE}.tar.gz" -o "$TMP_DIR/rbenv.tar.gz"
tar -xzf "$TMP_DIR/rbenv.tar.gz" -C "$TMP_DIR"
mkdir -p "$RBENV_DIR"
cp -r "$TMP_DIR/rbenv-${RBENV_RELEASE}/." "$RBENV_DIR/"
cd "$RBENV_DIR" && src/configure && make -C src
# Fetch latest ruby-build plugin release tag (e.g. v20250507 → 20250507)
local RUBY_BUILD_RELEASE
RUBY_BUILD_RELEASE=$(curl -fsSL https://api.github.com/repos/rbenv/ruby-build/releases/latest | grep '"tag_name":' | cut -d '"' -f4 | sed 's/^v//')
if [[ -z "$RUBY_BUILD_RELEASE" ]]; then
msg_error "Failed to fetch latest ruby-build version"
rm -rf "$TMP_DIR"
return 1
fi
# Download and install ruby-build plugin
curl -fsSL "https://github.com/rbenv/ruby-build/archive/refs/tags/v${RUBY_BUILD_RELEASE}.tar.gz" -o "$TMP_DIR/ruby-build.tar.gz"
tar -xzf "$TMP_DIR/ruby-build.tar.gz" -C "$TMP_DIR"
mkdir -p "$RBENV_DIR/plugins/ruby-build"
cp -r "$TMP_DIR/ruby-build-${RUBY_BUILD_RELEASE}/." "$RBENV_DIR/plugins/ruby-build/"
echo "$RUBY_BUILD_RELEASE" >"$RBENV_DIR/plugins/ruby-build/RUBY_BUILD_version.txt"
# Persist rbenv init to user's profile
if ! grep -q 'rbenv init' "$PROFILE_FILE"; then
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >>"$PROFILE_FILE"
echo 'eval "$(rbenv init -)"' >>"$PROFILE_FILE"
fi
# Activate rbenv in current shell
export PATH="$RBENV_DIR/bin:$PATH"
eval "$("$RBENV_BIN" init - bash)"
# Install Ruby version if not already present
if "$RBENV_BIN" versions --bare | grep -qx "$RUBY_VERSION"; then
msg_ok "Ruby $RUBY_VERSION already installed"
else
$STD msg_info "Installing Ruby $RUBY_VERSION"
$STD "$RBENV_BIN" install "$RUBY_VERSION"
fi
# Set Ruby version globally
"$RBENV_BIN" global "$RUBY_VERSION"
hash -r
# Optionally install Rails via gem
if [[ "$RUBY_INSTALL_RAILS" == "true" ]]; then
$STD msg_info "Installing latest Rails via gem"
gem install rails
msg_ok "Rails $(rails -v) installed"
fi
rm -rf "$TMP_DIR"
msg_ok "rbenv stack ready (Ruby $RUBY_VERSION)"
}

View File

@ -16,6 +16,15 @@ cat <<"EOF"
EOF EOF
add() { add() {
echo -e "\n IMPORTANT: Tag-Based Monitoring Enabled"
echo "Only VMs and containers with the tag 'mon-restart' will be automatically restarted by this service."
echo
echo "🔧 How to add the tag:"
echo " → Proxmox Web UI: Go to VM/CT → Options → Tags → Add 'mon-restart'"
echo " → CLI: qm set <vmid> -tags mon-restart"
echo " pct set <ctid> -tags mon-restart"
echo
while true; do while true; do
read -p "This script will add Monitor All to Proxmox VE. Proceed (y/n)? " yn read -p "This script will add Monitor All to Proxmox VE. Proceed (y/n)? " yn
case $yn in case $yn in
@ -25,34 +34,34 @@ add() {
esac esac
done done
echo '#!/usr/bin/env bash cat <<'EOF' >/usr/local/bin/ping-instances.sh
#!/usr/bin/env bash
# Read excluded instances from command line arguments # Read excluded instances from command line arguments
excluded_instances=("$@") excluded_instances=("$@")
echo "Excluded instances: ${excluded_instances[@]}" echo "Excluded instances: ${excluded_instances[@]}"
while true; do while true; do
for instance in $(pct list | awk '\''{if(NR>1) print $1}'\''; qm list | awk '\''{if(NR>1) print $1}'\''); do for instance in $(pct list | awk 'NR>1 {print $1}'; qm list | awk 'NR>1 {print $1}'); do
# Skip excluded instances # Skip excluded instances
if [[ " ${excluded_instances[@]} " =~ " ${instance} " ]]; then if [[ " ${excluded_instances[@]} " =~ " ${instance} " ]]; then
echo "Skipping $instance because it is excluded" echo "Skipping $instance because it is excluded"
continue continue
fi fi
# Determine the type of the instance (container or virtual machine) # Determine type and set config command
if pct status $instance >/dev/null 2>&1; then if pct status $instance >/dev/null 2>&1; then
# It is a container type="ct"
config_cmd="pct config" config_cmd="pct config"
IP=$(pct exec $instance ip a s dev eth0 | awk '\''/inet / {print $2}'\'' | cut -d/ -f1)
else else
# It is a virtual machine type="vm"
config_cmd="qm config" config_cmd="qm config"
IP=$(qm guest cmd $instance network-get-interfaces | egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -E "192\.|10\." | head -n 1)
fi fi
# Skip instances based on onboot and templates # Skip templates and onboot-disabled
onboot=$($config_cmd $instance | grep -q "onboot: 0" || ( ! $config_cmd $instance | grep -q "onboot" ) && echo "true" || echo "false") onboot=$($config_cmd $instance | grep -q "onboot: 0" || ( ! $config_cmd $instance | grep -q "onboot" ) && echo "true" || echo "false")
template=$($config_cmd $instance | grep template | grep -q "template:" && echo "true" || echo "false") template=$($config_cmd $instance | grep -q "^template:" && echo "true" || echo "false")
if [ "$onboot" == "true" ]; then if [ "$onboot" == "true" ]; then
echo "Skipping $instance because it is set not to boot" echo "Skipping $instance because it is set not to boot"
@ -62,36 +71,49 @@ while true; do
continue continue
fi fi
# Ping the instance # Check for mon-restart tag
has_tag=$($config_cmd $instance | grep -q "tags:.*mon-restart" && echo "true" || echo "false")
if [ "$has_tag" != "true" ]; then
echo "Skipping $instance because it does not have 'mon-restart' tag"
continue
fi
# Responsiveness check and restart if needed
if [ "$type" == "vm" ]; then
# Check if guest agent responds
if qm guest cmd $instance ping >/dev/null 2>&1; then
echo "VM $instance is responsive via guest agent"
else
echo "$(date): VM $instance is not responding to agent ping, restarting..."
if qm status $instance | grep -q "status: running"; then
qm stop $instance >/dev/null 2>&1
sleep 5
fi
qm start $instance >/dev/null 2>&1
fi
else
# Container: get IP and ping
IP=$(pct exec $instance ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
if ! ping -c 1 $IP >/dev/null 2>&1; then if ! ping -c 1 $IP >/dev/null 2>&1; then
# If the instance can not be pinged, stop and start it
if pct status $instance >/dev/null 2>&1; then
# It is a container
echo "$(date): CT $instance is not responding, restarting..." echo "$(date): CT $instance is not responding, restarting..."
pct stop $instance >/dev/null 2>&1 pct stop $instance >/dev/null 2>&1
sleep 5 sleep 5
pct start $instance >/dev/null 2>&1 pct start $instance >/dev/null 2>&1
else else
# It is a virtual machine echo "CT $instance is responsive"
if qm status $instance | grep -q "status: running"; then
echo "$(date): VM $instance is not responding, restarting..."
qm stop $instance >/dev/null 2>&1
sleep 5
else
echo "$(date): VM $instance is not running, starting..."
fi
qm start $instance >/dev/null 2>&1
fi fi
fi fi
done done
# Wait for 5 minutes. (Edit to your needs)
echo "$(date): Pausing for 5 minutes..." echo "$(date): Pausing for 5 minutes..."
sleep 300 sleep 300
done >/var/log/ping-instances.log 2>&1' >/usr/local/bin/ping-instances.sh
done >/var/log/ping-instances.log 2>&1
EOF
touch /var/log/ping-instances.log touch /var/log/ping-instances.log
# Change file permissions to executable
chmod +x /usr/local/bin/ping-instances.sh chmod +x /usr/local/bin/ping-instances.sh
cat <<EOF >/etc/systemd/system/ping-instances.timer cat <<EOF >/etc/systemd/system/ping-instances.timer
[Unit] [Unit]
Description=Delay ping-instances.service by 5 minutes Description=Delay ping-instances.service by 5 minutes
@ -104,17 +126,17 @@ OnUnitActiveSec=300
WantedBy=timers.target WantedBy=timers.target
EOF EOF
# Create ping-instances.service
cat <<EOF >/etc/systemd/system/ping-instances.service cat <<EOF >/etc/systemd/system/ping-instances.service
[Unit] [Unit]
Description=Ping instances every 5 minutes and restarts if necessary Description=Ping instances every 5 minutes and restart if necessary
After=ping-instances.timer After=ping-instances.timer
Requires=ping-instances.timer Requires=ping-instances.timer
[Service] [Service]
Type=simple Type=simple
# To specify which CT/VM should be excluded, add the CT/VM ID at the end of the line where ExecStart=/usr/local/bin/ping-instances.sh is specified. # To exclude specific instances, pass IDs to ExecStart, e.g.:
# For example: ExecStart=/usr/local/bin/ping-instances.sh 100 102 # ExecStart=/usr/local/bin/ping-instances.sh 100 200
# Virtual machines without the QEMU guest agent installed must be excluded. # Instances must also have the 'mon-restart' tag to be monitored
ExecStart=/usr/local/bin/ping-instances.sh ExecStart=/usr/local/bin/ping-instances.sh
Restart=always Restart=always
@ -125,39 +147,33 @@ StandardError=file:/var/log/ping-instances.log
WantedBy=multi-user.target WantedBy=multi-user.target
EOF EOF
# Reload daemon, enable and start ping-instances.service
systemctl daemon-reload systemctl daemon-reload
systemctl enable -q --now ping-instances.timer systemctl enable -q --now ping-instances.timer
systemctl enable -q --now ping-instances.service systemctl enable -q --now ping-instances.service
clear clear
echo -e "\n To view Monitor All logs: cat /var/log/ping-instances.log" echo -e "\n Monitor All installed."
echo "📄 To view logs: cat /var/log/ping-instances.log"
echo "⚙️ Make sure your VMs or containers have the 'mon-restart' tag to be monitored."
} }
remove() { remove() {
systemctl disable -q --now ping-instances.timer systemctl disable -q --now ping-instances.timer
systemctl disable -q --now ping-instances.service systemctl disable -q --now ping-instances.service
rm /etc/systemd/system/ping-instances.service /etc/systemd/system/ping-instances.timer /usr/local/bin/ping-instances.sh /var/log/ping-instances.log rm -f /etc/systemd/system/ping-instances.service
echo "Removed Monitor All from Proxmox VE" rm -f /etc/systemd/system/ping-instances.timer
rm -f /usr/local/bin/ping-instances.sh
rm -f /var/log/ping-instances.log
echo "Monitor All removed from Proxmox VE"
} }
# Define options for the whiptail menu
OPTIONS=(Add "Add Monitor-All to Proxmox VE" OPTIONS=(Add "Add Monitor-All to Proxmox VE"
Remove "Remove Monitor-All from Proxmox VE") Remove "Remove Monitor-All from Proxmox VE")
# Show the whiptail menu and save the user's choice
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Monitor-All for Proxmox VE" --menu "Select an option:" 10 58 2 \ CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Monitor-All for Proxmox VE" --menu "Select an option:" 10 58 2 \
"${OPTIONS[@]}" 3>&1 1>&2 2>&3) "${OPTIONS[@]}" 3>&1 1>&2 2>&3)
# Check the user's choice and perform the corresponding action
case $CHOICE in case $CHOICE in
"Add") "Add") add ;;
add "Remove") remove ;;
;; *) echo "Exiting..."; exit 0 ;;
"Remove")
remove
;;
*)
echo "Exiting..."
exit 0
;;
esac esac