Compare commits

...

37 Commits

Author SHA1 Message Date
push-app-to-main[bot]
352111765d Add solidinvoice (ct) 2026-08-29 22:34:50 +00:00
community-scripts-pr-app[bot]
bddc28bb57 Update CHANGELOG.md (#16857)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-29 21:38:30 +00:00
CanbiZ (MickLesk)
ceb783d62c github action: post the command that tests a ct/ or install/ change (#16833)
* Post the command that tests a ct/ or install/ change

Reviewing a script change meant working out the URL yourself, and the
obvious guess is wrong: curling the branch URL alone gives you the ct/
script from the PR and the install/ script from main, because each script
pins _CS_DEFAULT_URL to main and that pin is what fills
COMMUNITY_SCRIPTS_URL when it is unset. Frequently the install script is
the only thing that changed.

So the comment spells out both lines, per changed app.

Only for scripts already on the core bootstrap. The older one-liner
resolves everything from ProxmoxVE/main and ignores the variable, so a
command built for it would install main and look like it passed --  worse
than no comment. Those are named instead, with what to do about them.

pull_request_target for fork PRs, and nothing from the PR is checked out
or executed: the file list and the bootstrap line come from the API, and
a branch name that is not [A-Za-z0-9._/-]+ stops the run rather than
reaching a fenced code block.

* Update .github/workflows/pr-test-command.yml

Co-authored-by: Sam Heinz <sam@samheinz.com>

---------

Co-authored-by: Sam Heinz <sam@samheinz.com>
2026-08-29 23:38:09 +02:00
community-scripts-pr-app[bot]
b4398bacc2 Update CHANGELOG.md (#16844)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-28 15:09:51 +00:00
CanbiZ (MickLesk)
a61c3882b5 homepage: set CI=true so pnpm can self-heal node_modules without a TTY (#16841) 2026-08-28 17:09:26 +02:00
community-scripts-pr-app[bot]
856bd4301f Update CHANGELOG.md (#16843)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-28 14:59:34 +00:00
CanbiZ (MickLesk)
c1cff5ce2e Refactor: Calibre-Web database creation (#16842)
* calibre-web: point cps at explicit db path, src-layout package has no default anymore

* calibre-web: fix empty-library bootstrap, migrate pre-existing library on update
2026-08-29 00:59:06 +10:00
community-scripts-pr-app[bot]
bd0529547c Update CHANGELOG.md (#16840)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-28 12:32:25 +00:00
CanbiZ (MickLesk)
7b1c60f57a droppedneedle: launch via automatic_upgrade orchestrator, not raw target_main:app (#16834) 2026-08-28 14:32:00 +02:00
community-scripts-pr-app[bot]
61d5c61071 Update CHANGELOG.md (#16839)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-28 11:11:49 +00:00
CanbiZ (MickLesk)
374230d387 calibre-web: point cps at explicit db path, src-layout package has no default anymore (#16832) 2026-08-28 21:11:22 +10:00
community-scripts-pr-app[bot]
6c3ef6fc8b Update CHANGELOG.md (#16838)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-28 11:10:47 +00:00
community-scripts-pr-app[bot]
3334ac5bcd Update CHANGELOG.md (#16837)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-28 11:10:22 +00:00
CanbiZ (MickLesk)
e87cc87857 podman: pull portainer images before systemd unit start to avoid start timeout (#16831) 2026-08-28 21:10:20 +10:00
community-scripts-pr-app[bot]
1e777012c0 Update CHANGELOG.md (#16836)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-28 11:10:00 +00:00
CanbiZ (MickLesk)
81ad04344d mastodon: read .ruby-version dynamically instead of hardcoding 4.0.5 (#16829) 2026-08-28 21:09:57 +10:00
CanbiZ (MickLesk)
b194287cd5 gitea: make gitea own its home dir instead of toggling group perms (#16830) 2026-08-28 21:09:33 +10:00
community-scripts-pr-app[bot]
d14ca63429 Update CHANGELOG.md (#16825)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-28 01:20:05 +00:00
Tobias
1b714dceda pve-ups: fix: add pip binary (#16820)
* pve-ups: fix: pip binary

* pve-ups: fix: pip binary
2026-08-28 11:19:40 +10:00
community-scripts-pr-app[bot]
519f5630ce Update CHANGELOG.md (#16823)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-27 19:44:27 +00:00
Michel Roegl-Brunner
8734eba9a7 excalidash: Add a sed to switch to the correct DB Provider (#16814) 2026-08-27 21:43:54 +02:00
community-scripts-pr-app[bot]
d80fbc9629 Update CHANGELOG.md (#16817)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-27 14:12:00 +00:00
Michel Roegl-Brunner
f114aa553c fix(stirling-pdf): remove broken ExecStop using %n (#16813)
ExecStop=/bin/kill -15 %n expands %n to the unit name, not a PID, so
/bin/kill fails to parse it and logs a spurious status=1/FAILURE on
every stop/restart. Type=simple already sends SIGTERM to the main PID
and SuccessExitStatus=143 makes that a graceful stop, so the line is
redundant and broken. Fixes #16807
2026-08-27 16:11:30 +02:00
community-scripts-pr-app[bot]
db80438531 Update CHANGELOG.md (#16812)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-27 08:05:36 +00:00
Michel Roegl-Brunner
07d1f0837d Fix: Incorporate the new update functions to prevent a empty grep on … (#16809)
* Fix: Incorporate the new update functions to prevent a empty grep on the legacy link in /usr/bin/update

* Remove outdated comments from update-apps.sh

Removed comments regarding the new-style entrypoint and fallback logic for service extraction.

---------

Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
2026-08-27 10:05:08 +02:00
community-scripts-pr-app[bot]
45a6102d48 Update CHANGELOG.md (#16811)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-27 07:56:44 +00:00
community-scripts-pr-app[bot]
6cc27497a0 Update CHANGELOG.md (#16810)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-27 07:56:22 +00:00
push-app-to-main[bot]
beb5c3a573 Seanime (#16777)
* Add seanime (ct)

* Update ct/seanime.sh

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: Sam Heinz <sam@samheinz.com>
2026-08-27 09:56:12 +02:00
push-app-to-main[bot]
e60b90f385 Yopass (#16778)
* Add yopass (ct)

* Update ct/yopass.sh

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: Sam Heinz <sam@samheinz.com>
2026-08-27 09:55:56 +02:00
community-scripts-pr-app[bot]
fadcb0c375 Update CHANGELOG.md (#16802)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-26 19:28:08 +00:00
Jonathan Starck
89f5d3000e [Fix]: LimeSurvey - enable Apache mod_rewrite (#16767) 2026-08-26 21:27:12 +02:00
community-scripts-pr-app[bot]
0a6e59dab2 Update CHANGELOG.md (#16801)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-26 19:26:53 +00:00
CanbiZ (MickLesk)
4168f6c5d4 endurain: migrate legacy FRONTEND_DIR path on update (#16794) 2026-08-26 21:26:31 +02:00
community-scripts-pr-app[bot]
a51488a406 Update CHANGELOG.md (#16800)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-26 19:26:18 +00:00
CanbiZ (MickLesk)
ab1869fbb0 tools.func: recognize bare XZ-compressed tarballs in fetch_and_deploy* (#16796) 2026-08-26 21:25:51 +02:00
community-scripts-pr-app[bot]
e470b6ddf1 Update CHANGELOG.md (#16799)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-26 19:25:06 +00:00
CanbiZ (MickLesk)
416deb8fd0 tools.func: fix mongodb version comparison, guard apt purge against removing dependents (#16795) 2026-08-26 21:24:33 +02:00
31 changed files with 912 additions and 39 deletions

171
.github/workflows/pr-test-command.yml generated vendored Normal file
View File

@@ -0,0 +1,171 @@
name: PR test command
# Posts a ready-to-run test command for reviewers.
# It uses this PRs script branch with the production engine, since both resolve
# independently. Only scripts using community-scripts/core are supported.
#
# pull_request_target allows comments on fork PRs. No PR code is checked out or
# executed; API inputs are validated and the comment is assembled in JavaScript.
on:
pull_request_target:
branches: ["main"]
types: [opened, synchronize, reopened]
paths:
- "ct/**"
- "install/**"
jobs:
comment:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: self-hosted
permissions:
pull-requests: write
contents: read
steps:
- uses: actions/github-script@v9
with:
script: |
const MARKER = '<!-- pr-test-command -->';
const MAX_APPS = 10;
const pr = context.payload.pull_request;
const head = pr.head.repo; // null when the fork is gone
if (!head) return;
const owner = context.repo.owner;
const repo = context.repo.repo;
// Git allows backticks in a ref name, and this one ends up inside a
// fenced block. Anything outside the ordinary set is not worth
// rendering, so bail rather than escape.
const ref = pr.head.ref;
if (!/^[A-Za-z0-9._\/-]+$/.test(ref)) return;
const base = `https://raw.githubusercontent.com/${head.full_name}/${ref}`;
const files = await github.paginate(github.rest.pulls.listFiles, {
owner, repo, pull_number: pr.number, per_page: 100,
});
// ct/foo.sh and install/foo-install.sh are the same app. A removed
// file has nothing left to run.
const apps = new Map(); // slug -> {ct, install}
for (const f of files) {
if (f.status === 'removed') continue;
let m = f.filename.match(/^ct\/([a-z0-9][a-z0-9._-]*)\.sh$/);
if (m) { apps.set(m[1], { ...apps.get(m[1]), ct: true }); continue; }
m = f.filename.match(/^install\/([a-z0-9][a-z0-9._-]*)-install\.sh$/);
if (m) apps.set(m[1], { ...apps.get(m[1]), install: true });
}
if (apps.size === 0) return;
// Read the ct script at the PR head to see which engine it loads.
// Read only -- it is never sourced or run.
async function bootstrapOf(slug) {
try {
const res = await github.rest.repos.getContent({
owner: head.owner.login, repo: head.name,
path: `ct/${slug}.sh`, ref: pr.head.sha,
});
if (!res.data.content) return 'unknown';
const text = Buffer.from(res.data.content, 'base64').toString('utf8');
const firstLines = text.split('\n').slice(0, 12).join('\n');
return /_cs_boot=/.test(firstLines) ? 'core' : 'legacy';
} catch (e) {
return e.status === 404 ? 'missing' : 'unknown';
}
}
const ready = [], legacy = [], missing = [];
for (const slug of [...apps.keys()].sort()) {
const kind = await bootstrapOf(slug);
if (kind === 'core') ready.push(slug);
else if (kind === 'legacy') legacy.push(slug);
else if (kind === 'missing') missing.push(slug);
}
const lines = [MARKER];
if (ready.length > 0) {
const shown = ready.slice(0, MAX_APPS);
lines.push(
'### Try this branch',
'',
'The engine and the scripts resolve independently, so this runs the changed',
'`ct/` and `install/` scripts against the **production** engine:',
'',
);
for (const slug of shown) {
lines.push(
'```bash',
`export COMMUNITY_SCRIPTS_URL=${base}`,
`bash -c "$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/ct/${slug}.sh")"`,
'```',
'',
);
}
if (ready.length > shown.length) {
lines.push(
`${ready.length - shown.length} more script(s) changed; same command, different slug.`,
'',
);
}
lines.push(
'Both lines are needed. Each script pins `_CS_DEFAULT_URL` to `main`, and that',
'pin is what fills `COMMUNITY_SCRIPTS_URL` when the variable is unset — so',
'curling the branch URL on its own gives you the `ct/` script from this PR and',
'the `install/` script from `main`. Frequently the one you meant to test.',
'',
'The same command works on an Incus host: the engine detects the platform and',
'loads the matching backend, while the scripts still come from this branch.',
'',
'<details><summary>Useful while testing</summary>',
'',
'`dev_mode=net` logs every fetch with status and URL, which is the quickest way',
'to confirm the branch is really being used. `dev_mode=keep` stops a failed',
'build from deleting the container along with the evidence.',
'',
'```bash',
`export COMMUNITY_SCRIPTS_URL=${base}`,
`dev_mode=net,keep bash -c "$(curl -fsSL "$COMMUNITY_SCRIPTS_URL/ct/${shown[0]}.sh")"`,
'```',
'</details>',
);
}
if (legacy.length > 0) {
lines.push(
'',
ready.length > 0 ? '---' : '### Not testable this way yet',
'',
`\`${legacy.join('`, `')}\` still uses the older one-liner bootstrap, which`,
'resolves everything from `ProxmoxVE/main` and ignores `COMMUNITY_SCRIPTS_URL`.',
'There is no way to point it at this branch — test it from a checkout on the',
'host instead, or migrate the script to the `_cs_boot` bootstrap first.',
);
}
if (missing.length > 0) {
lines.push(
'',
`No \`ct/\` script found for \`${missing.join('`, `')}\`, so there is nothing to`,
'run. If the install script was renamed, its `ct/` counterpart needs the same',
'name.',
);
}
if (lines.length === 1) return; // marker only, nothing worth saying
const body = lines.join('\n');
// Update in place rather than posting again on every push.
const comments = await github.paginate(github.rest.issues.listComments, {
owner, repo, issue_number: pr.number, per_page: 100,
});
const mine = comments.find(c => c.body.includes(MARKER));
if (mine) {
if (mine.body !== body) {
await github.rest.issues.updateComment({ owner, repo, comment_id: mine.id, body });
}
} else {
await github.rest.issues.createComment({ owner, repo, issue_number: pr.number, body });
}

View File

@@ -527,6 +527,50 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details>
## 2026-08-29
### 📚 Documentation
- github action: post the command that tests a ct/ or install/ change [@MickLesk](https://github.com/MickLesk) ([#16833](https://github.com/community-scripts/ProxmoxVE/pull/16833))
## 2026-08-28
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- homepage: set CI=true so pnpm can self-heal node_modules without a TTY [@MickLesk](https://github.com/MickLesk) ([#16841](https://github.com/community-scripts/ProxmoxVE/pull/16841))
- droppedneedle: launch via automatic_upgrade orchestrator [@MickLesk](https://github.com/MickLesk) ([#16834](https://github.com/community-scripts/ProxmoxVE/pull/16834))
- calibre-web: point cps at explicit db path, src-layout package has no default anymore [@MickLesk](https://github.com/MickLesk) ([#16832](https://github.com/community-scripts/ProxmoxVE/pull/16832))
- podman: pull portainer images before systemd unit start to avoid start timeout [@MickLesk](https://github.com/MickLesk) ([#16831](https://github.com/community-scripts/ProxmoxVE/pull/16831))
- gitea: make gitea own its home dir instead of toggling group perms [@MickLesk](https://github.com/MickLesk) ([#16830](https://github.com/community-scripts/ProxmoxVE/pull/16830))
- pve-ups: fix: add pip binary [@CrazyWolf13](https://github.com/CrazyWolf13) ([#16820](https://github.com/community-scripts/ProxmoxVE/pull/16820))
- #### 🔧 Refactor
- Refactor: Calibre-Web database creation [@MickLesk](https://github.com/MickLesk) ([#16842](https://github.com/community-scripts/ProxmoxVE/pull/16842))
- mastodon: read .ruby-version dynamically instead of hardcoding 4.0.5 [@MickLesk](https://github.com/MickLesk) ([#16829](https://github.com/community-scripts/ProxmoxVE/pull/16829))
## 2026-08-27
### 🆕 New Scripts
- Seanime ([#16777](https://github.com/community-scripts/ProxmoxVE/pull/16777))
- Yopass ([#16778](https://github.com/community-scripts/ProxmoxVE/pull/16778))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- excalidash: Add a sed to switch to the correct DB Provider [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#16814](https://github.com/community-scripts/ProxmoxVE/pull/16814))
- fix(stirling-pdf): remove broken ExecStop using %n [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#16813](https://github.com/community-scripts/ProxmoxVE/pull/16813))
### 🧰 Tools
- #### 🐞 Bug Fixes
- Fix: Incorporate the new update functions to prevent a empty grep on … [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#16809](https://github.com/community-scripts/ProxmoxVE/pull/16809))
## 2026-08-26
### 🆕 New Scripts
@@ -541,6 +585,20 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
- Directus ([#16779](https://github.com/community-scripts/ProxmoxVE/pull/16779))
- HAProxy ([#16760](https://github.com/community-scripts/ProxmoxVE/pull/16760))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- [Fix]: LimeSurvey - enable Apache mod_rewrite [@jonathan8devs](https://github.com/jonathan8devs) ([#16767](https://github.com/community-scripts/ProxmoxVE/pull/16767))
- endurain: migrate legacy FRONTEND_DIR path on update [@MickLesk](https://github.com/MickLesk) ([#16794](https://github.com/community-scripts/ProxmoxVE/pull/16794))
### 💾 Core
- #### 🐞 Bug Fixes
- tools.func: recognize bare XZ-compressed tarballs in fetch_and_deploy* [@MickLesk](https://github.com/MickLesk) ([#16796](https://github.com/community-scripts/ProxmoxVE/pull/16796))
- tools.func: fix mongodb version comparison, guard apt purge against removing dependents [@MickLesk](https://github.com/MickLesk) ([#16795](https://github.com/community-scripts/ProxmoxVE/pull/16795))
### 📂 Github
- github: teach the PocketBase bot every field [@MickLesk](https://github.com/MickLesk) ([#16781](https://github.com/community-scripts/ProxmoxVE/pull/16781))

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: mikolaj92
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -35,8 +37,7 @@ function update_script() {
systemctl stop calibre-web
msg_ok "Stopped Service"
create_backup /opt/calibre-web/app.db \
/opt/calibre-web/data
create_backup /opt/calibre-web/data
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Calibre-Web" "janeczku/calibre-web" "prebuild" "latest" "/opt/calibre-web" "calibreweb*.tar.gz"
setup_uv
@@ -48,11 +49,26 @@ function update_script() {
$STD uv pip install --python /opt/calibre-web/.venv/bin/python --no-cache-dir .
msg_ok "Installed Dependencies"
sed -i 's|^ExecStart=.*|ExecStart=/opt/calibre-web/.venv/bin/cps|' /etc/systemd/system/calibre-web.service
sed -i 's|^ExecStart=.*|ExecStart=/opt/calibre-web/.venv/bin/cps -p /opt/calibre-web/data/app.db|' /etc/systemd/system/calibre-web.service
if ! grep -q '^Environment=HOME=' /etc/systemd/system/calibre-web.service; then
sed -i '/^ExecStart=/i Environment=HOME=/opt/calibre-web/data' /etc/systemd/system/calibre-web.service
fi
$STD systemctl daemon-reload
restore_backup
mkdir -p /opt/calibre-web-library
if [[ -f /opt/calibre-web/data/metadata.db && ! -f /opt/calibre-web-library/metadata.db ]]; then
msg_info "Migrating Calibre Library to its own directory"
find /opt/calibre-web/data -mindepth 1 -maxdepth 1 ! -name app.db ! -name .calibre-web -exec mv -t /opt/calibre-web-library -- {} +
msg_ok "Migrated Calibre Library"
fi
if [[ ! -f /opt/calibre-web-library/metadata.db ]]; then
msg_info "Creating Empty Calibre Library"
$STD calibredb list --with-library /opt/calibre-web-library
msg_ok "Created Empty Calibre Library"
fi
msg_info "Starting Service"
systemctl start calibre-web
msg_ok "Started Service"

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: michelroegl-brunner | Co-Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -91,7 +93,7 @@ WorkingDirectory=/opt/droppedneedle/backend
Environment=ROOT_APP_DIR=/opt/droppedneedle/backend
Environment=PORT=8688
# Environment=SLSKD_DOWNLOADS_PATH=<path-to-slskd-downloads>
ExecStart=/opt/droppedneedle/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8688 --loop uvloop --http httptools --workers 1
ExecStart=/opt/droppedneedle/venv/bin/python -m maintenance.automatic_upgrade --start-target
Restart=on-failure
RestartSec=5
@@ -100,8 +102,11 @@ WantedBy=multi-user.target
EOF
rm -f /etc/systemd/system/musicseerr.service
msg_ok "Replaced systemd Service"
elif ! grep -q 'SLSKD' /etc/systemd/system/droppedneedle.service; then
sed -i '\|=8688$|a# Environment=SLSKD_DOWNLOADS_PATH=<path-to-slskd-downloads>' /etc/systemd/system/droppedneedle.service
else
if ! grep -q 'SLSKD' /etc/systemd/system/droppedneedle.service; then
sed -i '\|=8688$|a# Environment=SLSKD_DOWNLOADS_PATH=<path-to-slskd-downloads>' /etc/systemd/system/droppedneedle.service
fi
sed -i 's|^ExecStart=.*|ExecStart=/opt/droppedneedle/venv/bin/python -m maintenance.automatic_upgrade --start-target|' /etc/systemd/system/droppedneedle.service
fi
systemctl daemon-reload

View File

@@ -35,29 +35,29 @@ function update_script() {
msg_ok "Stopped Service"
NODE_VERSION="24" setup_nodejs
create_backup /opt/endurain/.env /opt/endurain/frontend/dist/env.js
CLEAN_INSTALL=1 fetch_and_deploy_codeberg_release "endurain" "endurain-project/endurain" "tarball" "latest" "/opt/endurain"
msg_info "Preparing Update"
msg_info "Updating Endurain Frontend"
cd /opt/endurain
rm -rf /opt/endurain/{docs,example.env,screenshot_01.png} /opt/endurain/docker* /opt/endurain/*.yml
msg_ok "Prepared Update"
msg_info "Updating Frontend"
cd /opt/endurain/frontend
$STD npm ci
$STD npm run build
msg_ok "Updated Frontend"
msg_ok "Updated Endurain Frontend"
restore_backup
msg_info "Updating Backend"
if grep -qxF 'FRONTEND_DIR="/opt/endurain/frontend/app/dist"' /opt/endurain/.env; then
sed -i 's|^FRONTEND_DIR="/opt/endurain/frontend/app/dist"$|FRONTEND_DIR="/opt/endurain/frontend/dist"|' /opt/endurain/.env
fi
msg_info "Updating Endurain Backend"
cd /opt/endurain/backend
UV_VERSION=$(grep -Po 'required-version\s*=\s*"\K[^"]+' pyproject.toml 2>/dev/null || echo "0.11.18")
UV_VERSION="$UV_VERSION" setup_uv
$STD uv sync --frozen --no-dev
msg_ok "Backend Updated"
msg_ok "Endurain Backend Updated"
msg_info "Starting Service"
systemctl start endurain

View File

@@ -42,6 +42,7 @@ function update_script() {
msg_info "Configuring Database Provider (${DATABASE_PROVIDER:-sqlite})"
cd /opt/excalidash/backend
sed -i '/datasource db {/,/}/ s/provider = env("[^"]*")/provider = "'"${DATABASE_PROVIDER:-sqlite}"'"/' prisma/schema.prisma
sed -i '/datasource db {/,/}/ s/provider = "[^"]*"/provider = "'"${DATABASE_PROVIDER:-sqlite}"'"/' prisma/schema.prisma
mv prisma/migrations/"${DATABASE_PROVIDER:-sqlite}"/* prisma/migrations/
rm -rf prisma/migrations/postgresql prisma/migrations/sqlite
msg_ok "Configured Database Provider"

6
ct/headers/seanime Normal file
View File

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

6
ct/headers/solidinvoice Normal file
View File

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

6
ct/headers/yopass Normal file
View File

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

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -77,6 +79,10 @@ EOF
rm /opt/homepage/env.bak
chmod 600 /opt/homepage/.env
fi
if ! grep -q '^Environment=CI=true' /etc/systemd/system/homepage.service; then
sed -i '/^ExecStart=/i Environment=CI=true' /etc/systemd/system/homepage.service
systemctl daemon-reload
fi
msg_ok "Updated Homepage"
msg_info "Starting service"

View File

@@ -28,6 +28,13 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
if [[ ! -L /etc/apache2/mods-enabled/rewrite.load ]]; then
msg_info "Enabling Apache mod_rewrite"
$STD a2enmod rewrite
systemctl restart apache2
msg_ok "Enabled Apache mod_rewrite"
fi
setup_mariadb
msg_warn "Application is updated via Web Interface"

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -40,6 +42,7 @@ function update_script() {
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "mastodon" "mastodon/mastodon" "tarball"
sed -i "s/config.force_ssl = true/config.force_ssl = ENV.fetch('LOCAL_HTTPS', 'false') == 'true'/" /opt/mastodon/config/environments/production.rb
sed -i "s/https = Rails.env.production? || ENV\['LOCAL_HTTPS'\] == 'true'/https = ENV.fetch('LOCAL_HTTPS', 'false') == 'true'/" /opt/mastodon/config/initializers/1_hosts.rb
RUBY_VERSION="$(cat /opt/mastodon/.ruby-version)" RUBY_INSTALL_RAILS="false" setup_ruby
msg_info "Installing Ruby Dependencies"
cd /opt/mastodon

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE

View File

@@ -41,7 +41,7 @@ function update_script() {
msg_info "Updating Application"
cd /opt/pve-usv
$STD uv venv --clear venv
$STD uv venv --clear --seed venv
$STD uv pip install --python venv/bin/python .
chown -R pveusv:pveusv /opt/pve-usv
chmod 0755 deploy/pve-usv-agent.sh

63
ct/seanime.sh Normal file
View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: hasan-ismail
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://seanime.app/
APP="Seanime"
var_tags="${var_tags:-media;anime;manga}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_arm64="${var_arm64:-yes}"
var_unprivileged="${var_unprivileged:-1}"
var_gpu="${var_gpu:-yes}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/seanime ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "seanime" "5rahim/seanime"; then
msg_info "Stopping Service"
systemctl stop seanime
msg_ok "Stopped Service"
create_backup /opt/seanime-data/config.toml
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "seanime" "5rahim/seanime" "prebuild" "latest" "/opt/seanime" "seanime-[0-9]*_Linux_$(arch_resolve x86_64 arm64).tar.gz"
chmod +x /opt/seanime/seanime
restore_backup
msg_info "Starting Service"
systemctl start seanime
msg_ok "Started Service"
msg_ok "Updated successfully!"
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}:43211${CL}"

57
ct/solidinvoice.sh Normal file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Pierre du Plessis
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/solidinvoice/solidinvoice
APP="SolidInvoice"
var_tags="${var_tags:-invoicing;finance;billing}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
#var_arm64="${var_arm64:-no}" # unset = ask the user; set yes/no only when verified
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 /usr/bin/solidinvoice ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "solidinvoice" "SolidInvoice/SolidInvoice"; then
msg_info "Stopping ${APP} Service"
systemctl stop solidinvoice
msg_ok "Stopped ${APP} Service"
fetch_and_deploy_gh_release "solidinvoice" "SolidInvoice/SolidInvoice" "singlefile" "latest" "/usr/bin" "solidinvoice-linux-$(arch_resolve)"
msg_info "Starting ${APP} Service"
systemctl start solidinvoice
msg_ok "Started ${APP} Service"
msg_ok "Updated Successfully"
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 "${GATEWAY}${BGN}http://${IP}:8765${CL}"

65
ct/yopass.sh Normal file
View File

@@ -0,0 +1,65 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/jhaals/yopass
APP="Yopass"
var_tags="${var_tags:-security;secrets}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
#var_arm64="${var_arm64:-no}" # unset = ask the user; set yes/no only when verified
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/yopass ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "yopass" "jhaals/yopass"; then
msg_info "Stopping Service"
systemctl stop yopass
msg_ok "Stopped Service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "yopass" "jhaals/yopass" "tarball"
msg_info "Building Yopass"
cd /opt/yopass
$STD go build -ldflags "-X main.version=$(cat ~/.yopass)" ./cmd/yopass-server
cd /opt/yopass/website
$STD yarn install --network-timeout 600000
$STD yarn build
msg_ok "Built Yopass"
msg_info "Starting Service"
systemctl start yopass
msg_ok "Started Service"
msg_ok "Updated successfully!"
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 "${GATEWAY}${BGN}https://${IP}:1337${CL}"

View File

@@ -42,8 +42,14 @@ $STD uv pip install --python /opt/calibre-web/.venv/bin/python --no-cache-dir --
$STD uv pip install --python /opt/calibre-web/.venv/bin/python --no-cache-dir .
msg_ok "Installed Python Dependencies"
mkdir -p /opt/calibre-web/data /opt/calibre-web-library
if [[ ! -f /opt/calibre-web-library/metadata.db ]]; then
msg_info "Creating Empty Calibre Library"
$STD calibredb list --with-library /opt/calibre-web-library
msg_ok "Created Empty Calibre Library"
fi
msg_info "Creating Service"
mkdir -p /opt/calibre-web/data
cat <<EOF >/etc/systemd/system/calibre-web.service
[Unit]
Description=Calibre-Web Service
@@ -53,8 +59,9 @@ After=network.target
Type=simple
User=root
Environment="QTWEBENGINE_CHROMIUM_FLAGS=--no-sandbox"
Environment=HOME=/opt/calibre-web/data
WorkingDirectory=/opt/calibre-web
ExecStart=/opt/calibre-web/.venv/bin/cps
ExecStart=/opt/calibre-web/.venv/bin/cps -p /opt/calibre-web/data/app.db
Restart=on-failure
RestartSec=5

View File

@@ -45,7 +45,7 @@ WorkingDirectory=/opt/droppedneedle/backend
Environment=ROOT_APP_DIR=/opt/droppedneedle/backend
Environment=PORT=8688
# Environment=SLSKD_DOWNLOADS_PATH=<path-to-slskd-downloads>
ExecStart=/opt/droppedneedle/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8688 --loop uvloop --http httptools --workers 1
ExecStart=/opt/droppedneedle/venv/bin/python -m maintenance.automatic_upgrade --start-target
Restart=on-failure
RestartSec=5

View File

@@ -29,10 +29,9 @@ setup_deb_based() {
mkdir -p /var/lib/gitea/{custom,data,log}
chown -R gitea:gitea /var/lib/gitea/
chmod -R 750 /var/lib/gitea/
chown root:gitea /etc/gitea
chmod 770 /etc/gitea
sudo -u gitea ln -s /var/lib/gitea/data/.ssh/ /etc/gitea/.ssh
chown gitea:gitea /etc/gitea
chmod 750 /etc/gitea
sudo -u gitea ln -s /var/lib/gitea/data/.ssh/ /etc/gitea/.ssh
msg_ok "Configured Gitea"
msg_info "Creating Service"

View File

@@ -63,6 +63,7 @@ Restart=always
RestartSec=1
User=root
WorkingDirectory=/opt/homepage/
Environment=CI=true
ExecStart=pnpm start
[Install]

View File

@@ -60,6 +60,7 @@ cat <<EOF >/etc/apache2/sites-enabled/000-default.conf
EOF
chown -R www-data:www-data "/opt/limesurvey"
chmod -R 750 "/opt/limesurvey"
$STD a2enmod rewrite
systemctl reload apache2
rm -rf "$temp_file"
msg_ok "Set up LimeSurvey"

View File

@@ -48,13 +48,13 @@ PG_VERSION="17" setup_postgresql
PG_DB_NAME="mastodon_production" PG_DB_USER="mastodon" PG_DB_SKIP_ALTER_ROLE="true" setup_postgresql_db
$STD sudo -u postgres psql -c "ALTER USER mastodon CREATEDB;"
RUBY_VERSION="4.0.5" RUBY_INSTALL_RAILS="false" setup_ruby
export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"
fetch_and_deploy_gh_release "mastodon" "mastodon/mastodon" "tarball"
sed -i "s/config.force_ssl = true/config.force_ssl = ENV.fetch('LOCAL_HTTPS', 'false') == 'true'/" /opt/mastodon/config/environments/production.rb
sed -i "s/https = Rails.env.production? || ENV\['LOCAL_HTTPS'\] == 'true'/https = ENV.fetch('LOCAL_HTTPS', 'false') == 'true'/" /opt/mastodon/config/initializers/1_hosts.rb
RUBY_VERSION="$(cat /opt/mastodon/.ruby-version)" RUBY_INSTALL_RAILS="false" setup_ruby
export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"
msg_info "Installing Ruby Dependencies"
cd /opt/mastodon
$STD bundle config set --local without 'development test'

View File

@@ -51,6 +51,7 @@ read -r -p "${TAB3}Would you like to add Portainer? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Portainer $PORTAINER_LATEST_VERSION"
podman volume create portainer_data >/dev/null
$STD podman pull docker.io/portainer/portainer-ce:latest
cat <<EOF >/etc/containers/systemd/portainer.container
[Unit]
Description=Portainer Container
@@ -77,6 +78,7 @@ else
read -r -p "${TAB3}Would you like to add the Portainer Agent? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Portainer agent $PORTAINER_AGENT_LATEST_VERSION"
$STD podman pull docker.io/portainer/agent:latest
cat <<EOF >/etc/containers/systemd/portainer-agent.container
[Unit]
Description=Portainer Agent Container

View File

@@ -27,7 +27,7 @@ install -d -o pveusv -g pveusv -m 0750 \
/var/lib/pve-usv/updates
chown -R pveusv:pveusv /opt/pve-usv
cd /opt/pve-usv
$STD uv venv --clear venv
$STD uv venv --clear --seed venv
$STD uv pip install --python venv/bin/python .
chmod 0755 deploy/pve-usv-agent.sh
msg_ok "Set up Application"

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: hasan-ismail
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://seanime.app/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
setup_hwaccel
msg_info "Installing FFmpeg"
setup_deb822_repo \
"jellyfin" \
"https://repo.jellyfin.org/jellyfin_team.gpg.key" \
"https://repo.jellyfin.org/debian" \
"$(get_os_info codename)"
$STD apt install -y jellyfin-ffmpeg7
ln -sf /usr/lib/jellyfin-ffmpeg/ffmpeg /usr/bin/ffmpeg
ln -sf /usr/lib/jellyfin-ffmpeg/ffprobe /usr/bin/ffprobe
msg_ok "Installed FFmpeg"
fetch_and_deploy_gh_release "seanime" "5rahim/seanime" "prebuild" "latest" "/opt/seanime" "seanime-[0-9]*_Linux_$(arch_resolve x86_64 arm64).tar.gz"
chmod +x /opt/seanime/seanime
msg_info "Configuring Seanime"
SEANIME_PASSWORD=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)
mkdir -p /opt/seanime-data
cat <<EOF >/opt/seanime-data/config.toml
[server]
password = "${SEANIME_PASSWORD}"
EOF
cat <<EOF >/root/seanime.creds
Seanime URL: http://${LOCAL_IP}:43211
Password: ${SEANIME_PASSWORD}
EOF
msg_ok "Configured Seanime"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/seanime.service
[Unit]
Description=Seanime
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/seanime
ExecStart=/opt/seanime/seanime --datadir /opt/seanime-data --host 0.0.0.0
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now seanime
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -0,0 +1,190 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Pierre du Plessis
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/solidinvoice/solidinvoice
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Creating Directories"
mkdir -p /etc/solidinvoice /var/lib/solidinvoice
msg_ok "Created Directories"
fetch_and_deploy_gh_release "solidinvoice" "SolidInvoice/SolidInvoice" "singlefile" "latest" "/usr/bin" "solidinvoice-linux-$(arch_resolve)"
msg_info "Configuring SolidInvoice"
cat <<'EOF' >/etc/solidinvoice/solidinvoice.env
# SolidInvoice environment configuration
# This file is sourced by the systemd service unit.
# CLI flags always take precedence over values set here.
# ------------------------------------------------------------------
# Network
# ------------------------------------------------------------------
# Port to listen on (default: 8765)
#SOLIDINVOICE_PORT=8765
# IP address to bind to (default: auto-detected outbound IP)
#SOLIDINVOICE_SERVER_IP=0.0.0.0
# Domain name — required when using Let's Encrypt or custom certificates.
# When set, the application binds to https://<domain> instead of an IP.
#SOLIDINVOICE_DOMAIN=
# Bind the bundled webserver to every hostname so it answers regardless of the
# Host header — required behind a reverse proxy that forwards the original domain.
SOLIDINVOICE_DOCKER=true
# ------------------------------------------------------------------
# HTTPS / TLS
# ------------------------------------------------------------------
# Disable HTTPS and serve plain HTTP. Set to 1 when running behind a
# reverse proxy (nginx, Caddy, Traefik, etc.) that handles TLS termination.
# Remove or set to 0 when you want the application to manage its own certificates.
SOLIDINVOICE_DISABLE_HTTPS=1
# Enable automatic Let's Encrypt certificates (requires SOLIDINVOICE_DOMAIN).
# Incompatible with SOLIDINVOICE_DISABLE_HTTPS=1.
#SOLIDINVOICE_LETS_ENCRYPT=1
# Paths to a custom TLS certificate and private key (requires SOLIDINVOICE_DOMAIN).
# Incompatible with SOLIDINVOICE_DISABLE_HTTPS=1 and SOLIDINVOICE_LETS_ENCRYPT=1.
#SOLIDINVOICE_SSL_CERT=/etc/ssl/certs/solidinvoice.crt
#SOLIDINVOICE_SSL_KEY=/etc/ssl/private/solidinvoice.key
# ------------------------------------------------------------------
# Performance
# ------------------------------------------------------------------
# Enable FrankenPHP worker mode for improved performance (keeps PHP workers
# alive between requests). Recommended for high-traffic deployments.
# Set to 1 to enable.
#FRANKENPHP_WORKER_MODE=1
# Number of FrankenPHP worker threads when worker mode is enabled (default: 2).
#SOLIDINVOICE_WORKER_THREADS=2
# Number of background messenger worker processes (default: 1).
# Set to 0 to disable built-in workers (use the dedicated 'solidinvoice worker'
# command instead).
#SOLIDINVOICE_MESSENGER_WORKERS=1
# ------------------------------------------------------------------
# Application
# ------------------------------------------------------------------
# Application environment. Change to "dev" only for local development.
#SOLIDINVOICE_ENV=prod
# Enable debug mode (0 or 1). Never enable in production.
#SOLIDINVOICE_DEBUG=0
# Configuration directory — stores generated secrets, OAuth keys, and the
# SQLite database (when no external database is configured).
SOLIDINVOICE_CONFIG_DIR=/etc/solidinvoice
# Installation type identifier used for telemetry when opted in.
SOLIDINVOICE_INSTALL_TYPE=proxmox-community-scripts
# Skip the ASCII art / URL summary printed on startup.
SOLIDINVOICE_SKIP_INTRO=1
# Log format: "json" for structured logs (default for systemd), "console" for human-readable.
SOLIDINVOICE_LOG_FORMAT=json
# ------------------------------------------------------------------
# Database
# ------------------------------------------------------------------
# Database connection URL. Defaults to SQLite stored in SOLIDINVOICE_CONFIG_DIR
# when not set. Supported drivers: mysql, postgresql, sqlite.
#SOLIDINVOICE_DATABASE_URL=mysql://user:password@127.0.0.1:3306/solidinvoice
# ------------------------------------------------------------------
# Email
# ------------------------------------------------------------------
# Outbound mail transport DSN. Overrides the transport configured in the UI.
# See https://symfony.com/doc/current/mailer.html for DSN formats.
#SOLIDINVOICE_MAILER_DSN=smtp://user:password@localhost:25
# From address used for all outgoing emails. Overrides the address configured in the UI.
#SOLIDINVOICE_MAILER_SENDER=SolidInvoice <noreply@example.com>
# ------------------------------------------------------------------
# Async messaging
# ------------------------------------------------------------------
# Messenger transport DSN. Defaults to the database (doctrine) queue.
#SOLIDINVOICE_MESSENGER_DSN=doctrine://default?queue_name=async
# ------------------------------------------------------------------
# Search (optional)
# ------------------------------------------------------------------
# Meilisearch instance for full-text search. Leave blank to disable.
#SOLIDINVOICE_MEILISEARCH_URL=http://localhost:7700
#SOLIDINVOICE_MEILISEARCH_API_KEY=
# ------------------------------------------------------------------
# Localisation
# ------------------------------------------------------------------
# Default locale for the application interface (e.g. en, fr, de, nl).
#SOLIDINVOICE_LOCALE=en
# ------------------------------------------------------------------
# User registration
# ------------------------------------------------------------------
# Allow visitors to create their own accounts (0 = disabled, 1 = enabled).
#SOLIDINVOICE_ALLOW_REGISTRATION=0
# ------------------------------------------------------------------
# Monitoring (optional)
# ------------------------------------------------------------------
# Sentry DSN for error and performance monitoring.
#SOLIDINVOICE_SENTRY_DSN=
# Expose a Prometheus metrics endpoint on a dedicated port.
#SOLIDINVOICE_ENABLE_METRICS=1
#SOLIDINVOICE_METRICS_PORT=9090
EOF
chmod 640 /etc/solidinvoice/solidinvoice.env
msg_ok "Configured SolidInvoice"
msg_info "Creating Service"
cat <<'EOF' >/etc/systemd/system/solidinvoice.service
[Unit]
Description=SolidInvoice
Documentation=https://solidinvoice.co/docs
After=network.target
[Service]
Type=exec
User=root
WorkingDirectory=/var/lib/solidinvoice
ExecStart=/usr/bin/solidinvoice run
EnvironmentFile=/etc/solidinvoice/solidinvoice.env
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now solidinvoice
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -147,7 +147,6 @@ Group=root
EnvironmentFile=/opt/Stirling-PDF/.env
WorkingDirectory=/opt/Stirling-PDF
ExecStart=/usr/bin/java -jar Stirling-PDF.jar
ExecStop=/bin/kill -15 %n
Restart=always
RestartSec=10

69
install/yopass-install.sh Normal file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/jhaals/yopass
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y redis-server
systemctl enable -q --now redis-server
msg_ok "Installed Dependencies"
setup_go
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
fetch_and_deploy_gh_release "yopass" "jhaals/yopass" "tarball"
msg_info "Building Yopass"
cd /opt/yopass
$STD go build -ldflags "-X main.version=$(cat ~/.yopass)" ./cmd/yopass-server
cd /opt/yopass/website
$STD yarn install --network-timeout 600000
$STD yarn build
msg_ok "Built Yopass"
msg_info "Generating SSL Certificate"
mkdir -p /opt/yopass/certificates
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /opt/yopass/certificates/key.pem \
-out /opt/yopass/certificates/cert.pem \
-subj "/C=US/ST=State/L=City/O=Yopass/CN=${LOCAL_IP}" \
-addext "subjectAltName=IP:${LOCAL_IP},DNS:localhost,IP:127.0.0.1" \
2>/dev/null
chmod 600 /opt/yopass/certificates/key.pem
chmod 644 /opt/yopass/certificates/cert.pem
msg_ok "Generated SSL Certificate"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/yopass.service
[Unit]
Description=Yopass
Wants=network-online.target
After=network-online.target redis-server.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/yopass
ExecStart=/opt/yopass/yopass-server --address 0.0.0.0 --port 1337 --tls-cert /opt/yopass/certificates/cert.pem --tls-key /opt/yopass/certificates/key.pem --database redis --redis redis://127.0.0.1:6379/0 --asset-path /opt/yopass/website/dist
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now yopass
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -632,7 +632,7 @@ is_tool_installed() {
;;
mongodb | mongod)
if command -v mongod >/dev/null 2>&1; then
installed_version=$(mongod --version 2>/dev/null | awk '/db version/{print $3}' | cut -d. -f1,2)
installed_version=$(mongod --version 2>/dev/null | awk '/db version/{print $3}' | sed 's/^v//' | cut -d. -f1,2)
fi
;;
node | nodejs)
@@ -685,6 +685,39 @@ is_tool_installed() {
return 0 # Installed and version matches (if specified)
}
# ------------------------------------------------------------------------------
# Checks whether purging the given package glob(s) would also remove packages
# outside those globs (i.e. reverse dependents, such as an app depending on
# mongodb-org-server). Uses `apt-get -s` (simulate) with the stable apt-get
# output format, not `apt`, whose output is explicitly unstable for scripting.
# Returns 0 (safe to purge) or 1 (unsafe - prints the unexpected packages).
# Usage: _purge_is_safe 'mongodb*' ['other-glob*' ...]
# ------------------------------------------------------------------------------
_purge_is_safe() {
local -a globs=("$@")
local -a collateral=()
local pkg glob matched
local sim_out
sim_out=$(apt-get -s purge -y "${globs[@]}" 2>/dev/null) || return 0
while IFS= read -r pkg; do
[[ -z "$pkg" ]] && continue
matched=0
for glob in "${globs[@]}"; do
# shellcheck disable=SC2053
[[ "$pkg" == $glob ]] && {
matched=1
break
}
done
((matched)) || collateral+=("$pkg")
done < <(awk '/^(Remv|Purg) /{print $2}' <<<"$sim_out")
if ((${#collateral[@]} > 0)); then
msg_warn "Refusing purge of '${globs[*]}': would also remove ${collateral[*]}"
return 1
fi
return 0
}
# ------------------------------------------------------------------------------
# Remove old tool version completely (purge + cleanup repos)
# Usage: remove_old_tool_version "mariadb" "repository-name"
@@ -696,11 +729,13 @@ remove_old_tool_version() {
case "$tool_name" in
mariadb)
stop_all_services "mariadb"
_purge_is_safe 'mariadb*' || return 1
$STD apt purge -y 'mariadb*' >/dev/null 2>&1 || true
cleanup_tool_keyrings "mariadb"
;;
mysql)
stop_all_services "mysql"
_purge_is_safe 'mysql*' || return 1
$STD apt purge -y 'mysql*' >/dev/null 2>&1 || true
# Keep data directory for safety (remove manually if needed)
# rm -rf /var/lib/mysql 2>/dev/null || true
@@ -708,12 +743,14 @@ remove_old_tool_version() {
;;
mongodb)
stop_all_services "mongod"
_purge_is_safe 'mongodb*' || return 1
$STD apt purge -y 'mongodb*' >/dev/null 2>&1 || true
# Keep data directory for safety (remove manually if needed)
# rm -rf /var/lib/mongodb 2>/dev/null || true
cleanup_tool_keyrings "mongodb"
;;
node | nodejs)
_purge_is_safe nodejs npm || return 1
$STD apt purge -y nodejs npm >/dev/null 2>&1 || true
# Clean up npm global modules
if command -v npm >/dev/null 2>&1; then
@@ -726,23 +763,27 @@ remove_old_tool_version() {
;;
php)
stop_all_services "php.*-fpm"
_purge_is_safe 'php*' || return 1
$STD apt purge -y 'php*' >/dev/null 2>&1 || true
rm -rf /etc/php 2>/dev/null || true
cleanup_tool_keyrings "deb.sury.org-php" "php"
;;
postgresql)
stop_all_services "postgresql"
_purge_is_safe 'postgresql*' || return 1
$STD apt purge -y 'postgresql*' >/dev/null 2>&1 || true
# Keep data directory for safety (can be removed manually if needed)
# rm -rf /var/lib/postgresql 2>/dev/null || true
cleanup_tool_keyrings "postgresql" "pgdg"
;;
java)
_purge_is_safe 'temurin*' 'adoptium*' 'openjdk*' || return 1
$STD apt purge -y 'temurin*' 'adoptium*' 'openjdk*' >/dev/null 2>&1 || true
cleanup_tool_keyrings "adoptium"
;;
ruby)
cleanup_legacy_install "ruby"
_purge_is_safe 'ruby*' || return 1
$STD apt purge -y 'ruby*' >/dev/null 2>&1 || true
;;
rust)
@@ -754,6 +795,7 @@ remove_old_tool_version() {
;;
clickhouse)
stop_all_services "clickhouse-server"
_purge_is_safe 'clickhouse*' || return 1
$STD apt purge -y 'clickhouse*' >/dev/null 2>&1 || true
# Keep data directory for safety (remove manually if needed)
# rm -rf /var/lib/clickhouse 2>/dev/null || true
@@ -4473,7 +4515,10 @@ setup_clickhouse() {
if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" != "$CLICKHOUSE_VERSION" ]]; then
msg_info "Upgrade ClickHouse from $CURRENT_VERSION to $CLICKHOUSE_VERSION"
stop_all_services "clickhouse-server"
remove_old_tool_version "clickhouse"
remove_old_tool_version "clickhouse" || {
msg_error "Aborting ClickHouse upgrade: another package depends on it"
return 1
}
else
msg_info "Setup ClickHouse $CLICKHOUSE_VERSION"
fi
@@ -5150,7 +5195,10 @@ setup_go() {
# Scenario 2: Different version or not installed
if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" != "$GO_VERSION" ]]; then
msg_info "Upgrade Go from $CURRENT_VERSION to $GO_VERSION"
remove_old_tool_version "go"
remove_old_tool_version "go" || {
msg_error "Aborting Go upgrade: another package depends on it"
return 1
}
else
msg_info "Setup Go $GO_VERSION"
fi
@@ -6753,7 +6801,10 @@ EOF
# Scenario 2b: Different version installed - clean upgrade
if [[ -n "$CURRENT_VERSION" ]] && ! version_matches_spec "$CURRENT_VERSION" "$MARIADB_VERSION"; then
msg_info "Upgrade MariaDB from $CURRENT_VERSION to $MARIADB_VERSION"
remove_old_tool_version "mariadb"
remove_old_tool_version "mariadb" || {
msg_error "Aborting MariaDB upgrade: another package depends on it"
return 1
}
fi
# Scenario 3: Fresh install or version change with specific version
@@ -7283,7 +7334,10 @@ setup_mongodb() {
# Scenario 2: Different version installed - clean upgrade
if [[ -n "$INSTALLED_VERSION" && "$INSTALLED_VERSION" != "$MONGO_VERSION" ]]; then
msg_info "Upgrade MongoDB from $INSTALLED_VERSION to $MONGO_VERSION"
remove_old_tool_version "mongodb"
remove_old_tool_version "mongodb" || {
msg_error "Aborting MongoDB upgrade: another package depends on it (e.g. an app using it)"
return 1
}
else
msg_info "Setup MongoDB $MONGO_VERSION"
fi
@@ -7473,7 +7527,10 @@ setup_mysql() {
# Scenario 2: Different version installed - clean upgrade
if [[ -n "$CURRENT_VERSION" ]] && ! version_matches_spec "$CURRENT_VERSION" "$MYSQL_VERSION"; then
msg_info "Upgrade MySQL from $CURRENT_VERSION to $MYSQL_VERSION"
remove_old_tool_version "mysql"
remove_old_tool_version "mysql" || {
msg_error "Aborting MySQL upgrade: another package depends on it"
return 1
}
else
msg_info "Setup MySQL $MYSQL_VERSION"
fi
@@ -7637,7 +7694,10 @@ setup_nodejs() {
if [[ -n "$CURRENT_NODE_VERSION" && "$CURRENT_NODE_VERSION" != "$NODE_VERSION" ]]; then
msg_info "Upgrade Node.js from $CURRENT_NODE_VERSION to $NODE_VERSION"
node_setup_ok_msg="Upgrade Node.js to $NODE_VERSION"
remove_old_tool_version "nodejs"
remove_old_tool_version "nodejs" || {
msg_error "Aborting Node.js upgrade: another package depends on it"
return 1
}
else
msg_info "Setup Node.js $NODE_VERSION"
node_setup_ok_msg="Setup Node.js $NODE_VERSION"
@@ -9334,6 +9394,8 @@ fetch_and_deploy_from_url() {
if [[ "$file_desc" =~ gzip.*compressed|gzip\ compressed\ data ]]; then
archive_type="tar"
elif [[ "$file_desc" =~ XZ\ compressed\ data ]]; then
archive_type="tar"
elif [[ "$file_desc" =~ Zip.*archive|ZIP\ archive ]]; then
archive_type="zip"
elif [[ "$file_desc" =~ Debian.*package|Debian\ binary\ package ]]; then

View File

@@ -173,7 +173,11 @@ function detect_service() {
rm -rf "$tmpdir"
return 1
fi
service=$(grep -oE '/ct/[a-zA-Z0-9._-]+\.sh' "$update_file" 2>/dev/null | head -n1 | sed 's|.*/ct/||; s|\.sh$||')
service=$(sed -n -E 's/^[[:space:]]*export[[:space:]]+UPDATE_SCRIPT_NAME=["'"'"']?([a-zA-Z0-9._-]+).*/\1/p' "$update_file" | head -n1)
[[ -z "$service" ]] && service=$(sed -n -E 's/^[[:space:]]*export[[:space:]]+SCRIPT_SLUG=["'"'"']?([a-zA-Z0-9._-]+).*/\1/p' "$update_file" | head -n1)
[[ -z "$service" ]] && service=$(grep -oE '/ct/[a-zA-Z0-9._-]+\.sh' "$update_file" 2>/dev/null | head -n1 | sed 's|.*/ct/||; s|\.sh$||')
rm -rf "$tmpdir"
}