331 Commits

Author SHA1 Message Date
Tobias
e76681ed8e Improve stale PR auto-labeling and management
Enhance stale PR management by auto-labeling PRs with no activity in the last 14 days and maintaining existing stale PR handling.
2026-03-22 13:58:26 +01:00
Tobias
87bb2a34ca Merge pull request #1603 from heinemannj/patch-1
Enhance step-ca installation and initialization process
2026-03-22 10:30:41 +01:00
github-actions[bot]
2b907821a7 Delete versitygw (ct) after migration to ProxmoxVE (#1604)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-22 08:40:58 +00:00
MickLesk
96d9835d79 refactor(nginxproxymanager): use version-agnostic sed and revert to Debian 12 2026-03-21 19:39:59 +01:00
MickLesk
bba8577237 refactor(nginxproxymanager): clean up install and update scripts
Install script:
- Merge dependency blocks into one
- Remove pre-installed ca-certificates
- Use get_latest_github_release instead of curl/grep/awk
- Re-enable systemctl enable openresty
- Remove redundant systemctl restart

CT update script:
- Bump var_version to 13 (Trixie)
- Use apt instead of apt-get (project convention)
- Add $STD to apt purge/autoremove
- Use get_latest_github_release
- Remove redundant systemctl restart after enable --now
2026-03-21 19:34:42 +01:00
MickLesk
b4a824b9a1 fix(nginxproxymanager): add missing OpenResty modules for NPM
Add --with-http_sub_module and --with-http_auth_request_module
to OpenResty configure flags. NPM needs auth_request for access
list subrequests and sub_filter for response rewriting.
2026-03-21 19:23:30 +01:00
MickLesk
bd5e20237f test 2026-03-21 19:20:00 +01:00
MickLesk
96fc169f4b fix(build): prevent error handler crash from pipefail on grep
The missing_cmd grep pipeline in the install error handler runs
under set -o pipefail. When grep finds no match (exit 1), the
entire pipeline fails and triggers the ERR trap recursively,
crashing the recovery menu. Add || true to suppress this.
2026-03-21 19:16:33 +01:00
MickLesk
74007d3f72 fix(nginxproxymanager): add missing systemctl daemon-reload before enable
Without daemon-reload, systemd doesn't know about the new
openresty.service unit file, causing enable --now to fail.
2026-03-21 19:12:04 +01:00
MickLesk
7fec6ed156 fix(nginxproxymanager): reorder update to migrate OpenResty from apt to source
- Move OpenResty apt removal + source build before environment setup
- Ensures symlinks and configs point to freshly built OpenResty
- Use simplified systemd service (Type=simple, daemon off)
- Remove duplicate OpenResty build block
2026-03-21 19:08:39 +01:00
MickLesk
a6921a33f3 fix(nginxproxymanager): simplify openresty service for LXC compatibility
- Switch from Type=forking to Type=simple with 'daemon off;'
- Remove PIDFile, ExecReload, ExecStop (systemd handles these)
- Remove PrivateTmp=true (incompatible with LXC containers)
2026-03-21 19:02:08 +01:00
MickLesk
fde17c12ed testing npm openresty 2026-03-21 18:49:47 +01:00
Joerg Heinemann
16f7904371 Enhance step-ca installation and initialization process
First change to reduce the amount of status msg_xxx blocks.

To be continued after merging and testing.
2026-03-21 14:57:03 +01:00
CanbiZ (MickLesk)
eb0a973c62 docs(netboot-xyz): fix guide — all 31 assets, 8GB disk, proper headings 2026-03-20 16:08:17 +01:00
CanbiZ (MickLesk)
0deb262d5f docs(netboot-xyz): update guide — all 31 assets, 8GB disk, fix lint errors 2026-03-20 16:05:44 +01:00
CanbiZ (MickLesk)
91950cc983 fix(netboot-xyz): download all 31 release assets, bump disk to 8GB 2026-03-20 15:23:33 +01:00
CanbiZ (MickLesk)
f0fc1aff4e fix(netboot-xyz): download all bootloaders + add /ipxe/ nginx alias to fix 404s 2026-03-20 15:20:07 +01:00
CanbiZ (MickLesk)
13a836c44d fix(netboot-xyz): rename install script to match APP name (netboot.xyz-install.sh) 2026-03-20 15:05:14 +01:00
CanbiZ (MickLesk)
7df3ff5ece testing netboot as lxc 2026-03-20 15:00:39 +01:00
CanbiZ (MickLesk)
1f3970fcf7 fix(discourse): update notes with creds path 2026-03-20 14:52:31 +01:00
CanbiZ (MickLesk)
8c3ebdd166 fix(discourse): nginx serve static assets from public/, fix JS/font 404s 2026-03-20 14:50:44 +01:00
CanbiZ (MickLesk)
8883957393 fix(discourse): create admin via rails runner, fix invalid email 2026-03-20 14:48:11 +01:00
CanbiZ (MickLesk)
a21f901a1a fix(versitygw): add colon prefix to VGW_PORT (:7070) 2026-03-20 14:32:31 +01:00
CanbiZ (MickLesk)
d2c4288395 fix(versitygw): move WebGUI prompt before msg_info spinner 2026-03-20 14:15:59 +01:00
CanbiZ (MickLesk)
9066f6511a fix(discourse): nginx reload, db:seed, sidekiq queues, skip email verification 2026-03-20 14:09:48 +01:00
CanbiZ (MickLesk)
c281d7ce68 fix(simplelogin): reload nginx after config, add SMTP note 2026-03-20 14:08:07 +01:00
CanbiZ (MickLesk)
e7f51e92d2 OOM 2026-03-20 13:59:50 +01:00
CanbiZ (MickLesk)
70914c20a2 Add optional VersityGW WebGUI support
Prompt the user during install to enable the beta VersityGW WebGUI and, if accepted, append VGW_WEBUI_PORT=:7071 and VGW_WEBUI_NO_TLS=true to /etc/versitygw.d/gateway.conf. Update the installer to report that the WebGUI will be enabled and modify the completion script to display the WebGUI URL (http://<IP>:7071) when the config contains VGW_WEBUI_PORT. Keeps existing access/key generation and default gateway port unchanged.
2026-03-20 13:58:57 +01:00
CanbiZ (MickLesk)
97b44d8a26 Switch to alembic migrations and pitchfork
Replace calls to `flask db upgrade` with `alembic upgrade head` in SimpleLogin install and update scripts so migrations are executed via Alembic in the virtualenv. For Discourse, remove in-place puma.rb sed tweaks (socket bind and stdout redirect) and update the systemd ExecStart to run `pitchfork -c config/pitchfork.conf.rb` instead of invoking puma directly, using Discourse's recommended process manager.
2026-03-20 13:57:43 +01:00
github-actions[bot]
055abcb99f Delete isponsorblocktv (ct) after migration to ProxmoxVE (#1600)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-20 12:31:09 +00:00
github-actions[bot]
b76e25910d Delete alpine-wakapi (ct) after migration to ProxmoxVE (#1599)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-20 12:24:46 +00:00
CanbiZ (MickLesk)
34250d6adf Update move-to-main-repo.yaml 2026-03-20 13:23:59 +01:00
CanbiZ (MickLesk)
7738065237 Enhance PocketBase workflow; fix installer scripts
Workflow: add push trigger for main branch on json/*.json and update the "Get JSON file for script" step to handle both workflow_dispatch and push events. The step now collects changed json/*.json files, validates each has a .slug with jq, ignores metadata/update-apps.json/versions.json, writes changed_app_jsons.txt, and sets a count output for downstream steps.

Installer & ct scripts: normalize indentation/formatting, ensure aliases.json and plugin-settings.json are initialized as {} and repos.json as [] when missing, and add missing trailing newlines. These changes improve robustness and shellcheck friendliness and make the workflow respond to direct pushes of app JSON files.
2026-03-20 13:21:50 +01:00
CanbiZ (MickLesk)
b833eb68eb Add degoog CT/install/metadata and update docs
Introduce degoog support: add ct/degoog.sh (container orchestration and update handler), install/degoog-install.sh (in-container install using Bun, deploy prebuilt release, create systemd service on port 4444) and json/degoog.json (app metadata and default resources). ct script includes update routine with backups, Bun install, and fetch_and_deploy_gh_release usage. Also update documentation: refine contribution guide (CONTRIBUTING.md) with fork/testing workflow, templates, and metadata guidance; expand misc README to reflect canonical misc/* function library responsibilities and references.
2026-03-20 12:31:43 +01:00
github-actions[bot]
cc8dd29f63 Delete teleport (ct) after migration to ProxmoxVE (#1597)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-20 08:06:53 +00:00
tremor021
4b3d9366d2 Teleport: increase sleep to 10s 2026-03-19 14:11:05 +01:00
CanbiZ (MickLesk)
0527db122b feat(bot): add version to ALLOWED_FIELDS 2026-03-19 08:47:04 +01:00
CanbiZ (MickLesk)
b689917eee fix(bot): handle PocketBase returning JSON fields as pre-parsed objects 2026-03-18 19:39:44 +01:00
CanbiZ (MickLesk)
8bb2f28b48 debug(bot): show raw field values in method list when count=0 2026-03-18 19:36:51 +01:00
CanbiZ (MickLesk)
71c02e052b fix(bot): fallback to expanded install_methods relation when install_methods_json is empty 2026-03-18 19:05:32 +01:00
CanbiZ (MickLesk)
105dceb42e refactor(bot): use notes_json and install_methods_json directly, remove extra table dependencies 2026-03-18 18:59:47 +01:00
CanbiZ (MickLesk)
8ba7b55cd5 Merge pull request #1591 from community-scripts/feature/pocketbase-bot
Pocketbase bot
2026-03-18 18:44:58 +01:00
CanbiZ (MickLesk)
6a7da073f8 docs: add PocketBase Bot command reference 2026-03-18 18:43:11 +01:00
CanbiZ (MickLesk)
366626be9c feat(pocketbase-bot): add method subcommand + set command for HTML/multiline values 2026-03-18 17:26:43 +01:00
CanbiZ (MickLesk)
599aa97a92 feat(pocketbase-bot): add note add/edit/remove/list subcommands 2026-03-18 17:24:10 +01:00
CanbiZ (MickLesk)
3981500e65 fix(pocketbase-bot): align ALLOWED_FIELDS with actual PocketBase schema 2026-03-18 17:13:10 +01:00
CanbiZ (MickLesk)
b96c20db88 feat(workflows): add PocketBase Bot for contributor commands via issue comments 2026-03-18 17:05:12 +01:00
CanbiZ (MickLesk)
b365a78807 fix(workflows): last_update_commit uses script files (ct/vm/install) not JSON 2026-03-18 16:40:09 +01:00
CanbiZ (MickLesk)
f19a59e4f1 optizmize json 2026-03-18 16:38:23 +01:00
CanbiZ (MickLesk)
47b5bd40f8 feat(workflows): enrich PocketBase payload with notes_json, install_methods_json, execute_in, github, project_url, last_update_commit 2026-03-18 16:37:55 +01:00
CanbiZ (MickLesk)
170dce61d2 Update push_json_to_pocketbase.yml 2026-03-18 16:22:00 +01:00
CanbiZ (MickLesk)
85de978ea4 fix(workflows): set script_updated to current date on push to PocketBase 2026-03-18 16:21:44 +01:00
CanbiZ (MickLesk)
e275cafc13 test 2026-03-18 16:19:58 +01:00
CanbiZ (MickLesk)
0762e41e83 fix(workflows): follow HTTP redirects in PocketBase request function 2026-03-18 16:18:23 +01:00
CanbiZ (MickLesk)
c4670a25c2 fix(librechat): add ENDPOINTS to .env so AI providers appear in UI 2026-03-18 15:42:24 +01:00
tremor021
e6e3c47beb Correct the admin log 2026-03-18 15:42:11 +01:00
tremor021
19d7d58a64 Teleport: remove silent 2026-03-18 15:11:35 +01:00
CanbiZ (MickLesk)
7ab160ff75 gitea sync 2026-03-18 14:58:47 +01:00
tremor021
8a5acacd52 Teleport: give more time for service to start up 2026-03-18 14:47:40 +01:00
CanbiZ (MickLesk)
aaaf18de91 switch urls back to github (due slow gitea syncs) 2026-03-18 14:47:29 +01:00
CanbiZ (MickLesk)
67de69f8bb docs(librechat): add Ollama local embeddings tip to notes 2026-03-18 14:45:13 +01:00
CanbiZ (MickLesk)
67e0db6d48 fix(librechat): use uv+Python 3.12 with pip resolver for RAG API deps 2026-03-18 14:40:43 +01:00
CanbiZ (MickLesk)
11055a22fb fix(librechat): use python3-venv+pip instead of uv for RAG API to handle numpy dependency conflict 2026-03-18 14:38:43 +01:00
CanbiZ (MickLesk)
b4b8f1c118 feat: Add LibreChat LXC script with MongoDB, Meilisearch, PostgreSQL/pgvector, and RAG API 2026-03-18 14:23:47 +01:00
tremor021
b8f490d8c8 Teleport: increase resources 2026-03-18 14:22:37 +01:00
CanbiZ (MickLesk)
b3e9814d79 add rag service 2026-03-18 13:53:17 +01:00
tremor021
7393d85f74 Teleport: update install script 2026-03-18 13:52:08 +01:00
tremor021
549789a6a7 Teleport: update tags 2026-03-18 13:48:28 +01:00
CanbiZ (MickLesk)
fbd9cfa90c remove alpine ntfy from ved 2026-03-18 13:46:33 +01:00
CanbiZ (MickLesk)
be57260532 Merge branch 'main' of https://github.com/community-scripts/ProxmoxVED 2026-03-18 13:44:13 +01:00
CanbiZ (MickLesk)
d694185e17 add more envs and cleanup and meillisearch 2026-03-18 13:44:06 +01:00
tremor021
33185f12c1 Teleport: update port in json 2026-03-18 13:44:02 +01:00
tremor021
ec12d0f31a add Teleport script 2026-03-18 13:39:51 +01:00
CanbiZ (MickLesk)
fdd9a22992 librechat 2026-03-18 12:56:51 +01:00
CanbiZ (MickLesk)
88f4f966d2 Merge pull request #1587 from community-scripts/MickLesk-patch-3-1
update tools.func from upstream
2026-03-18 12:36:57 +01:00
CanbiZ (MickLesk)
4b0fcf7d9d Update print statement from 'Hello' to 'Goodbye' 2026-03-18 12:36:33 +01:00
github-actions[bot]
66fd840baa Delete split-pro (ct) after migration to ProxmoxVE (#1586)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-18 07:44:11 +00:00
CanbiZ (MickLesk)
6b58bd1bf9 test 2026-03-16 18:46:39 +01:00
CanbiZ (MickLesk)
f7a42823a4 Update discourse-install.sh 2026-03-16 18:25:17 +01:00
CanbiZ (MickLesk)
11c34baf7a Update simplelogin-install.sh 2026-03-16 18:12:32 +01:00
CanbiZ (MickLesk)
1f2d8159d0 Update simplelogin-install.sh 2026-03-16 18:00:50 +01:00
CanbiZ (MickLesk)
d382697368 Update discourse-install.sh 2026-03-16 17:53:52 +01:00
CanbiZ (MickLesk)
817b0ea517 Split Discourse services; update SimpleLogin setup
Add DISCOURSE_PUMA_BIND to Discourse env and switch the discourse.service to load EnvironmentFile=/opt/discourse/.env. Create a separate systemd unit for Sidekiq (discourse-sidekiq.service), enable both services, and adjust messaging to "Services". In simplelogin install: remove git from apt list, bump PostgreSQL setup from 16 to 17, and export FLASK_APP=server before running migrations/initialization so Flask commands run with the correct app context.
2026-03-16 17:50:37 +01:00
CanbiZ (MickLesk)
9413782993 Merge branch 'main' of https://github.com/community-scripts/ProxmoxVED 2026-03-16 17:50:32 +01:00
github-actions[bot]
f727d7979c Delete gluetun (ct) after migration to ProxmoxVE (#1583)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-16 16:45:57 +00:00
CanbiZ (MickLesk)
6fd1b2e96d Enable vector and load .env in installers
Discourse install: add PG_DB_EXTENSIONS="vector" to setup_postgresql_db and remove the separate CREATE EXTENSION psql call; also remove curl and git from the apt install list and drop the automatic admin bootstrap messaging. SimpleLogin install: source /opt/simplelogin/.env before running migrations and add EnvironmentFile=/opt/simplelogin/.env to the systemd unit files (gunicorn, email_handler, job_runner) so services inherit environment variables.
2026-03-16 17:40:49 +01:00
github-actions[bot]
b3ca9efbed Delete anytype-server (ct) after migration to ProxmoxVE (#1582)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-16 16:34:07 +00:00
CanbiZ (MickLesk)
faf5c6d7ff Update Postgres version and SimpleLogin mail env
Bump PostgreSQL target from 16 to 17 in discourse-install.sh and make pg_hba.conf lookup dynamic (uses find) instead of a hardcoded path, ensuring compatibility with systems where the data directory path differs. Also add EMAIL_SERVERS_WITH_PRIORITY and POSTFIX_SERVER entries to the SimpleLogin .env to configure local mail delivery (set to localhost).
2026-03-16 17:27:09 +01:00
CanbiZ (MickLesk)
0e1759dc7c Update gluetun-install.sh 2026-03-16 17:24:03 +01:00
CanbiZ (MickLesk)
9d7f643bd4 sdf 2026-03-16 17:14:50 +01:00
CanbiZ (MickLesk)
34d1c7693d fixes 2026-03-16 17:12:33 +01:00
CanbiZ (MickLesk)
b056d30f9d fixes pg_cron 2026-03-16 16:57:55 +01:00
CanbiZ (MickLesk)
af6481368c Update isponsorblocktv-install.sh 2026-03-16 16:54:18 +01:00
CanbiZ (MickLesk)
7d411e30d7 fixes 2026-03-16 16:50:49 +01:00
github-actions[bot]
a22f30f864 Delete yamtrack (ct) after migration to ProxmoxVE (#1581)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-15 22:12:39 +00:00
github-actions[bot]
9fe0e94025 Delete test (ct) after migration to ProxmoxVE (#1560)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-12 14:22:14 +00:00
Michel Roegl-Brunner
3a7a195fdc chage worflow 2026-03-12 15:17:15 +01:00
Michel Roegl-Brunner
69fe411bb2 test case 2026-03-12 15:08:15 +01:00
Michel Roegl-Brunner
27f39963ec Change workflow to no longer include jsons 2026-03-12 15:06:00 +01:00
tremor021
a4492fd26d Wakapi add json 2026-03-12 14:35:47 +01:00
tremor021
fd2162d527 Wakapi updates 2026-03-12 14:30:13 +01:00
Michel Roegl-Brunner
5bf7c84f29 remove/change workflows 2026-03-12 14:28:30 +01:00
CanbiZ (MickLesk)
b8c147ebfc fixes 2026-03-12 14:27:06 +01:00
tremor021
d742795ecd Wakapi updates 2026-03-12 14:24:57 +01:00
CanbiZ (MickLesk)
c87e326387 refactor: move json/ to top-level, remove frontend/, update workflows
- Move frontend/public/json/ to json/ (top-level)
- Update all workflow path references to json/
- Delete frontend-cicd.yml workflow
- Delete frontend/ directory entirely
- Clean up .gitattributes (remove frontend entries)
2026-03-12 14:11:07 +01:00
CanbiZ (MickLesk)
aacbe238ba Update cron-update-lxcs.sh 2026-03-12 14:06:07 +01:00
tremor021
f8c8cffda1 Wakapi fixes 2026-03-12 13:57:01 +01:00
tremor021
c53b4e1d32 add Wakapi script 2026-03-12 13:38:32 +01:00
CanbiZ (MickLesk)
1cbc30e578 Switch repo URLs to raw.githubusercontent.com
Update script and license links to use GitHub raw URLs. Replace git.community-scripts.org references with https://raw.githubusercontent.com/... for script fetching and https://github.com/... for the LICENSE link in tools/pve/cron-update-lxcs.sh and tools/pve/update-lxcs-cron.sh so the curl examples and REPO_URL point to GitHub-hosted raw content.
2026-03-12 11:35:21 +01:00
CanbiZ (MickLesk)
73b8a02a8c Update update-lxcs-cron.sh 2026-03-12 11:31:59 +01:00
CanbiZ (MickLesk)
a6e0de632f cron 2026-03-12 11:27:07 +01:00
CanbiZ (MickLesk)
ec875e6e62 Run app install live during image build
Change VM app deployer to run CT install scripts during image customization (virt-customize --run) instead of via a first-boot systemd service. Updated docs to reflect live installation, new update workflow (curl the ct/<app>.sh inside the VM), and new troubleshooting/reinstall guidance. misc/vm-app.func now injects function libs, runs a temporary wrapper inside virt-customize (with logging and error handling), removes the first-boot service and update wrapper injection, and updates summary/status messages to mark apps as pre-installed.
2026-03-12 09:43:43 +01:00
CanbiZ (MickLesk)
be8e4483fc Update vm-app.func 2026-03-12 09:22:12 +01:00
CanbiZ (MickLesk)
37e53c19ec force gitea sync 2026-03-12 09:18:29 +01:00
CanbiZ (MickLesk)
19cc18037c vm app-deployer 2026-03-12 09:06:41 +01:00
CanbiZ (MickLesk)
e581096d53 Merge pull request #1557 from dereckhall/fix/unifi-os-server-vm
Fix and improve UniFi OS Server VM script
2026-03-12 07:24:52 +01:00
Dereck
7a211fd407 Address third CodeRabbit review feedback
- Remove unused send_line_to_vm function (replaced by virt-customize)
- Quote $VMID and add guard in cleanup_vmid
- Guard cleanup() against unset TEMP_DIR and quote variable
2026-03-12 00:54:39 -04:00
Dereck
1db68f32b5 Address second CodeRabbit review feedback
- Quote $VMID in error_handler for robustness
- Reduce port 11443 wait loop from 15min to 5min and update message
2026-03-12 00:45:49 -04:00
Dereck
3da60ba0a2 Address CodeRabbit review feedback
- Remove unused CLOUDINIT_PASSWORD variable
- Separate local declaration from assignment in get_image_url()
- Add retry loop for apt-get install (matches apt-get update pattern)
- Fix timeout message to match actual loop duration (~5-6 min)
2026-03-12 00:30:01 -04:00
Dereck
afa4e4ef07 Fix and improve UniFi OS Server VM script
Bug fixes:
- Add ~20 missing fi statements throughout advanced_settings(), check_root(),
  arch_check(), ssh_check(), select_os(), start_script(), etc.
- Fix pve_check() missing elif/else/fi structure
- Fix DISK_SIZE unbound variable, initialized before machine type dialog
- Fix error_handler() with ${VMID:-} guard to prevent unbound variable error

Architecture improvement:
- Migrate from send_line_to_vm serial console approach to virt-customize with
  a first-boot systemd service, consistent with other VM scripts
- First-boot service handles: clock sync (NTP + HTTP fallback), package
  installation, swap setup, and UniFi OS installer execution

New features:
- Root password prompt with confirmation
- SSH public key support
- SSH enabled by default
- Cloud-init password override with user-set password
- Port 11443 readiness check after VM boot
- Elapsed time counter during wait loops
2026-03-12 00:22:10 -04:00
Michel Roegl-Brunner
91572c9c8c Test workflow 2026-03-11 15:32:00 +01:00
Michel Roegl-Brunner
c9a2bf916c Test workflow 2026-03-11 15:31:10 +01:00
Michel Roegl-Brunner
262a3a72f4 Test workflow 2026-03-11 15:29:54 +01:00
Michel Roegl-Brunner
2a79253118 Test 2026-03-11 14:12:59 +01:00
Michel Roegl-Brunner
5a273d91ed Delete frontend/public/json/test.json 2026-03-11 14:09:20 +01:00
Michel Roegl-Brunner
36e5863726 test workflow 2026-03-11 14:04:59 +01:00
Michel Roegl-Brunner
909f37ab7a Append workflow 2026-03-11 14:04:26 +01:00
CanbiZ (MickLesk)
66013146ab Update build target, add /gluetun link & env
Switch the Go build invocation to target the cmd/gluetun package directory (./cmd/gluetun/) in both ct/gluetun.sh and install/gluetun-install.sh, and ensure modules are downloaded during install (go mod download). In the installer, create /opt/gluetun-data and add a symlink /gluetun -> /opt/gluetun-data, update STORAGE/PUBLICIP/PORT file paths to use /gluetun, add PPROF_ENABLED=no to the default .env, and add UnsetEnvironment=USER to the systemd unit to avoid inheriting the USER environment. These changes standardize build behavior and relocate runtime data to a consistent /gluetun path.
2026-03-11 11:44:26 +01:00
Tobias
0c2dccba2d Update pull_request_template.md 2026-03-11 10:00:28 +01:00
Michel Roegl-Brunner
aadeab7568 Add GitHub Pages redirect workflow 2026-03-11 08:41:08 +01:00
Michel Roegl-Brunner
0f2eaa664c Merge pull request #1516 from steveonjava/submit/protonmail-bridge-proxmoxved
feat: add Proton Mail Bridge
2026-03-11 08:30:02 +01:00
Tobias
69be85f81b Update unmet-pr-close.yml 2026-03-10 22:14:45 +01:00
Tobias
597cb21870 Create unmet-pr-close.yml 2026-03-10 22:12:37 +01:00
MickLesk
c18000e1fa switch route 2026-03-10 19:01:49 +01:00
MickLesk
ad8a5ccd60 harmonize package-lock shit 2026-03-10 18:57:46 +01:00
MickLesk
8d92578756 add gluetun 2026-03-10 18:48:35 +01:00
MickLesk
6c2aafab12 fix validation 2026-03-10 18:47:02 +01:00
MickLesk
8c3f67536b add versitygw 2026-03-10 18:35:57 +01:00
Michel Roegl-Brunner
195c064c71 Add workflow to update script timestamps on .sh changes
This workflow updates the timestamps of scripts in PocketBase whenever .sh files are changed in specified directories.
2026-03-10 15:49:54 +01:00
Michel Roegl-Brunner
5aa9cfe213 Install git and GitHub CLI dependencies
Added installation of git and GitHub CLI as dependencies.
2026-03-10 15:43:26 +01:00
Tobias
c65429f2f8 fix: correcting file write 2026-03-10 10:06:10 +01:00
Stephen Chin
fc6cf2b11e Fixed heredoc syntax 2026-03-10 01:40:55 -07:00
vhsdream
c6cf0d92c2 add git 2026-03-09 15:18:26 -04:00
vhsdream
b73bb2cdb0 add build-essential 2026-03-09 15:13:13 -04:00
vhsdream
237897342c fix dep 2026-03-09 14:59:45 -04:00
vhsdream
6c3d5797dd Add Invidious 2026-03-09 14:44:31 -04:00
Stephen Chin
320886faad Fixed EOFs to match style guidelines 2026-03-09 02:03:07 -07:00
Stephen Chin
e488a16077 Apply suggestion from @CrazyWolf13
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-09 02:01:01 -07:00
Stephen Chin
5d17a0baa6 Removed comment 2026-03-09 02:00:16 -07:00
Stephen Chin
8aee8f0af7 Fixes for review comments. 2026-03-09 01:08:53 -07:00
Stephen Chin
f7efc94f34 Improved display of message 2026-03-09 00:43:38 -07:00
Stephen Chin
a7f7d961fb Added missing .socket postfixes 2026-03-08 23:09:07 -07:00
Stephen Chin
5b496a28d2 Removed extraneous .service postfixes and improved messages. 2026-03-08 23:08:32 -07:00
Stephen Chin
fb687c5d22 Use protonmailbridge-configure for both initialization and later configuration. 2026-03-08 18:30:30 -07:00
Stephen Chin
46e0107392 Use protonmailbridge-configure for both initialization and later configuration. 2026-03-08 18:29:29 -07:00
Stephen Chin
70344e5f8f Use protonmailbridge-configure for both initialization and later configuration. 2026-03-08 18:28:35 -07:00
vhsdream
3d7322bf72 OxiCloud: add RUSTFLAGS 2026-03-08 20:59:24 -04:00
Stephen Chin
0bed845d6d Fixed the update script to leave services in the same state they were before it was called. 2026-03-08 17:36:45 -07:00
Stephen Chin
54ba42afce Converted to heredoc style 2026-03-08 15:47:41 -07:00
Stephen Chin
bed6361769 Updated the end of install messages to be more consistent. 2026-03-08 15:21:45 -07:00
Stephen Chin
1e32c49bf0 Added exit code value 2026-03-08 15:02:58 -07:00
Stephen Chin
7df0d109e7 Changed ram to 1024 to match the json 2026-03-08 15:02:24 -07:00
Stephen Chin
70a40bb958 Changed to use the github raw content instead of gitea server 2026-03-08 15:00:24 -07:00
Stephen Chin
11c7f88a3c Apply suggestions from code review
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-08 14:43:39 -07:00
Stephen Chin
172a72c9ef Apply suggestion from @CrazyWolf13
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-08 14:42:32 -07:00
Stephen Chin
42ee142ebf Apply suggestion from @CrazyWolf13
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-08 14:42:19 -07:00
Stephen Chin
69596eb7f3 Removed check for user already existing 2026-03-08 14:41:13 -07:00
Stephen Chin
4931c39349 Apply suggestion from @CrazyWolf13
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-08 14:39:58 -07:00
Stephen Chin
7977f5589d Added GitHuib username in parenthesis 2026-03-08 14:04:54 -07:00
Stephen Chin
546ab51547 Updated memory requirements to 1GB 2026-03-08 14:03:59 -07:00
Stephen Chin
daecf37e3b Added GitHub username in parenthesis 2026-03-08 14:01:50 -07:00
Stephen Chin
f87a90b959 Remove extra message
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-08 13:59:14 -07:00
Stephen Chin
86af319d32 Remove types on service stop
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-08 13:58:28 -07:00
Stephen Chin
63622ece38 Removed types on service start
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-08 13:57:07 -07:00
Stephen Chin
8e0f6fcb21 Removed extra messages.
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-08 13:55:02 -07:00
Stephen Chin
269060341b Switched back to ${APP}
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-08 13:53:18 -07:00
Stephen Chin
bfdb602826 Removed description
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-08 13:52:42 -07:00
vhsdream
7193f4802e OxiCloud: properly export DB URL, fix BASE_URL sed 2026-03-08 12:09:53 -04:00
Stephen Chin
6e26f7d4c8 Update protonmail-bridge-install.sh 2026-03-07 21:40:28 -08:00
Stephen Chin
8bb917572c Update protonmail-bridge.sh 2026-03-07 21:39:01 -08:00
github-actions[bot]
5d3900e3b1 Delete immichframe (ct) after migration to ProxmoxVE (#1546)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-07 22:47:00 +00:00
Stephen Chin
8293bcaa02 Update protonmail-bridge-install.sh
Comments removed
2026-03-07 14:43:40 -08:00
Stephen Chin
c71157316b Changed fetch location 2026-03-07 14:42:47 -08:00
Stephen Chin
c5d10eaaaf Removed section headers 2026-03-07 14:39:53 -08:00
Stephen Chin
f1300e25d7 Update ct/protonmail-bridge.sh
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-07 14:36:33 -08:00
Stephen Chin
2ce43a7e0f Update install/protonmail-bridge-install.sh
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-07 14:35:58 -08:00
Stephen Chin
41792306a2 Update install/protonmail-bridge-install.sh
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-07 14:35:33 -08:00
Stephen Chin
a3a0f6df56 Update install/protonmail-bridge-install.sh
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-07 14:35:03 -08:00
Stephen Chin
575c542833 Update ct/protonmail-bridge.sh
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-07 14:34:54 -08:00
Stephen Chin
fb3186640c Update ct/protonmail-bridge.sh
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-07 14:34:07 -08:00
vhsdream
77e85aa26d remove oxicloud user 2026-03-06 17:59:19 -05:00
vhsdream
bfefe51761 Try to fix permission issues 2026-03-06 17:51:35 -05:00
vhsdream
c0b7c6c2ff sediting 2026-03-06 14:18:07 -05:00
vhsdream
db6c5d2b4f more sed changes 2026-03-06 14:05:45 -05:00
vhsdream
05426a7735 fix sed redux 2026-03-06 12:52:41 -05:00
vhsdream
74da15f98f fix sed 2026-03-06 11:47:23 -05:00
vhsdream
f5a9954484 delete env file 2026-03-06 11:13:17 -05:00
vhsdream
7399402e30 Add OxiCloud 2026-03-06 10:57:09 -05:00
CanbiZ (MickLesk)
2f5560c975 move jsons 2026-03-06 11:37:20 +01:00
Sam Heinz
34f0284c09 arm64 scripts test
Adguard, Bazarr, Homeassistant, jellyfin, pihole, rdtclient, vaultwarden are working
kima-hub is unported
bentopdf is untested
lubelogger is broken
2026-03-06 20:35:01 +10:00
Michel Roegl-Brunner
dfe47a1ece Create arm-test.sh 2026-03-06 11:13:23 +01:00
CanbiZ (MickLesk)
2c739da9e1 Merge branch 'main' of https://github.com/community-scripts/ProxmoxVED 2026-03-06 09:56:54 +01:00
CanbiZ (MickLesk)
7abef0d58c arm testing 2026-03-06 09:56:52 +01:00
Michel Roegl-Brunner
8f7b5d211c Change runner from ubuntu-latest to self-hosted 2026-03-06 09:15:26 +01:00
Michel Roegl-Brunner
13a5761855 Change runner from ubuntu-latest to self-hosted 2026-03-06 09:15:02 +01:00
CanbiZ (MickLesk)
e8953ca09f various fixes 2026-03-06 09:13:00 +01:00
CanbiZ (MickLesk)
dfdca249ad Merge pull request #1536 from BillyOutlast/LocalAGI
feat: add LocalAGI LXC helper script
2026-03-06 09:03:32 +01:00
John Doe
3b0f9ea35d fix: simplify default value for var_tags in localagi.sh 2026-03-05 17:04:22 -05:00
John Doe
7fe554e2be fix: update LocalAGI service management in update_script function 2026-03-05 15:40:56 -05:00
John Doe
d07d8f1054 fix: add informational messages for systemd service creation and management in localagi-install.sh 2026-03-05 15:35:30 -05:00
John Doe
3a1de5a78b fix: remove unused environment variables from LocalAGI configuration in localagi-install.sh 2026-03-05 15:33:29 -05:00
John Doe
5048507159 fix: remove error handling for LocalAGI build process in localagi-install.sh 2026-03-05 15:32:44 -05:00
John Doe
22fe50ee64 fix: add informational messages for fetching and building LocalAGI in localagi-install.sh 2026-03-05 15:31:19 -05:00
John Doe
c89dcca71a fix: add informational messages for dependency installation in localagi-install.sh 2026-03-05 15:29:23 -05:00
John Doe
8a1a4f8b9b fix: enhance Bun installation process with informational messages in localagi-install.sh 2026-03-05 15:28:54 -05:00
John Doe
40a072f787 fix: add informational messages for starting LocalAGI service in update_script function 2026-03-05 15:27:37 -05:00
John Doe
a9db3ba2e0 fix: add success message after updating LocalAGI in update_script function 2026-03-05 15:26:39 -05:00
John Doe
c64024613b fix: remove error message and exit on build failure in update_script function 2026-03-05 15:26:04 -05:00
John Doe
420dee4678 fix: improve update_script function by enhancing structure and readability 2026-03-05 15:24:13 -05:00
John Doe
efb6329952 fix: streamline update_script function by consolidating service stop and backup logic 2026-03-05 15:22:16 -05:00
John Doe
aeb49678d8 fix: add informational messages for stopping LocalAGI service in update_script function 2026-03-05 15:19:41 -05:00
John Doe
b64645a4f5 fix: refactor update_script function to improve readability by separating commands onto individual lines 2026-03-05 15:16:24 -05:00
John Doe
c0de2c9242 fix: enhance update_script function with additional informational messages during backup and restore processes 2026-03-05 15:14:06 -05:00
John Doe
dd1dd63a19 fix: update backup file path in update_script function to use /tmp directory 2026-03-05 15:12:00 -05:00
John Doe
5d391c333f Merge branch 'LocalAGI' of https://github.com/BillyOutlast/ProxmoxVED into LocalAGI 2026-03-05 15:09:21 -05:00
John Doe
23eb101dca fix: streamline update_script function by removing unnecessary directory change and cleanup steps 2026-03-05 15:09:20 -05:00
BillyOutlast
5d9a24f8f3 Merge branch 'community-scripts:main' into LocalAGI 2026-03-05 13:54:49 -05:00
John Doe
268d260fdc fix: simplify localagi-install.sh by removing redundant messages and streamlining installation steps 2026-03-05 13:37:58 -05:00
John Doe
33ba83a416 fix: streamline update_script function by removing redundant messages and backup logic 2026-03-05 13:36:48 -05:00
CanbiZ (MickLesk)
0fa6e172cf - 2026-03-05 16:49:25 +01:00
CanbiZ (MickLesk)
ab88156e2e Add NOT_SECURED and newrelic stub
Set NOT_SECURED=true in postiz install script for local/non-secured setups. In simplelogin install, detect the venv site-packages path and create a minimal newrelic package stub (newrelic/__init__.py and newrelic/agent.py) with no-op record_custom_event and initialize functions to avoid import errors when New Relic is not present.
2026-03-05 16:31:07 +01:00
github-actions[bot]
04dea4d2aa Delete ddclient (ct) after migration to ProxmoxVE (#1540)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 14:59:19 +00:00
github-actions[bot]
11b5a30ff8 Delete netbird (ct) after migration to ProxmoxVE (#1539)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 14:58:43 +00:00
CanbiZ (MickLesk)
cb1e2728e9 some fixes 2026-03-05 15:14:42 +01:00
CanbiZ (MickLesk)
a9a053720e cleanup 2026-03-05 14:40:44 +01:00
github-actions[bot]
f31c7e1bf8 Delete papra (ct) after migration to ProxmoxVE (#1537)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-05 12:50:59 +00:00
CanbiZ (MickLesk)
14396ea2a3 fixes 2026-03-05 09:27:40 +01:00
John Doe
a82d63cbd3 fix: replace restart with enable for LocalAGI service startup 2026-03-04 22:16:31 -05:00
John Doe
6ac2534aff fix: reload systemd daemon before restarting LocalAGI service 2026-03-04 22:16:07 -05:00
John Doe
76efff96bc fix: remove outdated service information from localagi.json 2026-03-04 22:13:55 -05:00
John Doe
5354ce8b04 fix: improve environment backup and restore process in update_script function 2026-03-04 22:13:04 -05:00
John Doe
a0282db2dd fix: suppress output during Bun installation for cleaner logs 2026-03-04 21:59:51 -05:00
John Doe
6f84e271ab fix: add EnvironmentFile directive to LocalAGI service 2026-03-04 21:59:18 -05:00
John Doe
57b20c7025 fix: remove installation checks from update_script function 2026-03-04 21:54:02 -05:00
John Doe
be5ed7d43f fix: remove version recording for installed LocalAGI 2026-03-04 21:53:26 -05:00
John Doe
3ec7fb917e fix: update Bun installation command to ensure proper execution 2026-03-04 21:49:02 -05:00
John Doe
21f82e39bb fix: separate Bun installation command for better error handling 2026-03-04 21:41:15 -05:00
John Doe
2352877bae fix: correct syntax error in Bun installation command 2026-03-04 21:37:30 -05:00
John Doe
6a721f0b67 fix: update script source URL to use community-scripts repository 2026-03-04 21:25:31 -05:00
John Doe
c42df79542 fix: simplify Bun installation process by removing conditional checks and fallback to npm 2026-03-04 21:17:55 -05:00
John Doe
4d4d5ae751 fix: streamline LocalAGI service creation by removing unnecessary options and verification step 2026-03-04 21:15:57 -05:00
John Doe
8b441033ba fix: ensure proper command execution during LocalAGI source build process 2026-03-04 21:13:25 -05:00
John Doe
0ce45197f6 fix: improve Bun installation process and ensure proper command execution 2026-03-04 21:11:08 -05:00
John Doe
75578ab173 fix: remove unused health check function from localagi.sh 2026-03-04 21:08:20 -05:00
John Doe
50402cec02 fix: update source URL for build functions in localagi.sh 2026-03-04 21:01:01 -05:00
John Doe
9a74d59517 fix: simplify build process in localagi-install.sh by removing subshell 2026-03-04 20:59:54 -05:00
John Doe
7ece196cff fix: refactor LocalAGI service configuration to use systemd drop-in override 2026-03-04 20:59:14 -05:00
John Doe
8a3d6f3a2b fix: update source URL and improve Bun installation in LocalAGI scripts 2026-03-04 20:58:03 -05:00
John Doe
b844eab504 feat: enhance LocalAGI installation and update process with version checks and improved Bun installation 2026-03-04 20:50:35 -05:00
John Doe
3bbc5a933b fix: update source URL for build functions in localagi.sh 2026-03-04 20:45:55 -05:00
John Doe
05ea89e3d0 feat: add health check and release tag recording for LocalAGI installation and updates 2026-03-04 20:45:04 -05:00
John Doe
a6f13f3e30 feat: implement systemd drop-in override for LocalAGI service hardening 2026-03-04 20:43:45 -05:00
John Doe
92e3192cb7 feat: add user creation and systemd unit hardening for LocalAGI installation 2026-03-04 20:41:55 -05:00
John Doe
d0803f96d8 feat: enhance LocalAGI installation with user creation and service hardening 2026-03-04 20:41:07 -05:00
BillyOutlast
ff80094629 Merge branch 'community-scripts:main' into LocalAGI 2026-03-04 17:32:55 -05:00
John Doe
f9eea806dd fix: simplify LocalAGI build process by removing error handling 2026-03-04 15:53:30 -05:00
John Doe
a5c85d465c fix: remove service recovery logic from LocalAGI installation script 2026-03-04 15:52:02 -05:00
John Doe
5b865bba63 fix: remove backend mode configuration from LocalAGI installation script 2026-03-04 15:50:38 -05:00
John Doe
8252698a45 Merge branch 'LocalAGI' of https://github.com/BillyOutlast/ProxmoxVED into LocalAGI 2026-03-04 15:48:13 -05:00
John Doe
fb6a07611b fix: simplify dependency installation by removing unnecessary packages in localagi-install.sh 2026-03-04 15:48:12 -05:00
BillyOutlast
99190f8fa6 Update install/localagi-install.sh
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-03-04 15:48:06 -05:00
tremor021
a9720a1006 CaddyManager: update ct script 2026-03-04 21:45:44 +01:00
John Doe
99b1a773dc fix: remove cleanup function and related logic for LocalAGI service recovery in localagi.sh 2026-03-04 15:40:13 -05:00
tremor021
b9a7425ff2 CaddyManager: update ct script 2026-03-04 21:31:59 +01:00
tremor021
c01caf7a1a CaddyManager: update ct script 2026-03-04 21:21:39 +01:00
tremor021
57150c29de CaddyManager: update ct script 2026-03-04 21:08:19 +01:00
tremor021
ff04bb45a9 CaddyManager: update ct script 2026-03-04 21:04:49 +01:00
John Doe
87cb94c8ca fix: update URL output format in localagi.sh to include port number 2026-03-04 12:29:44 -05:00
John Doe
975f5bcbbe fix: remove dynamic COMMUNITY_SCRIPTS_URL assignment in localagi.sh 2026-03-04 12:27:25 -05:00
John Doe
00db7c9fcf fix: update COMMUNITY_SCRIPTS_URL assignment for dynamic sourcing in localagi.sh 2026-03-04 12:24:55 -05:00
John Doe
d15ef86fab fix: remove curl debug logging function and related variable in localagi.sh 2026-03-04 12:23:23 -05:00
John Doe
13aab6df05 fix: add curl function with debug logging for error handling in localagi.sh 2026-03-04 12:22:48 -05:00
John Doe
45fd4d2d98 fix: remove dynamic COMMUNITY_SCRIPTS_URL assignment and header creation logic in localagi.sh 2026-03-04 12:17:58 -05:00
John Doe
eb95857830 fix: update COMMUNITY_SCRIPTS_URL assignment in localagi.sh 2026-03-04 12:15:50 -05:00
John Doe
c4019eeeb5 fix: add header creation logic for LocalAGI setup 2026-03-04 12:13:40 -05:00
John Doe
ebdb4db5e5 fix: enhance environment backup validation during LocalAGI updates 2026-03-04 10:45:58 -05:00
John Doe
b2fd9b23b7 fix: implement recovery mechanism for LocalAGI service during installation 2026-03-04 10:44:10 -05:00
John Doe
2797550b7e fix: implement cleanup function for LocalAGI service recovery during updates 2026-03-04 10:43:50 -05:00
John Doe
c379261168 fix: update author information in localagi.sh and localagi-install.sh 2026-03-04 10:42:01 -05:00
John Doe
8db69a2dd7 fix: add missing URL output for LocalAGI setup completion 2026-03-04 10:41:02 -05:00
John Doe
2e7e6507f6 refactor: remove redundant IP address retrieval logic from localagi.sh 2026-03-04 10:38:12 -05:00
John Doe
90fc8fb1c7 refactor: simplify localagi-install.sh by removing GO_VERSION variable from setup_go 2026-03-04 10:30:43 -05:00
John Doe
dc7d9fcb82 refactor: update log message for backend mode configuration in update_script function 2026-03-04 10:24:37 -05:00
John Doe
521c74d2ba refactor: simplify localagi.sh by removing redundant variables and streamlining update_script function 2026-03-04 10:16:45 -05:00
John Doe
6261ee8c34 refactor: streamline localagi-install.sh by removing redundant comments and simplifying build process 2026-03-04 10:10:05 -05:00
John Doe
86d22a060a refactor: simplify update_script function by removing redundant comments and streamlining logic 2026-03-04 10:08:45 -05:00
John Doe
610d12be9c refactor: streamline LocalAGI build process in update_script function 2026-03-04 10:06:53 -05:00
John Doe
fd820b026b refactor: remove set_env_var function and streamline LOCALAGI_LLM_API_URL migration logic 2026-03-04 10:05:58 -05:00
BillyOutlast
931af95855 Update install/localagi-install.sh
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-03-04 10:03:30 -05:00
BillyOutlast
2055148dac Update ct/localagi.sh
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-03-04 10:02:59 -05:00
John Doe
614a0c0089 fix: ensure update_script exits with error code on failure 2026-03-04 10:02:22 -05:00
tremor021
2afbe78348 Add fetch_and_deploy_gl_release 2026-03-04 12:34:52 +01:00
Michel Roegl-Brunner
1ce31bd622 add github actions runner 2026-03-04 10:21:22 +01:00
Michel Roegl-Brunner
14437d9482 add github actions runner 2026-03-04 10:19:56 +01:00
Michel Roegl-Brunner
74e57d61e2 add github actions runner 2026-03-04 10:12:36 +01:00
Michel Roegl-Brunner
be0b17c171 Update push_json_to_pocketbase.yml 2026-03-04 10:06:28 +01:00
John Doe
f6cb6fa8a8 feat: update interface port for LocalAGI from 8080 to 3000 2026-03-04 00:49:42 -05:00
John Doe
4895935b4a feat: reduce CPU allocation from 4 to 2 in LocalAGI configuration 2026-03-04 00:47:21 -05:00
John Doe
c5bbc2f81d feat: update LocalAGI resource configurations to reduce RAM to 4GB and disk size to 20GB 2026-03-04 00:46:51 -05:00
John Doe
abf9c8e78b feat: refactor LocalAGI backend configuration to use external-LLM mode and update disk size to 30GB 2026-03-04 00:46:36 -05:00
John Doe
7ec67de15c feat: update LOCALAGI_LLM_API_URL to Ollama-compatible endpoint and enhance documentation 2026-03-04 00:42:39 -05:00
John Doe
d49a8d04cd feat: update ROCm installation commands to use standardized functions 2026-03-04 00:35:43 -05:00
John Doe
83847ad98f feat: update logo URL in LocalAGI configuration to use CDN 2026-03-04 00:32:00 -05:00
John Doe
79b5cb70af feat: enhance LocalAGI /dev/kfd passthrough handling based on GPU type and backend 2026-03-04 00:31:29 -05:00
John Doe
390f2ff178 feat: increase default disk size to 60GB in LocalAGI installation scripts 2026-03-04 00:29:38 -05:00
John Doe
4cdfa49460 feat: add backend detection for LocalAGI installation based on host GPU 2026-03-04 00:25:11 -05:00
John Doe
2d81660dc5 feat: refactor header content retrieval in LocalAGI installation script 2026-03-04 00:23:38 -05:00
John Doe
63615ded07 feat: enhance ROCm installation process and backend resolution in LocalAGI scripts 2026-03-04 00:18:51 -05:00
John Doe
55de0ad144 feat: improve backend detection summary in LocalAGI installation scripts 2026-03-04 00:14:13 -05:00
John Doe
565705e837 feat: enhance GPU backend detection in LocalAGI installation scripts 2026-03-04 00:09:48 -05:00
John Doe
d3d1da15cc feat: remove AMD device detection for /dev/kfd from build functions 2026-03-04 00:08:01 -05:00
John Doe
cf986a34a9 feat: add function to ensure /dev/kfd passthrough for LocalAGI in LXC containers 2026-03-04 00:07:13 -05:00
John Doe
f9755d1102 feat: add AMD GPU detection for ROCm backend in LocalAGI installation scripts 2026-03-04 00:04:07 -05:00
John Doe
7e897f4e93 feat: enhance LocalAGI installation scripts with backend resolution and ROCm runtime support 2026-03-03 23:57:14 -05:00
John Doe
c2dba1e052 feat: refactor APT package installation functions for improved readability and maintainability 2026-03-03 23:53:28 -05:00
John Doe
39009f50f7 feat: implement resilient APT package installation and retry logic 2026-03-03 23:53:10 -05:00
John Doe
b603aa0670 feat: add ROCm runtime installation for Debian in localagi scripts 2026-03-03 23:49:57 -05:00
John Doe
d4f74b05b0 feat: enhance LocalAGI installation and update scripts with source build and systemd service integration 2026-03-03 23:47:27 -05:00
John Doe
f85543886f feat: add AMD device support and localagi header file 2026-03-03 23:41:11 -05:00
John Doe
1161c0b352 feat: add LocalAGI installation and configuration scripts 2026-03-03 23:31:02 -05:00
Stephen Chin
7ac2a1c3d6 feat: add Proton Mail Bridge 2026-02-25 23:22:09 -08:00
323 changed files with 11851 additions and 25621 deletions

7
.gitattributes vendored
View File

@@ -10,11 +10,6 @@
# Treat Golang files as Go (for /api/)
api/**/*.go linguist-language=Go
# ---------------------------------------
# Treat frontend as JavaScript/TypeScript (optional)
frontend/**/*.ts linguist-language=TypeScript
frontend/**/*.js linguist-language=JavaScript
# ---------------------------------------
# Exclude documentation from stats
*.md linguist-documentation
@@ -26,7 +21,7 @@ SECURITY.md linguist-documentation
# ---------------------------------------
# Exclude generated/config files
*.json linguist-generated
frontend/public/json/*.json linguist-generated=false
json/*.json linguist-generated=false
*.lock linguist-generated
*.yml linguist-generated
*.yaml linguist-generated

2
.github/autolabeler-config.json generated vendored
View File

@@ -97,7 +97,7 @@
{
"fileStatus": "modified",
"includeGlobs": [
"frontend/public/json/**"
"json/**"
],
"excludeGlobs": []
}

3
.github/pull_request_template.md generated vendored
View File

@@ -49,3 +49,6 @@ Link: #
- [ ] The application has **600+ GitHub stars**
- [ ] Official **release tarballs** are published
- [ ] I understand that not all scripts will be accepted due to various reasons and criteria by the community-scripts ORG
## 🌐 Source
<!-- Add any sources and github links. -->

View File

@@ -47,7 +47,7 @@ jobs:
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "GitHub Actions[bot]"
git checkout -b update_versions || git checkout update_versions
git add frontend/public/json/versions.json
git add json/versions.json
if git diff --cached --quiet; then
echo "No changes detected."
echo "changed=false" >> "$GITHUB_ENV"

View File

@@ -46,7 +46,7 @@ jobs:
run: |
page=1
projects_file="project_json"
output_file="frontend/public/json/versions.json"
output_file="json/versions.json"
echo "[]" > $output_file
@@ -95,7 +95,7 @@ jobs:
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "GitHub Actions[bot]"
git checkout -b update_versions || git checkout update_versions
git add frontend/public/json/versions.json
git add json/versions.json
if git diff --cached --quiet; then
echo "No changes detected."
echo "changed=false" >> "$GITHUB_ENV"

View File

@@ -11,8 +11,8 @@ permissions:
pull-requests: write
env:
SOURCES_FILE: frontend/public/json/version-sources.json
VERSIONS_FILE: frontend/public/json/versions.json
SOURCES_FILE: json/version-sources.json
VERSIONS_FILE: json/versions.json
jobs:
update-versions:

View File

@@ -7,6 +7,7 @@ on:
permissions:
issues: write
actions: write
jobs:
post_to_discord:
@@ -59,19 +60,19 @@ jobs:
FILES=(
"ct/${TITLE}.sh"
"install/${TITLE}-install.sh"
"frontend/public/json/${TITLE}.json"
"json/${TITLE}.json"
)
;;
vm)
FILES=(
"vm/${TITLE}.sh"
"frontend/public/json/${TITLE}.json"
"json/${TITLE}.json"
)
;;
addon)
FILES=(
"tools/addon/${TITLE}.sh"
"frontend/public/json/${TITLE}.json"
"json/${TITLE}.json"
)
;;
pve)
@@ -122,7 +123,7 @@ jobs:
JSON_FILE=""
case "$SCRIPT_TYPE" in
ct|vm|addon)
JSON_FILE="frontend/public/json/${TITLE}.json"
JSON_FILE="json/${TITLE}.json"
;;
esac
@@ -217,3 +218,10 @@ jobs:
echo -e "$MESSAGE" > comment.txt
sed -i '/Discussion & issue tracking:/,$d' comment.txt
gh issue comment ${{ github.event.issue.number }} --repo ${{ github.repository }} --body-file comment.txt
- name: Push script JSON to PocketBase
if: env.SCRIPT_TYPE == 'ct' || env.SCRIPT_TYPE == 'vm' || env.SCRIPT_TYPE == 'addon'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh workflow run push_json_to_pocketbase.yml --repo ${{ github.repository }} -f script_slug=${{ env.TITLE }}

View File

@@ -124,20 +124,20 @@ jobs:
rm -f "ct/${TITLE}.sh"
rm -f "ct/headers/${TITLE}"
rm -f "install/${TITLE}-install.sh"
rm -f "frontend/public/json/${TITLE}.json"
rm -f "json/${TITLE}.json"
# Also try alpine variant
if [[ "$TITLE" == alpine-* ]]; then
stripped="${TITLE#alpine-}"
rm -f "frontend/public/json/${stripped}.json"
rm -f "json/${stripped}.json"
fi
;;
vm)
rm -f "vm/${TITLE}.sh"
rm -f "frontend/public/json/${TITLE}.json"
rm -f "json/${TITLE}.json"
;;
addon)
rm -f "tools/addon/${TITLE}.sh"
rm -f "frontend/public/json/${TITLE}.json"
rm -f "json/${TITLE}.json"
;;
pve)
rm -f "tools/pve/${TITLE}.sh"

77
.github/workflows/frontend-cicd.yml generated vendored
View File

@@ -1,77 +0,0 @@
# Based on https://github.com/actions/starter-workflows/blob/main/pages/nextjs.yml
name: Frontend CI/CD
on:
push:
branches: ["main"]
paths:
- frontend/**
pull_request:
branches: ["main"]
types: [opened, synchronize, reopened, edited]
paths:
- frontend/**
workflow_dispatch:
permissions:
contents: read
concurrency:
group: pages-${{ github.ref }}
cancel-in-progress: false
jobs:
build:
if: github.repository == 'community-scripts/ProxmoxVED'
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend # Set default working directory for all run steps
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
run: npm ci --prefer-offline --legacy-peer-deps
- name: Run tests
run: npm run test
- name: Configure Next.js for pages
uses: actions/configure-pages@v5
with:
static_site_generator: next
- name: Build with Next.js
run: npm run build
- name: Upload artifact
if: github.ref == 'refs/heads/main'
uses: actions/upload-pages-artifact@v3
with:
path: frontend/out
deploy:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main' && github.repository == 'community-scripts/ProxmoxVED'
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

View File

@@ -39,11 +39,22 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
run: |
echo "Filtering Issues with Label Migration To ProxmoxVE"
raw_output=$(gh issue list --json title,labels,number,body)
filtered_issue=$(echo "$raw_output" | jq -r '[.[] | select(.labels[]?.name == "Migration To ProxmoxVE")][0]')
echo "Resolving issue with label Migration To ProxmoxVE"
if [ "$filtered_issue" == "null" ] || [ -z "$filtered_issue" ]; then
if [[ "${{ github.event_name }}" == "issues" ]]; then
# For labeled issue events, use the exact issue from event payload.
filtered_issue='${{ toJson(github.event.issue) }}'
else
# Fallback for workflow_dispatch: query explicitly by label and raise limit.
raw_output=$(gh issue list \
--label "Migration To ProxmoxVE" \
--state open \
--limit 500 \
--json title,labels,number,body)
filtered_issue=$(echo "$raw_output" | jq -c '.[0]')
fi
if [[ "$filtered_issue" == "null" ]] || [[ -z "$filtered_issue" ]]; then
echo "No issues found with label 'Migration To ProxmoxVE'."
exit 1
fi
@@ -100,26 +111,6 @@ jobs:
files_found="false"
missing_files+="install/${script_name}-install.sh "
fi
# JSON check with alpine fallback
json_file="frontend/public/json/${script_name}.json"
if [[ ! -f "$json_file" ]]; then
if [[ "$script_name" == alpine-* ]]; then
stripped_name="${script_name#alpine-}"
alt_json="frontend/public/json/${stripped_name}.json"
if [[ -f "$alt_json" ]]; then
echo "Using alpine fallback JSON: $alt_json"
echo "json_fallback=$alt_json" >> $GITHUB_OUTPUT
else
echo "json file not found: $json_file"
files_found="false"
missing_files+="$json_file "
fi
else
echo "json file not found: $json_file"
files_found="false"
missing_files+="$json_file "
fi
fi
;;
vm)
if [[ ! -f "vm/${script_name}.sh" ]]; then
@@ -127,11 +118,6 @@ jobs:
files_found="false"
missing_files+="vm/${script_name}.sh "
fi
# JSON is optional for VMs but check anyway
json_file="frontend/public/json/${script_name}.json"
if [[ ! -f "$json_file" ]]; then
echo "json file not found (optional): $json_file"
fi
;;
addon)
if [[ ! -f "tools/addon/${script_name}.sh" ]]; then
@@ -139,11 +125,6 @@ jobs:
files_found="false"
missing_files+="tools/addon/${script_name}.sh "
fi
# JSON is optional for addons
json_file="frontend/public/json/${script_name}.json"
if [[ ! -f "$json_file" ]]; then
echo "json file not found (optional): $json_file"
fi
;;
pve)
if [[ ! -f "tools/pve/${script_name}.sh" ]]; then
@@ -190,7 +171,6 @@ jobs:
run: |
script_name="${{ steps.list_issues.outputs.script_name }}"
script_type="${{ steps.list_issues.outputs.script_type }}"
json_fallback="${{ steps.check_files.outputs.json_fallback }}"
git clone https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/community-scripts/ProxmoxVE.git ProxmoxVE
cd ProxmoxVE
@@ -227,13 +207,6 @@ jobs:
cp ../ct/headers/${script_name} ct/headers/ 2>/dev/null || true
cp ../install/${script_name}-install.sh install/
# Handle JSON with alpine fallback
if [[ -n "$json_fallback" ]]; then
cp ../${json_fallback} frontend/public/json/ || true
else
cp ../frontend/public/json/${script_name}.json frontend/public/json/ 2>/dev/null || true
fi
# Update URLs in ct script
sed -i "s|https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func|https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func|" ct/${script_name}.sh
sed -i "s|https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func|https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func|" ct/${script_name}.sh
@@ -242,7 +215,6 @@ jobs:
;;
vm)
cp ../vm/${script_name}.sh vm/
cp ../frontend/public/json/${script_name}.json frontend/public/json/ 2>/dev/null || true
# Update URLs in vm script
sed -i "s|https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func|https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func|" vm/${script_name}.sh
@@ -251,7 +223,6 @@ jobs:
addon)
mkdir -p tools/addon
cp ../tools/addon/${script_name}.sh tools/addon/
cp ../frontend/public/json/${script_name}.json frontend/public/json/ 2>/dev/null || true
# Update URLs in addon script
sed -i "s|community-scripts/ProxmoxVED|community-scripts/ProxmoxVE|g" tools/addon/${script_name}.sh

676
.github/workflows/pocketbase-bot.yml generated vendored Normal file
View File

@@ -0,0 +1,676 @@
name: PocketBase Bot
on:
issue_comment:
types: [created]
permissions:
issues: write
pull-requests: write
contents: read
jobs:
pocketbase-bot:
runs-on: self-hosted
# Only act on /pocketbase commands
if: startsWith(github.event.comment.body, '/pocketbase')
steps:
- name: Execute PocketBase bot command
env:
POCKETBASE_URL: ${{ secrets.POCKETBASE_URL }}
POCKETBASE_COLLECTION: ${{ secrets.POCKETBASE_COLLECTION }}
POCKETBASE_ADMIN_EMAIL: ${{ secrets.POCKETBASE_ADMIN_EMAIL }}
POCKETBASE_ADMIN_PASSWORD: ${{ secrets.POCKETBASE_ADMIN_PASSWORD }}
COMMENT_BODY: ${{ github.event.comment.body }}
COMMENT_ID: ${{ github.event.comment.id }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
REPO_OWNER: ${{ github.repository_owner }}
REPO_NAME: ${{ github.event.repository.name }}
ACTOR: ${{ github.event.comment.user.login }}
ACTOR_ASSOCIATION: ${{ github.event.comment.author_association }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
node << 'ENDSCRIPT'
(async function () {
const https = require('https');
const http = require('http');
const url = require('url');
// ── HTTP helper with redirect following ────────────────────────────
function request(fullUrl, opts, redirectCount) {
redirectCount = redirectCount || 0;
return new Promise(function (resolve, reject) {
const u = url.parse(fullUrl);
const isHttps = u.protocol === 'https:';
const body = opts.body;
const options = {
hostname: u.hostname,
port: u.port || (isHttps ? 443 : 80),
path: u.path,
method: opts.method || 'GET',
headers: opts.headers || {}
};
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
const lib = isHttps ? https : http;
const req = lib.request(options, function (res) {
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
if (redirectCount >= 5) return reject(new Error('Too many redirects from ' + fullUrl));
const redirectUrl = url.resolve(fullUrl, res.headers.location);
res.resume();
resolve(request(redirectUrl, opts, redirectCount + 1));
return;
}
let data = '';
res.on('data', function (chunk) { data += chunk; });
res.on('end', function () {
resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, statusCode: res.statusCode, body: data });
});
});
req.on('error', reject);
if (body) req.write(body);
req.end();
});
}
// ── GitHub API helpers ─────────────────────────────────────────────
const owner = process.env.REPO_OWNER;
const repo = process.env.REPO_NAME;
const issueNumber = parseInt(process.env.ISSUE_NUMBER, 10);
const commentId = parseInt(process.env.COMMENT_ID, 10);
const actor = process.env.ACTOR;
function ghRequest(path, method, body) {
const headers = {
'Authorization': 'Bearer ' + process.env.GITHUB_TOKEN,
'Accept': 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
'User-Agent': 'PocketBase-Bot'
};
const bodyStr = body ? JSON.stringify(body) : undefined;
if (bodyStr) headers['Content-Type'] = 'application/json';
return request('https://api.github.com' + path, { method: method || 'GET', headers, body: bodyStr });
}
async function addReaction(content) {
try {
await ghRequest(
'/repos/' + owner + '/' + repo + '/issues/comments/' + commentId + '/reactions',
'POST', { content }
);
} catch (e) {
console.warn('Could not add reaction:', e.message);
}
}
async function postComment(text) {
const res = await ghRequest(
'/repos/' + owner + '/' + repo + '/issues/' + issueNumber + '/comments',
'POST', { body: text }
);
if (!res.ok) console.warn('Could not post comment:', res.body);
}
// ── Permission check ───────────────────────────────────────────────
// author_association: OWNER = repo/org owner, MEMBER = org member (includes Contributors team)
const association = process.env.ACTOR_ASSOCIATION;
if (association !== 'OWNER' && association !== 'MEMBER') {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: @' + actor + ' is not authorized to use this command.\n' +
'Only org members (Contributors team) can use `/pocketbase`.'
);
process.exit(0);
}
// ── Acknowledge ────────────────────────────────────────────────────
await addReaction('eyes');
// ── Parse command ──────────────────────────────────────────────────
// Formats (first line of comment):
// /pocketbase <slug> field=value [field=value ...] ← field updates (simple values)
// /pocketbase <slug> set <field> ← value from code block below
// /pocketbase <slug> note list|add|edit|remove ... ← note management
// /pocketbase <slug> method list ← list install methods
// /pocketbase <slug> method <type> cpu=N ram=N hdd=N ← edit install method resources
const commentBody = process.env.COMMENT_BODY || '';
const lines = commentBody.trim().split('\n');
const firstLine = lines[0].trim();
const withoutCmd = firstLine.replace(/^\/pocketbase\s+/, '').trim();
// Extract code block content from comment body (```...``` or ```lang\n...```)
function extractCodeBlock(body) {
const m = body.match(/```[^\n]*\n([\s\S]*?)```/);
return m ? m[1].trim() : null;
}
const codeBlockValue = extractCodeBlock(commentBody);
const HELP_TEXT =
'**Field update (simple):** `/pocketbase <slug> field=value [field=value ...]`\n\n' +
'**Field update (HTML/multiline) — value from code block:**\n' +
'````\n' +
'/pocketbase <slug> set description\n' +
'```html\n' +
'<p>Your <b>HTML</b> or multi-line content here</p>\n' +
'```\n' +
'````\n\n' +
'**Note management:**\n' +
'```\n' +
'/pocketbase <slug> note list\n' +
'/pocketbase <slug> note add <type> "<text>"\n' +
'/pocketbase <slug> note edit <type> "<old text>" "<new text>"\n' +
'/pocketbase <slug> note remove <type> "<text>"\n' +
'```\n\n' +
'**Install method resources:**\n' +
'```\n' +
'/pocketbase <slug> method list\n' +
'/pocketbase <slug> method <type> hdd=10\n' +
'/pocketbase <slug> method <type> cpu=4 ram=2048 hdd=20\n' +
'```\n\n' +
'**Editable fields:** `name` `description` `logo` `documentation` `website` `project_url` `github` ' +
'`config_path` `port` `default_user` `default_passwd` ' +
'`updateable` `privileged` `has_arm` `is_dev` ' +
'`is_disabled` `disable_message` `is_deleted` `deleted_message`';
if (!withoutCmd) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: No slug or command specified.\n\n' + HELP_TEXT);
process.exit(0);
}
const spaceIdx = withoutCmd.indexOf(' ');
const slug = (spaceIdx === -1 ? withoutCmd : withoutCmd.substring(0, spaceIdx)).trim();
const rest = spaceIdx === -1 ? '' : withoutCmd.substring(spaceIdx + 1).trim();
if (!rest) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: No command specified for slug `' + slug + '`.\n\n' + HELP_TEXT);
process.exit(0);
}
// ── Allowed fields and their types ─────────────────────────────────
// ── PocketBase: authenticate (shared by all paths) ─────────────────
const raw = process.env.POCKETBASE_URL.replace(/\/$/, '');
const apiBase = /\/api$/i.test(raw) ? raw : raw + '/api';
const coll = process.env.POCKETBASE_COLLECTION;
const authRes = await request(apiBase + '/collections/users/auth-with-password', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
identity: process.env.POCKETBASE_ADMIN_EMAIL,
password: process.env.POCKETBASE_ADMIN_PASSWORD
})
});
if (!authRes.ok) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: PocketBase authentication failed. CC @' + owner + '/maintainers');
process.exit(1);
}
const token = JSON.parse(authRes.body).token;
// ── PocketBase: find record by slug (shared by all paths) ──────────
const recordsUrl = apiBase + '/collections/' + encodeURIComponent(coll) + '/records';
const filter = "(slug='" + slug.replace(/'/g, "''") + "')";
const listRes = await request(recordsUrl + '?filter=' + encodeURIComponent(filter) + '&perPage=1', {
headers: { 'Authorization': token }
});
const list = JSON.parse(listRes.body);
const record = list.items && list.items[0];
if (!record) {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: No record found for slug `' + slug + '`.\n\n' +
'Make sure the script was already pushed to PocketBase (JSON must exist and have been synced).'
);
process.exit(0);
}
// ── Route: dispatch to subcommand handler ──────────────────────────
const noteMatch = rest.match(/^note\s+(list|add|edit|remove)\b/i);
const methodMatch = rest.match(/^method\b/i);
const setMatch = rest.match(/^set\s+(\S+)/i);
if (noteMatch) {
// ── NOTE SUBCOMMAND (reads/writes notes_json on script record) ────
const noteAction = noteMatch[1].toLowerCase();
const noteArgsStr = rest.substring(noteMatch[0].length).trim();
// Parse notes_json from the already-fetched script record
// PocketBase may return JSON fields as already-parsed objects
let notesArr = [];
try {
const rawNotes = record.notes_json;
notesArr = Array.isArray(rawNotes) ? rawNotes : JSON.parse(rawNotes || '[]');
} catch (e) { notesArr = []; }
// Token parser: unquoted-word OR "quoted string" (supports \" escapes)
function parseNoteTokens(str) {
const tokens = [];
let pos = 0;
while (pos < str.length) {
while (pos < str.length && /\s/.test(str[pos])) pos++;
if (pos >= str.length) break;
if (str[pos] === '"') {
pos++;
let start = pos;
while (pos < str.length && str[pos] !== '"') {
if (str[pos] === '\\') pos++;
pos++;
}
tokens.push(str.substring(start, pos).replace(/\\"/g, '"'));
if (pos < str.length) pos++;
} else {
let start = pos;
while (pos < str.length && !/\s/.test(str[pos])) pos++;
tokens.push(str.substring(start, pos));
}
}
return tokens;
}
function formatNotesList(arr) {
if (arr.length === 0) return '*None*';
return arr.map(function (n, i) {
return (i + 1) + '. **`' + (n.type || '?') + '`**: ' + (n.text || '');
}).join('\n');
}
async function patchNotesJson(arr) {
const res = await request(recordsUrl + '/' + record.id, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify({ notes_json: JSON.stringify(arr) })
});
if (!res.ok) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: Failed to update `notes_json`:\n```\n' + res.body + '\n```');
process.exit(1);
}
}
if (noteAction === 'list') {
await addReaction('+1');
await postComment(
' **PocketBase Bot**: Notes for **`' + slug + '`** (' + notesArr.length + ' total)\n\n' +
formatNotesList(notesArr)
);
} else if (noteAction === 'add') {
const tokens = parseNoteTokens(noteArgsStr);
if (tokens.length < 2) {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: `note add` requires `<type>` and `"<text>"`.\n\n' +
'**Usage:** `/pocketbase ' + slug + ' note add <type> "<text>"`'
);
process.exit(0);
}
const noteType = tokens[0].toLowerCase();
const noteText = tokens.slice(1).join(' ');
notesArr.push({ type: noteType, text: noteText });
await patchNotesJson(notesArr);
await addReaction('+1');
await postComment(
'✅ **PocketBase Bot**: Added note to **`' + slug + '`**\n\n' +
'- **Type:** `' + noteType + '`\n' +
'- **Text:** ' + noteText + '\n\n' +
'*Executed by @' + actor + '*'
);
} else if (noteAction === 'edit') {
const tokens = parseNoteTokens(noteArgsStr);
if (tokens.length < 3) {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: `note edit` requires `<type>`, `"<old text>"`, and `"<new text>"`.\n\n' +
'**Usage:** `/pocketbase ' + slug + ' note edit <type> "<old text>" "<new text>"`\n\n' +
'Use `/pocketbase ' + slug + ' note list` to see current notes.'
);
process.exit(0);
}
const noteType = tokens[0].toLowerCase();
const oldText = tokens[1];
const newText = tokens[2];
const idx = notesArr.findIndex(function (n) {
return n.type.toLowerCase() === noteType && n.text === oldText;
});
if (idx === -1) {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: No `' + noteType + '` note found with that exact text.\n\n' +
'**Current notes for `' + slug + '`:**\n' + formatNotesList(notesArr)
);
process.exit(0);
}
notesArr[idx].text = newText;
await patchNotesJson(notesArr);
await addReaction('+1');
await postComment(
'✅ **PocketBase Bot**: Edited note in **`' + slug + '`**\n\n' +
'- **Type:** `' + noteType + '`\n' +
'- **Old:** ' + oldText + '\n' +
'- **New:** ' + newText + '\n\n' +
'*Executed by @' + actor + '*'
);
} else if (noteAction === 'remove') {
const tokens = parseNoteTokens(noteArgsStr);
if (tokens.length < 2) {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: `note remove` requires `<type>` and `"<text>"`.\n\n' +
'**Usage:** `/pocketbase ' + slug + ' note remove <type> "<text>"`\n\n' +
'Use `/pocketbase ' + slug + ' note list` to see current notes.'
);
process.exit(0);
}
const noteType = tokens[0].toLowerCase();
const noteText = tokens[1];
const before = notesArr.length;
notesArr = notesArr.filter(function (n) {
return !(n.type.toLowerCase() === noteType && n.text === noteText);
});
if (notesArr.length === before) {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: No `' + noteType + '` note found with that exact text.\n\n' +
'**Current notes for `' + slug + '`:**\n' + formatNotesList(notesArr)
);
process.exit(0);
}
await patchNotesJson(notesArr);
await addReaction('+1');
await postComment(
'✅ **PocketBase Bot**: Removed note from **`' + slug + '`**\n\n' +
'- **Type:** `' + noteType + '`\n' +
'- **Text:** ' + noteText + '\n\n' +
'*Executed by @' + actor + '*'
);
}
} else if (methodMatch) {
// ── METHOD SUBCOMMAND (reads/writes install_methods_json on script record) ──
const methodArgs = rest.replace(/^method\s*/i, '').trim();
const methodListMode = !methodArgs || methodArgs.toLowerCase() === 'list';
// Parse install_methods_json from the already-fetched script record
// PocketBase may return JSON fields as already-parsed objects
let methodsArr = [];
try {
const rawMethods = record.install_methods_json;
methodsArr = Array.isArray(rawMethods) ? rawMethods : JSON.parse(rawMethods || '[]');
} catch (e) { methodsArr = []; }
function formatMethodsList(arr) {
if (arr.length === 0) return '*None*';
return arr.map(function (im, i) {
const r = im.resources || {};
return (i + 1) + '. **`' + (im.type || '?') + '`** — CPU: `' + (r.cpu != null ? r.cpu : '?') +
'` · RAM: `' + (r.ram != null ? r.ram : '?') + ' MB` · HDD: `' + (r.hdd != null ? r.hdd : '?') + ' GB`';
}).join('\n');
}
async function patchInstallMethodsJson(arr) {
const res = await request(recordsUrl + '/' + record.id, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify({ install_methods_json: JSON.stringify(arr) })
});
if (!res.ok) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: Failed to update `install_methods_json`:\n```\n' + res.body + '\n```');
process.exit(1);
}
}
if (methodListMode) {
await addReaction('+1');
await postComment(
' **PocketBase Bot**: Install methods for **`' + slug + '`** (' + methodsArr.length + ' total)\n\n' +
formatMethodsList(methodsArr)
);
} else {
// Parse: <type> cpu=N ram=N hdd=N
const methodParts = methodArgs.match(/^(\S+)\s+(.+)$/);
if (!methodParts) {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: Invalid `method` syntax.\n\n' +
'**Usage:**\n```\n/pocketbase ' + slug + ' method list\n/pocketbase ' + slug + ' method <type> hdd=10\n/pocketbase ' + slug + ' method <type> cpu=4 ram=2048 hdd=20\n```'
);
process.exit(0);
}
const targetType = methodParts[1].toLowerCase();
const resourcesStr = methodParts[2];
// Parse resource fields (only cpu/ram/hdd allowed)
const RESOURCE_FIELDS = { cpu: true, ram: true, hdd: true };
const resourceChanges = {};
const rePairs = /([a-z]+)=(\d+)/gi;
let m;
while ((m = rePairs.exec(resourcesStr)) !== null) {
const key = m[1].toLowerCase();
if (RESOURCE_FIELDS[key]) resourceChanges[key] = parseInt(m[2], 10);
}
if (Object.keys(resourceChanges).length === 0) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: No valid resource fields found. Use `cpu=N`, `ram=N`, `hdd=N`.');
process.exit(0);
}
// Find matching method by type name (case-insensitive)
const idx = methodsArr.findIndex(function (im) {
return (im.type || '').toLowerCase() === targetType;
});
if (idx === -1) {
await addReaction('-1');
const availableTypes = methodsArr.map(function (im) { return im.type || '?'; });
await postComment(
'❌ **PocketBase Bot**: No install method with type `' + targetType + '` found for `' + slug + '`.\n\n' +
'**Available types:** `' + (availableTypes.length ? availableTypes.join('`, `') : '(none)') + '`\n\n' +
'Use `/pocketbase ' + slug + ' method list` to see all methods.'
);
process.exit(0);
}
if (!methodsArr[idx].resources) methodsArr[idx].resources = {};
if (resourceChanges.cpu != null) methodsArr[idx].resources.cpu = resourceChanges.cpu;
if (resourceChanges.ram != null) methodsArr[idx].resources.ram = resourceChanges.ram;
if (resourceChanges.hdd != null) methodsArr[idx].resources.hdd = resourceChanges.hdd;
await patchInstallMethodsJson(methodsArr);
const changesLines = Object.entries(resourceChanges)
.map(function ([k, v]) { return '- `' + k + '` → `' + v + (k === 'ram' ? ' MB' : k === 'hdd' ? ' GB' : '') + '`'; })
.join('\n');
await addReaction('+1');
await postComment(
'✅ **PocketBase Bot**: Updated install method **`' + methodsArr[idx].type + '`** for **`' + slug + '`**\n\n' +
'**Changes applied:**\n' + changesLines + '\n\n' +
'*Executed by @' + actor + '*'
);
}
} else if (setMatch) {
// ── SET SUBCOMMAND (multi-line / HTML / special chars via code block) ──
const fieldName = setMatch[1].toLowerCase();
const SET_ALLOWED = {
name: 'string', description: 'string', logo: 'string',
documentation: 'string', website: 'string', project_url: 'string', github: 'string',
config_path: 'string', disable_message: 'string', deleted_message: 'string'
};
if (!SET_ALLOWED[fieldName]) {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: `set` only supports text fields.\n\n' +
'**Allowed:** `' + Object.keys(SET_ALLOWED).join('`, `') + '`\n\n' +
'For boolean/number fields use `field=value` syntax instead.'
);
process.exit(0);
}
if (!codeBlockValue) {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: `set` requires a code block with the value.\n\n' +
'**Usage:**\n````\n/pocketbase ' + slug + ' set ' + fieldName + '\n```\nYour content here (HTML, multiline, special chars all fine)\n```\n````'
);
process.exit(0);
}
const setPayload = {};
setPayload[fieldName] = codeBlockValue;
const setPatchRes = await request(recordsUrl + '/' + record.id, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify(setPayload)
});
if (!setPatchRes.ok) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: PATCH failed for `' + slug + '`:\n```\n' + setPatchRes.body + '\n```');
process.exit(1);
}
const preview = codeBlockValue.length > 300 ? codeBlockValue.substring(0, 300) + '…' : codeBlockValue;
await addReaction('+1');
await postComment(
'✅ **PocketBase Bot**: Set `' + fieldName + '` for **`' + slug + '`**\n\n' +
'**Value set:**\n```\n' + preview + '\n```\n\n' +
'*Executed by @' + actor + '*'
);
} else {
// ── FIELD=VALUE PATH ─────────────────────────────────────────────
const fieldsStr = rest;
// Skipped: slug, script_created/updated, created (auto), categories/
// install_methods/notes/type (relations), github_data/install_methods_json/
// notes_json (auto-generated), execute_in (select relation), last_update_commit (auto)
const ALLOWED_FIELDS = {
name: 'string',
description: 'string',
logo: 'string',
documentation: 'string',
website: 'string',
project_url: 'string',
github: 'string',
config_path: 'string',
port: 'number',
default_user: 'nullable_string',
default_passwd: 'nullable_string',
updateable: 'boolean',
privileged: 'boolean',
has_arm: 'boolean',
is_dev: 'boolean',
is_disabled: 'boolean',
disable_message: 'string',
is_deleted: 'boolean',
deleted_message: 'string',
version: 'string',
};
// Field=value parser (handles quoted values and empty=null)
function parseFields(str) {
const fields = {};
let pos = 0;
while (pos < str.length) {
while (pos < str.length && /\s/.test(str[pos])) pos++;
if (pos >= str.length) break;
let keyStart = pos;
while (pos < str.length && str[pos] !== '=' && !/\s/.test(str[pos])) pos++;
const key = str.substring(keyStart, pos).trim();
if (!key || pos >= str.length || str[pos] !== '=') { pos++; continue; }
pos++;
let value;
if (str[pos] === '"') {
pos++;
let valStart = pos;
while (pos < str.length && str[pos] !== '"') {
if (str[pos] === '\\') pos++;
pos++;
}
value = str.substring(valStart, pos).replace(/\\"/g, '"');
if (pos < str.length) pos++;
} else {
let valStart = pos;
while (pos < str.length && !/\s/.test(str[pos])) pos++;
value = str.substring(valStart, pos);
}
fields[key] = value;
}
return fields;
}
const parsedFields = parseFields(fieldsStr);
const unknownFields = Object.keys(parsedFields).filter(function (f) { return !ALLOWED_FIELDS[f]; });
if (unknownFields.length > 0) {
await addReaction('-1');
await postComment(
'❌ **PocketBase Bot**: Unknown field(s): `' + unknownFields.join('`, `') + '`\n\n' +
'**Allowed fields:** `' + Object.keys(ALLOWED_FIELDS).join('`, `') + '`'
);
process.exit(0);
}
if (Object.keys(parsedFields).length === 0) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: Could not parse any valid `field=value` pairs.\n\n' + HELP_TEXT);
process.exit(0);
}
// Cast values to correct types
const payload = {};
for (const [key, rawVal] of Object.entries(parsedFields)) {
const type = ALLOWED_FIELDS[key];
if (type === 'boolean') {
if (rawVal === 'true') payload[key] = true;
else if (rawVal === 'false') payload[key] = false;
else {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: `' + key + '` must be `true` or `false`, got: `' + rawVal + '`');
process.exit(0);
}
} else if (type === 'number') {
const n = parseInt(rawVal, 10);
if (isNaN(n)) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: `' + key + '` must be a number, got: `' + rawVal + '`');
process.exit(0);
}
payload[key] = n;
} else if (type === 'nullable_string') {
payload[key] = rawVal === '' ? null : rawVal;
} else {
payload[key] = rawVal;
}
}
const patchRes = await request(recordsUrl + '/' + record.id, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!patchRes.ok) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: PATCH failed for `' + slug + '`:\n```\n' + patchRes.body + '\n```');
process.exit(1);
}
await addReaction('+1');
const changesLines = Object.entries(payload)
.map(function ([k, v]) { return '- `' + k + '` → `' + JSON.stringify(v) + '`'; })
.join('\n');
await postComment(
'✅ **PocketBase Bot**: Updated **`' + slug + '`** successfully!\n\n' +
'**Changes applied:**\n' + changesLines + '\n\n' +
'*Executed by @' + actor + '*'
);
}
console.log('Done.');
})().catch(function (e) {
console.error('Fatal error:', e.message || e);
process.exit(1);
});
ENDSCRIPT
shell: bash

39
.github/workflows/push-to-gitea.yml generated vendored
View File

@@ -1,39 +0,0 @@
name: Sync to Gitea
on:
push:
branches:
- main
jobs:
sync:
if: github.repository == 'community-scripts/ProxmoxVED'
runs-on: ubuntu-latest
steps:
- name: Checkout source repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set Git identity for actions
run: |
git config --global user.name "Push From Github"
git config --global user.email "actions@github.com"
- name: Add Gitea remote
run: git remote add gitea https://$GITEA_USER:$GITEA_TOKEN@git.community-scripts.org/community-scripts/ProxmoxVED.git
env:
GITEA_USER: ${{ secrets.GITEA_USERNAME }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
- name: Pull Gitea changes
run: |
git fetch gitea
git merge --strategy=ours gitea/main
env:
GITEA_USER: ${{ secrets.GITEA_USERNAME }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
- name: Push to Gitea
run: git push gitea main --force
env:
GITEA_USER: ${{ secrets.GITEA_USERNAME }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}

View File

@@ -5,7 +5,13 @@ on:
branches:
- main
paths:
- "frontend/public/json/**"
- "json/*.json"
workflow_dispatch:
inputs:
script_slug:
description: "Script slug (e.g. my-app)"
required: true
type: string
jobs:
push-json:
@@ -16,23 +22,55 @@ jobs:
with:
fetch-depth: 0
- name: Get changed JSON files with slug
- name: Get JSON file for script
id: changed
run: |
changed=$(git diff --name-only "${{ github.event.before }}" "${{ github.event.after }}" -- frontend/public/json/ | grep '\.json$' || true)
with_slug=""
for f in $changed; do
[[ -f "$f" ]] || continue
jq -e '.slug' "$f" >/dev/null 2>&1 && with_slug="$with_slug $f"
done
with_slug=$(echo $with_slug | xargs -n1)
if [[ -z "$with_slug" ]]; then
echo "No app JSON files changed (or no files with slug)."
: > changed_app_jsons.txt
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
script_slug="${{ github.event.inputs.script_slug }}"
file="json/${script_slug}.json"
if [[ ! -f "$file" ]]; then
echo "No JSON file at $file."
echo "count=0" >> "$GITHUB_OUTPUT"
exit 0
fi
if ! jq -e '.slug' "$file" >/dev/null 2>&1; then
echo "File $file has no .slug."
echo "count=0" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "$file" > changed_app_jsons.txt
echo "count=1" >> "$GITHUB_OUTPUT"
exit 0
fi
changed=$(git diff --name-only "${{ github.event.before }}" "${{ github.event.after }}" -- json/*.json || true)
if [[ -z "$changed" ]]; then
echo "No JSON files changed under json/*.json."
echo "count=0" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "$with_slug" > changed_app_jsons.txt
echo "count=$(echo "$with_slug" | wc -w)" >> "$GITHUB_OUTPUT"
count=0
for file in $changed; do
[[ -f "$file" ]] || continue
if [[ "$file" == "json/metadata.json" || "$file" == "json/update-apps.json" || "$file" == "json/versions.json" ]]; then
continue
fi
if jq -e '.slug' "$file" >/dev/null 2>&1; then
echo "$file" >> changed_app_jsons.txt
count=$((count + 1))
fi
done
if [[ $count -eq 0 ]]; then
echo "No app JSON files with .slug found in this push."
echo "count=0" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "count=$count" >> "$GITHUB_OUTPUT"
- name: Push to PocketBase
if: steps.changed.outputs.count != '0'
@@ -48,7 +86,8 @@ jobs:
const https = require('https');
const http = require('http');
const url = require('url');
function request(fullUrl, opts) {
function request(fullUrl, opts, redirectCount) {
redirectCount = redirectCount || 0;
return new Promise(function(resolve, reject) {
const u = url.parse(fullUrl);
const isHttps = u.protocol === 'https:';
@@ -63,6 +102,13 @@ jobs:
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
const lib = isHttps ? https : http;
const req = lib.request(options, function(res) {
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
if (redirectCount >= 5) return reject(new Error('Too many redirects from ' + fullUrl));
const redirectUrl = url.resolve(fullUrl, res.headers.location);
res.resume();
resolve(request(redirectUrl, opts, redirectCount + 1));
return;
}
let data = '';
res.on('data', function(chunk) { data += chunk; });
res.on('end', function() {
@@ -96,7 +142,7 @@ jobs:
const recordsUrl = apiBase + '/collections/' + encodeURIComponent(coll) + '/records';
let categoryIdToName = {};
try {
const metadata = JSON.parse(fs.readFileSync('frontend/public/json/metadata.json', 'utf8'));
const metadata = JSON.parse(fs.readFileSync('json/metadata.json', 'utf8'));
(metadata.categories || []).forEach(function(cat) { categoryIdToName[cat.id] = cat.name; });
} catch (e) { console.warn('Could not load metadata.json:', e.message); }
let typeValueToId = {};
@@ -125,22 +171,32 @@ jobs:
var osVersionToId = {};
try {
const res = await request(apiBase + '/collections/z_ref_note_types/records?perPage=500', { headers: { 'Authorization': token } });
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.type != null) noteTypeToId[item.type] = item.id; });
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) {
if (item.type != null) { noteTypeToId[item.type] = item.id; noteTypeToId[item.type.toLowerCase()] = item.id; }
});
} catch (e) { console.warn('z_ref_note_types:', e.message); }
try {
const res = await request(apiBase + '/collections/z_ref_install_method_types/records?perPage=500', { headers: { 'Authorization': token } });
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.type != null) installMethodTypeToId[item.type] = item.id; });
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) {
if (item.type != null) { installMethodTypeToId[item.type] = item.id; installMethodTypeToId[item.type.toLowerCase()] = item.id; }
});
} catch (e) { console.warn('z_ref_install_method_types:', e.message); }
try {
const res = await request(apiBase + '/collections/z_ref_os/records?perPage=500', { headers: { 'Authorization': token } });
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.os != null) osToId[item.os] = item.id; });
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) {
if (item.os != null) { osToId[item.os] = item.id; osToId[item.os.toLowerCase()] = item.id; }
});
} catch (e) { console.warn('z_ref_os:', e.message); }
try {
const res = await request(apiBase + '/collections/z_ref_os_version/records?perPage=500&expand=os', { headers: { 'Authorization': token } });
if (res.ok) {
(JSON.parse(res.body).items || []).forEach(function(item) {
var osName = item.expand && item.expand.os && item.expand.os.os != null ? item.expand.os.os : null;
if (osName != null && item.version != null) osVersionToId[osName + '|' + item.version] = item.id;
if (osName != null && item.version != null) {
var key = osName + '|' + item.version;
osVersionToId[key] = item.id;
osVersionToId[osName.toLowerCase() + '|' + item.version] = item.id;
}
});
}
} catch (e) { console.warn('z_ref_os_version:', e.message); }
@@ -150,11 +206,40 @@ jobs:
if (!fs.existsSync(file)) continue;
const data = JSON.parse(fs.readFileSync(file, 'utf8'));
if (!data.slug) { console.log('Skipping', file, '(no slug)'); continue; }
// execute_in: map type to canonical value
var executeInMap = { ct: 'lxc', lxc: 'lxc', turnkey: 'turnkey', pve: 'pve', addon: 'addon', vm: 'vm' };
var executeIn = data.type ? (executeInMap[data.type.toLowerCase()] || data.type.toLowerCase()) : null;
// github: extract owner/repo from full GitHub URL
var githubField = null;
var projectUrl = data.github || null;
if (data.github) {
var ghMatch = data.github.match(/github\.com\/([^/]+\/[^/?#]+)/);
if (ghMatch) githubField = ghMatch[1].replace(/\.git$/, '');
}
// last_update_commit: last commit touching the actual script files (ct/slug.sh, install/slug-install.sh, vm/slug.sh, etc.)
var lastCommit = null;
try {
var cp = require('child_process');
var scriptFiles = [];
// primary script from install_methods[].script (e.g. "ct/teleport.sh", "vm/teleport.sh")
(data.install_methods || []).forEach(function(im) {
if (im.script) scriptFiles.push(im.script);
});
// derive install script from slug (install/slug-install.sh)
scriptFiles.push('install/' + data.slug + '-install.sh');
// filter to only files that actually exist in git
var existingFiles = scriptFiles.filter(function(f) {
try { cp.execSync('git ls-files --error-unmatch ' + f, { stdio: 'ignore' }); return true; } catch(e) { return false; }
});
if (existingFiles.length > 0) {
lastCommit = cp.execSync('git log -1 --format=%H -- ' + existingFiles.join(' ')).toString().trim() || null;
}
} catch(e) { console.warn('Could not get last commit:', e.message); }
var payload = {
name: data.name,
slug: data.slug,
script_created: data.date_created || data.script_created,
script_updated: data.date_created || data.script_updated,
script_updated: new Date().toISOString().split('T')[0],
updateable: data.updateable,
privileged: data.privileged,
port: data.interface_port != null ? data.interface_port : data.port,
@@ -163,10 +248,16 @@ jobs:
logo: data.logo,
description: data.description,
config_path: data.config_path,
default_user: (data.default_credentials && data.default_credentials.username) || data.default_user,
default_passwd: (data.default_credentials && data.default_credentials.password) || data.default_passwd,
default_user: (data.default_credentials && data.default_credentials.username) || data.default_user || null,
default_passwd: (data.default_credentials && data.default_credentials.password) || data.default_passwd || null,
notes_json: JSON.stringify(data.notes || []),
install_methods_json: JSON.stringify(data.install_methods || []),
is_dev: true
};
if (executeIn) payload.execute_in = executeIn;
if (githubField) payload.github = githubField;
if (projectUrl) payload.project_url = projectUrl;
if (lastCommit) payload.last_update_commit = lastCommit;
var resolvedType = typeValueToId[data.type];
if (resolvedType == null && data.type === 'ct') resolvedType = typeValueToId['lxc'];
if (resolvedType) payload.type = resolvedType;
@@ -185,23 +276,27 @@ jobs:
var noteIds = [];
for (var i = 0; i < (data.notes || []).length; i++) {
var note = data.notes[i];
var typeId = noteTypeToId[note.type];
if (typeId == null) continue;
var typeId = noteTypeToId[note.type] || (note.type && noteTypeToId[note.type.toLowerCase()]);
if (typeId == null) {
console.warn('Note type not in z_ref_note_types:', note.type);
continue;
}
var postRes = await request(notesCollUrl, {
method: 'POST',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify({ text: note.text || '', type: typeId })
body: JSON.stringify({ text: note.text || '', type: typeId, script: scriptId })
});
if (postRes.ok) noteIds.push(JSON.parse(postRes.body).id);
else console.error('script_notes POST failed:', postRes.statusCode, postRes.body);
}
var installMethodIds = [];
for (var j = 0; j < (data.install_methods || []).length; j++) {
var im = data.install_methods[j];
var typeId = installMethodTypeToId[im.type];
var typeId = installMethodTypeToId[im.type] || (im.type && installMethodTypeToId[im.type.toLowerCase()]);
var res = im.resources || {};
var osId = osToId[res.os];
var osId = osToId[res.os] || (res.os && osToId[res.os.toLowerCase()]);
var osVersionKey = (res.os != null && res.version != null) ? res.os + '|' + res.version : null;
var osVersionId = osVersionKey ? osVersionToId[osVersionKey] : null;
var osVersionId = osVersionKey ? (osVersionToId[osVersionKey] || osVersionToId[res.os.toLowerCase() + '|' + res.version]) : null;
var imBody = {
script: scriptId,
resources_cpu: res.cpu != null ? res.cpu : 0,
@@ -217,6 +312,7 @@ jobs:
body: JSON.stringify(imBody)
});
if (imPostRes.ok) installMethodIds.push(JSON.parse(imPostRes.body).id);
else console.error('script_install_methods POST failed:', imPostRes.statusCode, imPostRes.body);
}
return { noteIds: noteIds, installMethodIds: installMethodIds };
}
@@ -225,6 +321,7 @@ jobs:
payload.notes = resolved.noteIds;
payload.install_methods = resolved.installMethodIds;
console.log('Updating', file, '(slug=' + data.slug + ')');
console.log('Created', resolved.noteIds.length, 'notes,', resolved.installMethodIds.length, 'install_methods for slug=' + data.slug);
const r = await request(recordsUrl + '/' + existingId, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
@@ -241,12 +338,19 @@ jobs:
if (!r.ok) throw new Error('POST failed: ' + r.body);
var scriptId = JSON.parse(r.body).id;
var resolved = await resolveNotesAndInstallMethods(scriptId);
console.log('Created', resolved.noteIds.length, 'notes,', resolved.installMethodIds.length, 'install_methods for slug=' + data.slug);
var patchPayload = {};
for (var k in payload) patchPayload[k] = payload[k];
patchPayload.notes = resolved.noteIds;
patchPayload.install_methods = resolved.installMethodIds;
var patchRes = await request(recordsUrl + '/' + scriptId, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify({ install_methods: resolved.installMethodIds, notes: resolved.noteIds })
body: JSON.stringify(patchPayload)
});
if (!patchRes.ok) throw new Error('PATCH relations failed: ' + patchRes.body);
var patched = JSON.parse(patchRes.body);
console.log('Script linked: notes=' + (patched.notes && patched.notes.length) + ', install_methods=' + (patched.install_methods && patched.install_methods.length));
}
}
console.log('Done.');

View File

@@ -1,7 +1,7 @@
#!/bin/bash
INPUT_FILE=".github/workflows/scripts/repos.txt"
OUTPUT_FILE="frontend/public/json/versions.json"
OUTPUT_FILE="json/versions.json"
TMP_FILE="releases_tmp.json"
if [ -f "$OUTPUT_FILE" ]; then

83
.github/workflows/stale_pr_close.yml generated vendored
View File

@@ -9,7 +9,7 @@ on:
jobs:
stale-prs:
runs-on: ubuntu-latest
runs-on: self-hosted
permissions:
pull-requests: write
issues: write
@@ -22,7 +22,7 @@ jobs:
const now = new Date();
const owner = context.repo.owner;
const repo = context.repo.repo;
// --- When stale label is added, comment immediately ---
if (context.eventName === "pull_request_target" && context.payload.action === "labeled") {
const label = context.payload.label?.name;
@@ -37,19 +37,74 @@ jobs:
}
return;
}
// --- Scheduled run: check all stale PRs ---
// --- Scheduled run: fetch all open PRs ---
const { data: prs } = await github.rest.pulls.list({
owner,
repo,
state: "open",
per_page: 100
});
for (const pr of prs) {
const hasStale = pr.labels.some(l => l.name === "stale");
if (!hasStale) continue;
const labels = pr.labels.map(l => l.name);
const hasStale = labels.includes("stale");
const hasKeepOpen = labels.includes("keep-open");
// -------------------------------------------------------
// NEW: Auto-label PRs with no activity in the last 14 days
// -------------------------------------------------------
if (!hasStale && !hasKeepOpen) {
// Find the most recent commit date
const { data: commits } = await github.rest.pulls.listCommits({
owner,
repo,
pull_number: pr.number
});
const lastCommitDate = commits.length > 0
? new Date(commits[commits.length - 1].commit.author.date)
: new Date(pr.created_at);
// Find the most recent non-bot comment date
const { data: comments } = await github.rest.issues.listComments({
owner,
repo,
issue_number: pr.number,
per_page: 100
});
const humanComments = comments.filter(c => c.user?.type !== "Bot");
const lastCommentDate = humanComments.length > 0
? new Date(humanComments[humanComments.length - 1].created_at)
: null;
// Most recent activity across commits and comments
const lastActivityDate = lastCommentDate && lastCommentDate > lastCommitDate
? lastCommentDate
: lastCommitDate;
const daysSinceActivity = (now - lastActivityDate) / (1000 * 60 * 60 * 24);
if (daysSinceActivity > 14) {
await github.rest.issues.addLabels({
owner,
repo,
issue_number: pr.number,
labels: ["stale"]
});
// The pull_request_target labeled event will fire the comment automatically.
// Skip further processing for this PR in this run.
continue;
}
// Not stale, nothing else to do for this PR.
continue;
}
// -------------------------------------------------------
// EXISTING: Manage already-stale PRs
// -------------------------------------------------------
if (!hasStale) continue; // has keep-open but not stale — skip
// Get timeline events to find when stale label was added
const { data: events } = await github.rest.issues.listEvents({
owner,
@@ -57,27 +112,27 @@ jobs:
issue_number: pr.number,
per_page: 100
});
// Find the most recent time the stale label was added
const staleLabelEvents = events
.filter(e => e.event === "labeled" && e.label?.name === "stale")
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
if (staleLabelEvents.length === 0) continue;
const staleLabelDate = new Date(staleLabelEvents[0].created_at);
const daysSinceStale = (now - staleLabelDate) / (1000 * 60 * 60 * 24);
// Check for new commits since stale label was added
const { data: commits } = await github.rest.pulls.listCommits({
owner,
repo,
pull_number: pr.number
});
const lastCommitDate = new Date(commits[commits.length - 1].commit.author.date);
const author = pr.user.login;
// If there are new commits after the stale label, remove it
if (lastCommitDate > staleLabelDate) {
await github.rest.issues.removeLabel({

41
.github/workflows/trigger_github_pages_redirect.yml generated vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Pages Redirect
on:
workflow_dispatch:
permissions:
pages: write
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create redirect page
run: |
mkdir site
cat <<EOF > site/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=https://community-scripts.org/">
<link rel="canonical" href="https://community-scripts.org/">
<title>Redirecting...</title>
</head>
<body>
Redirecting...
</body>
</html>
EOF
- uses: actions/upload-pages-artifact@v3
with:
path: site
- name: Deploy
uses: actions/deploy-pages@v4

89
.github/workflows/unmet-pr-close.yml generated vendored Normal file
View File

@@ -0,0 +1,89 @@
name: PR Script Requirements Check
on:
pull_request:
types: [opened, edited, synchronize]
permissions:
pull-requests: write
contents: read
jobs:
validate-script-requirements:
runs-on: ubuntu-latest
steps:
- name: Validate new script requirements
uses: actions/github-script@v7
with:
script: |
const body = context.payload.pull_request.body || "";
const lines = body.split("\n");
function checkboxChecked(line) {
return /\[\s*x\s*\]/i.test(line);
}
function findLine(text) {
return lines.find(l => l.includes(text));
}
// detect if "New script" is checked
const newScriptLine = findLine("🆕 **New script**");
if (!newScriptLine || !checkboxChecked(newScriptLine)) {
console.log("Not a new script PR — skipping requirement check.");
return;
}
const requirements = [
"The application is **at least 6 months old**",
"The application is **actively maintained**",
"The application has **600+ GitHub stars**",
"Official **release tarballs** are published",
"I understand that not all scripts will be accepted"
];
const missing = [];
for (const req of requirements) {
const line = findLine(req);
if (!line || !checkboxChecked(line)) {
missing.push(req);
}
}
if (missing.length > 0) {
let list = "";
for (const m of missing) {
list += "- " + m + "\n";
}
const message =
"❌ **Pull Request Closed Application Requirements Not Met**\n\n" +
"This pull request is marked as **🆕 New script**, but the required application criteria were not confirmed.\n\n" +
"The following requirement confirmations are missing:\n\n" +
list +
"\nNew application submissions must meet the project requirements before being considered.\n" +
"Please wait until the application satisfies the criteria before submitting a new PR.\n\n" +
"---\n\n" +
"⚠ **Maintainer note**\n\n" +
"The team periodically reviews closed submissions. If a project is still considered valuable to the ecosystem, maintainers may reopen the PR even if it does not fully meet the thresholds.\n\n" +
"**Please do not ping or repeatedly contact maintainers to reopen PRs.**";
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: message
});
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
state: "closed"
});
core.setFailed("Application requirements checklist incomplete.");
}

View File

@@ -1,218 +0,0 @@
name: Update GitHub Versions (New)
on:
workflow_dispatch:
schedule:
# Runs 4x daily: 00:00, 06:00, 12:00, 18:00 UTC
- cron: "0 0,6,12,18 * * *"
permissions:
contents: write
pull-requests: write
env:
VERSIONS_FILE: frontend/public/json/github-versions.json
jobs:
update-github-versions:
if: github.repository == 'community-scripts/ProxmoxVED'
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
ref: main
- name: Extract GitHub versions from install scripts
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
echo "========================================="
echo " Extracting GitHub versions from scripts"
echo "========================================="
# Initialize versions array
versions_json="[]"
# Function to add a version entry
add_version() {
local slug="$1"
local repo="$2"
local version="$3"
local pinned="$4"
local date="$5"
versions_json=$(echo "$versions_json" | jq \
--arg slug "$slug" \
--arg repo "$repo" \
--arg version "$version" \
--argjson pinned "$pinned" \
--arg date "$date" \
'. += [{"slug": $slug, "repo": $repo, "version": $version, "pinned": $pinned, "date": $date}]')
}
# Get list of slugs from JSON files
echo ""
echo "=== Scanning JSON files for slugs ==="
for json_file in frontend/public/json/*.json; do
[[ ! -f "$json_file" ]] && continue
# Skip non-app JSON files
basename_file=$(basename "$json_file")
case "$basename_file" in
metadata.json|versions.json|github-versions.json|dependency-check.json|update-apps.json)
continue
;;
esac
# Extract slug from JSON
slug=$(jq -r '.slug // empty' "$json_file" 2>/dev/null)
[[ -z "$slug" ]] && continue
# Find corresponding install script
install_script="install/${slug}-install.sh"
[[ ! -f "$install_script" ]] && continue
# Look for fetch_and_deploy_gh_release calls
# Pattern: fetch_and_deploy_gh_release "app" "owner/repo" ["mode"] ["version"]
while IFS= read -r line; do
# Skip commented lines
[[ "$line" =~ ^[[:space:]]*# ]] && continue
# Extract repo and version from fetch_and_deploy_gh_release
if [[ "$line" =~ fetch_and_deploy_gh_release[[:space:]]+\"[^\"]*\"[[:space:]]+\"([^\"]+)\"([[:space:]]+\"([^\"]+)\")?([[:space:]]+\"([^\"]+)\")? ]]; then
repo="${BASH_REMATCH[1]}"
mode="${BASH_REMATCH[3]:-tarball}"
pinned_version="${BASH_REMATCH[5]:-latest}"
# Check if version is pinned (not "latest" and not empty)
is_pinned=false
target_version=""
if [[ -n "$pinned_version" && "$pinned_version" != "latest" ]]; then
is_pinned=true
target_version="$pinned_version"
fi
# Fetch version from GitHub
if [[ "$is_pinned" == "true" ]]; then
# For pinned versions, verify it exists and get date
response=$(gh api "repos/${repo}/releases/tags/${target_version}" 2>/dev/null || echo '{}')
if echo "$response" | jq -e '.tag_name' > /dev/null 2>&1; then
version=$(echo "$response" | jq -r '.tag_name')
date=$(echo "$response" | jq -r '.published_at // empty')
add_version "$slug" "$repo" "$version" "true" "$date"
echo "[$slug] ✓ $version (pinned)"
else
echo "[$slug] ⚠ pinned version $target_version not found"
fi
else
# Fetch latest release
response=$(gh api "repos/${repo}/releases/latest" 2>/dev/null || echo '{}')
if echo "$response" | jq -e '.tag_name' > /dev/null 2>&1; then
version=$(echo "$response" | jq -r '.tag_name')
date=$(echo "$response" | jq -r '.published_at // empty')
add_version "$slug" "$repo" "$version" "false" "$date"
echo "[$slug] ✓ $version"
else
# Try tags as fallback
version=$(gh api "repos/${repo}/tags" --jq '.[0].name // empty' 2>/dev/null || echo "")
if [[ -n "$version" ]]; then
add_version "$slug" "$repo" "$version" "false" ""
echo "[$slug] ✓ $version (from tags)"
else
echo "[$slug] ⚠ no version found"
fi
fi
fi
break # Only first match per script
fi
done < <(grep 'fetch_and_deploy_gh_release' "$install_script" 2>/dev/null || true)
done
# Save versions file
echo "$versions_json" | jq --arg date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'{generated: $date, versions: (. | sort_by(.slug))}' > "$VERSIONS_FILE"
total=$(echo "$versions_json" | jq 'length')
echo ""
echo "========================================="
echo " Total versions extracted: $total"
echo "========================================="
- name: Check for changes
id: check-changes
run: |
# Check if file is new (untracked) or has changes
if [[ ! -f "$VERSIONS_FILE" ]]; then
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "Versions file was not created"
elif ! git ls-files --error-unmatch "$VERSIONS_FILE" &>/dev/null; then
# File exists but is not tracked - it's new
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "New file created: $VERSIONS_FILE"
elif git diff --quiet "$VERSIONS_FILE" 2>/dev/null; then
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "No changes detected"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "Changes detected:"
git diff --stat "$VERSIONS_FILE" 2>/dev/null || true
fi
- name: Create Pull Request
if: steps.check-changes.outputs.changed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
BRANCH_NAME="automated/update-github-versions-$(date +%Y%m%d)"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "GitHub Actions[bot]"
# Check if branch exists and delete it
git push origin --delete "$BRANCH_NAME" 2>/dev/null || true
git checkout -b "$BRANCH_NAME"
git add "$VERSIONS_FILE"
git commit -m "chore: update github-versions.json
Total versions: $(jq '.versions | length' "$VERSIONS_FILE")
Pinned versions: $(jq '[.versions[] | select(.pinned == true)] | length' "$VERSIONS_FILE")
Generated: $(jq -r '.generated' "$VERSIONS_FILE")"
git push origin "$BRANCH_NAME" --force
# Check if PR already exists
existing_pr=$(gh pr list --head "$BRANCH_NAME" --state open --json number --jq '.[0].number // empty')
if [[ -n "$existing_pr" ]]; then
echo "PR #$existing_pr already exists, updating..."
else
gh pr create \
--title "[Automated] Update GitHub versions" \
--body "This PR updates version information from GitHub releases.
## How it works
1. Scans all JSON files in \`frontend/public/json/\` for slugs
2. Finds corresponding \`install/{slug}-install.sh\` scripts
3. Extracts \`fetch_and_deploy_gh_release\` calls
4. Fetches latest (or pinned) version from GitHub
## Stats
- Total versions: $(jq '.versions | length' "$VERSIONS_FILE")
- Pinned versions: $(jq '[.versions[] | select(.pinned == true)] | length' "$VERSIONS_FILE")
- Latest versions: $(jq '[.versions[] | select(.pinned == false)] | length' "$VERSIONS_FILE")
---
*Automatically generated from install scripts*" \
--base main \
--head "$BRANCH_NAME" \
--label "automated pr"
fi

175
.github/workflows/update-timestamp-on-db.yml generated vendored Normal file
View File

@@ -0,0 +1,175 @@
name: Update script timestamp on .sh changes
on:
push:
branches:
- main
paths:
- "ct/**/*.sh"
- "install/**/*.sh"
- "tools/**/*.sh"
- "turnkey/**/*.sh"
- "vm/**/*.sh"
jobs:
update-script-timestamp:
runs-on: self-hosted
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed .sh files and derive slugs
id: slugs
run: |
changed=$(git diff --name-only "${{ github.event.before }}" "${{ github.event.after }}" -- ct/ install/ tools/ turnkey/ vm/ | grep '\.sh$' || true)
if [[ -z "$changed" ]]; then
echo "No .sh files changed in ct/, install/, tools/, turnkey/, or vm/."
echo "count=0" >> "$GITHUB_OUTPUT"
exit 0
fi
declare -A seen
slugs=""
for f in $changed; do
[[ -f "$f" ]] || continue
base="${f##*/}"
base="${base%.sh}"
if [[ "$f" == install/* && "$base" == *-install ]]; then
slug="${base%-install}"
else
slug="$base"
fi
if [[ -z "${seen[$slug]:-}" ]]; then
seen[$slug]=1
slugs="$slugs $slug"
fi
done
slugs=$(echo $slugs | xargs -n1 | sort -u)
if [[ -z "$slugs" ]]; then
echo "No slugs to update."
echo "count=0" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "$slugs" > changed_slugs.txt
echo "count=$(echo "$slugs" | wc -w)" >> "$GITHUB_OUTPUT"
- name: Parse PR number from merge commit
id: pr
run: |
re='#([0-9]+)'
if [[ "$COMMIT_MSG" =~ $re ]]; then
echo "number=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT"
else
echo "number=" >> "$GITHUB_OUTPUT"
fi
env:
COMMIT_MSG: ${{ github.event.head_commit.message }}
- name: Update script timestamps in PocketBase
if: steps.slugs.outputs.count != '0'
env:
POCKETBASE_URL: ${{ secrets.POCKETBASE_URL }}
POCKETBASE_COLLECTION: ${{ secrets.POCKETBASE_COLLECTION }}
POCKETBASE_ADMIN_EMAIL: ${{ secrets.POCKETBASE_ADMIN_EMAIL }}
POCKETBASE_ADMIN_PASSWORD: ${{ secrets.POCKETBASE_ADMIN_PASSWORD }}
COMMIT_URL: ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}
PR_URL: ${{ steps.pr.outputs.number != '' && format('{0}/{1}/pull/{2}', github.server_url, github.repository, steps.pr.outputs.number) || '' }}
run: |
node << 'ENDSCRIPT'
(async function() {
const fs = require('fs');
const https = require('https');
const http = require('http');
const url = require('url');
function request(fullUrl, opts, redirectCount) {
redirectCount = redirectCount || 0;
return new Promise(function(resolve, reject) {
const u = url.parse(fullUrl);
const isHttps = u.protocol === 'https:';
const body = opts.body;
const options = {
hostname: u.hostname,
port: u.port || (isHttps ? 443 : 80),
path: u.path,
method: opts.method || 'GET',
headers: opts.headers || {}
};
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
const lib = isHttps ? https : http;
const req = lib.request(options, function(res) {
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
if (redirectCount >= 5) return reject(new Error('Too many redirects from ' + fullUrl));
const redirectUrl = url.resolve(fullUrl, res.headers.location);
res.resume();
resolve(request(redirectUrl, opts, redirectCount + 1));
return;
}
let data = '';
res.on('data', function(chunk) { data += chunk; });
res.on('end', function() {
resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, statusCode: res.statusCode, body: data });
});
});
req.on('error', reject);
if (body) req.write(body);
req.end();
});
}
const raw = process.env.POCKETBASE_URL.replace(/\/$/, '');
const apiBase = /\/api$/i.test(raw) ? raw : raw + '/api';
const coll = process.env.POCKETBASE_COLLECTION;
const slugsText = fs.readFileSync('changed_slugs.txt', 'utf8').trim();
const slugs = slugsText ? slugsText.split(/\s+/).filter(Boolean) : [];
if (slugs.length === 0) {
console.log('No slugs to update.');
return;
}
const authUrl = apiBase + '/collections/users/auth-with-password';
const authBody = JSON.stringify({
identity: process.env.POCKETBASE_ADMIN_EMAIL,
password: process.env.POCKETBASE_ADMIN_PASSWORD
});
const authRes = await request(authUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: authBody
});
if (!authRes.ok) {
throw new Error('Auth failed: ' + authRes.body);
}
const token = JSON.parse(authRes.body).token;
const recordsUrl = apiBase + '/collections/' + encodeURIComponent(coll) + '/records';
for (const slug of slugs) {
const filter = "(slug='" + slug.replace(/'/g, "''") + "')";
const listRes = await request(recordsUrl + '?filter=' + encodeURIComponent(filter) + '&perPage=1', {
headers: { 'Authorization': token }
});
const list = JSON.parse(listRes.body);
const record = list.items && list.items[0];
if (!record) {
console.log('Slug not in DB, skipping: ' + slug);
continue;
}
const patchRes = await request(recordsUrl + '/' + record.id, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify({
name: record.name || record.slug,
last_update_commit: process.env.PR_URL || process.env.COMMIT_URL || ''
})
});
if (!patchRes.ok) {
console.warn('PATCH failed for slug ' + slug + ': ' + patchRes.body);
continue;
}
console.log('Updated timestamp for slug: ' + slug);
}
console.log('Done.');
})().catch(e => { console.error(e); process.exit(1); });
ENDSCRIPT
shell: bash

View File

@@ -1,50 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: cobalt (cobaltgit)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://ntfy.sh/
APP="Alpine-ntfy"
var_tags="${var_tags:-notification}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-256}"
var_disk="${var_disk:-2}"
var_os="${var_os:-alpine}"
var_version="${var_version:-3.22}"
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 /etc/ntfy ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating ntfy LXC"
$STD apk -U upgrade
setcap 'cap_net_bind_service=+ep' /usr/bin/ntfy
msg_ok "Updated ntfy LXC"
msg_info "Restarting ntfy"
rc-service ntfy restart
msg_ok "Restarted ntfy"
msg_ok "Updated successfully!"
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"

View File

@@ -1,67 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://anytype.io
APP="Anytype-Server"
var_tags="${var_tags:-notes;productivity;sync}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-16}"
var_os="${var_os:-ubuntu}"
var_version="${var_version:-24.04}"
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 /opt/anytype/any-sync-bundle ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "anytype" "grishy/any-sync-bundle"; then
msg_info "Stopping Service"
systemctl stop anytype
msg_ok "Stopped Service"
msg_info "Backing up Data"
cp -r /opt/anytype/data /opt/anytype_data_backup
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "anytype" "grishy/any-sync-bundle" "prebuild" "latest" "/opt/anytype" "any-sync-bundle_*_linux_amd64.tar.gz"
chmod +x /opt/anytype/any-sync-bundle
msg_info "Restoring Data"
cp -r /opt/anytype_data_backup/. /opt/anytype/data
rm -rf /opt/anytype_data_backup
msg_ok "Restored Data"
msg_info "Starting Service"
systemctl start anytype
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}:33010${CL}"
echo -e "${INFO}${YW} Client config file:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}/opt/anytype/data/client-config.yml${CL}"

73
ct/arm.sh Normal file
View File

@@ -0,0 +1,73 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/automatic-ripping-machine/automatic-ripping-machine
APP="ARM"
var_tags="${var_tags:-media;ripping;automation}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-16}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-0}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/arm ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "arm" "automatic-ripping-machine/automatic-ripping-machine"; then
msg_info "Stopping Service"
systemctl stop armui
msg_ok "Stopped Service"
msg_info "Backing up Data"
cp /opt/arm/arm.yaml /opt/arm_yaml.bak
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "arm" "automatic-ripping-machine/automatic-ripping-machine" "tarball"
msg_info "Rebuilding Python Environment"
cd /opt/arm
$STD uv venv /opt/arm/venv
$STD uv pip install --python /opt/arm/venv/bin/python \
-r <(curl -fsSL https://raw.githubusercontent.com/automatic-ripping-machine/arm-dependencies/main/requirements.txt) \
-r requirements.txt
msg_ok "Rebuilt Python Environment"
msg_info "Restoring Data"
cp /opt/arm_yaml.bak /opt/arm/arm.yaml
chmod +x /opt/arm/scripts/thickclient/*.sh 2>/dev/null || true
rm -f /opt/arm_yaml.bak
msg_ok "Restored Data"
msg_info "Starting Service"
systemctl start armui
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}:8080${CL}"

41
ct/arm/adguard.sh Normal file
View File

@@ -0,0 +1,41 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/asylumexp/Proxmox/raw/main/LICENSE
# Source: https://adguard.com/
APP="Adguard"
var_tags="${var_tags:-adblock}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-2}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/AdGuardHome ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Adguard Home can only be updated via the user interface."
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}:3000${CL}"

70
ct/arm/bazarr.sh Normal file
View File

@@ -0,0 +1,70 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/asylumexp/Proxmox/raw/main/LICENSE
# Source: https://www.bazarr.media/
APP="Bazarr"
var_tags="${var_tags:-arr}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /var/lib/bazarr/ ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "bazarr" "morpheus65535/bazarr"; then
apt-get install -y libicu76 &>/dev/null
msg_info "Stopping Service"
systemctl stop bazarr
msg_ok "Stopped Service"
PYTHON_VERSION="3.12" setup_uv
fetch_and_deploy_gh_release "bazarr" "morpheus65535/bazarr" "prebuild" "latest" "/opt/bazarr" "bazarr.zip"
msg_info "Setup Bazarr"
mkdir -p /var/lib/bazarr/
chmod 775 /opt/bazarr /var/lib/bazarr/
# Always ensure venv exists
if [[ ! -d /opt/bazarr/venv/ ]]; then
$STD uv venv --clear /opt/bazarr/venv --python 3.12
fi
# Always check and fix service file if needed
if [[ -f /etc/systemd/system/bazarr.service ]] && grep -q "ExecStart=/usr/bin/python3" /etc/systemd/system/bazarr.service; then
sed -i "s|ExecStart=/usr/bin/python3 /opt/bazarr/bazarr.py|ExecStart=/opt/bazarr/venv/bin/python3 /opt/bazarr/bazarr.py|g" /etc/systemd/system/bazarr.service
systemctl daemon-reload
fi
sed -i.bak 's/--only-binary=Pillow//g' /opt/bazarr/requirements.txt
$STD uv pip install -r /opt/bazarr/requirements.txt --python /opt/bazarr/venv/bin/python3
msg_ok "Setup Bazarr"
msg_info "Starting Service"
systemctl start bazarr
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}:6767${CL}"

62
ct/arm/bentopdf.sh Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/asylumexp/Proxmox/raw/main/LICENSE
# Source: https://github.com/alam00000/bentopdf
APP="BentoPDF"
var_tags="${var_tags:-pdf-editor}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/bentopdf ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
NODE_VERSION="24" setup_nodejs
if check_for_gh_release "bentopdf" "alam00000/bentopdf"; then
msg_info "Stopping Service"
systemctl stop bentopdf
msg_ok "Stopped Service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "bentopdf" "alam00000/bentopdf" "tarball" "latest" "/opt/bentopdf"
msg_info "Updating BentoPDF"
cd /opt/bentopdf
$STD npm ci --no-audit --no-fund
export SIMPLE_MODE=true
$STD npm run build -- --mode production
msg_ok "Updated BentoPDF"
msg_info "Starting Service"
systemctl start bentopdf
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}:8080${CL}"

109
ct/arm/homeassistant.sh Normal file
View File

@@ -0,0 +1,109 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/asylumexp/Proxmox/raw/main/LICENSE
# Source: https://www.home-assistant.io/
APP="Home Assistant"
var_tags="${var_tags:-automation;smarthome}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-16}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /var/lib/docker/volumes/hass_config/_data ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
UPD=$(msg_menu "Home Assistant Update Options" \
"1" "Update ALL Containers" \
"2" "Remove ALL Unused Images" \
"3" "Install HACS" \
"4" "Install FileBrowser")
if [ "$UPD" == "1" ]; then
msg_info "Updating All Containers"
CONTAINER_LIST="${1:-$(docker ps -q)}"
for container in ${CONTAINER_LIST}; do
CONTAINER_IMAGE="$(docker inspect --format "{{.Config.Image}}" --type container "${container}")"
RUNNING_IMAGE="$(docker inspect --format "{{.Image}}" --type container "${container}")"
docker pull "${CONTAINER_IMAGE}"
LATEST_IMAGE="$(docker inspect --format "{{.Id}}" --type image "${CONTAINER_IMAGE}")"
if [[ "${RUNNING_IMAGE}" != "${LATEST_IMAGE}" ]]; then
pip install -U runlike
echo "Updating ${container} image ${CONTAINER_IMAGE}"
DOCKER_COMMAND="$(runlike --use-volume-id "${container}")"
docker rm --force "${container}"
eval "${DOCKER_COMMAND}"
fi
done
msg_ok "Updated All Containers"
exit
fi
if [ "$UPD" == "2" ]; then
msg_info "Removing ALL Unused Images"
docker image prune -af
msg_ok "Removed ALL Unused Images"
exit
fi
if [ "$UPD" == "3" ]; then
msg_info "Installing Home Assistant Community Store (HACS)"
$STD apt update
cd /var/lib/docker/volumes/hass_config/_data
$STD bash <(curl -fsSL https://get.hacs.xyz)
msg_ok "Installed Home Assistant Community Store (HACS)"
echo -e "\n Reboot Home Assistant and clear browser cache then Add HACS integration.\n"
exit
fi
if [ "$UPD" == "4" ]; then
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')
$STD curl -fsSL https://github.com/filebrowser/filebrowser/releases/download/v2.23.0/linux-arm64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin
$STD filebrowser config init -a '0.0.0.0'
$STD filebrowser config set -a '0.0.0.0'
$STD filebrowser users add admin helper-scripts.com --perm.admin
msg_ok "Installed FileBrowser"
msg_info "Creating Service"
service_path="/etc/systemd/system/filebrowser.service"
echo "[Unit]
Description=Filebrowser
After=network-online.target
[Service]
User=root
WorkingDirectory=/root/
ExecStart=/usr/local/bin/filebrowser -r /
[Install]
WantedBy=default.target" >$service_path
$STD systemctl enable --now filebrowser
msg_ok "Created Service"
msg_ok "Completed successfully!\n"
echo -e "FileBrowser should be reachable by going to the following URL.
${BL}http://$LOCAL_IP:8080${CL} admin|helper-scripts.com\n"
exit
fi
}
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}HA: http://${IP}:8123${CL}"
echo -e "${TAB}${GATEWAY}${BGN}Portainer: https://${IP}:9443${CL}"

52
ct/arm/jellyfin.sh Normal file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/asylumexp/Proxmox/raw/main/LICENSE
# Source: https://jellyfin.org/
APP="Jellyfin"
var_tags="${var_tags:-media}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-16}"
var_os="${var_os:-ubuntu}"
var_version="${var_version:-24.04}"
var_unprivileged="${var_unprivileged:-0}"
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 /usr/lib/jellyfin ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating Jellyfin"
ensure_dependencies libjemalloc2
if [[ ! -f /usr/lib/libjemalloc.so ]]; then
ln -sf /usr/lib/aarch64-linux-gnu/libjemalloc.so.2 /usr/lib/libjemalloc.so
fi
$STD apt update
$STD apt -y upgrade
$STD apt -y --with-new-pkgs upgrade jellyfin jellyfin-server
msg_ok "Updated Jellyfin"
msg_ok "Updated successfully!"
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8096${CL}"

79
ct/arm/kima-hub.sh Normal file
View File

@@ -0,0 +1,79 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/asylumexp/Proxmox/raw/main/LICENSE
# Source: https://github.com/Chevron7Locked/kima-hub
APP="Kima-Hub"
var_tags="${var_tags:-music;streaming;media}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-8192}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/kima-hub ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "kima-hub" "Chevron7Locked/kima-hub"; then
msg_info "Stopping Services"
systemctl stop kima-frontend kima-backend kima-analyzer kima-analyzer-clap
msg_ok "Stopped Services"
msg_info "Backing up Data"
cp /opt/kima-hub/backend/.env /opt/kima-hub-backend-env.bak
cp /opt/kima-hub/frontend/.env /opt/kima-hub-frontend-env.bak
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "kima-hub" "Chevron7Locked/kima-hub" "tarball"
msg_info "Restoring Data"
cp /opt/kima-hub-backend-env.bak /opt/kima-hub/backend/.env
cp /opt/kima-hub-frontend-env.bak /opt/kima-hub/frontend/.env
rm -f /opt/kima-hub-backend-env.bak /opt/kima-hub-frontend-env.bak
msg_ok "Restored Data"
msg_info "Rebuilding Backend"
cd /opt/kima-hub/backend
$STD npm install
$STD npm run build
$STD npx prisma generate
$STD npx prisma migrate deploy
msg_ok "Rebuilt Backend"
msg_info "Rebuilding Frontend"
cd /opt/kima-hub/frontend
$STD npm install
$STD npm run build
msg_ok "Rebuilt Frontend"
msg_info "Starting Services"
systemctl start kima-backend kima-frontend kima-analyzer kima-analyzer-clap
msg_ok "Started Services"
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}:3030${CL}"

74
ct/arm/lubelogger.sh Normal file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: kristocopani
# License: MIT | https://github.com/asylumexp/Proxmox/raw/main/LICENSE
# Source: https://lubelogger.com/
APP="LubeLogger"
var_tags="${var_tags:-vehicle;car}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-2}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/lubelogger.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "lubelogger" "hargata/lubelog"; then
msg_info "Stopping Service"
systemctl stop lubelogger
msg_ok "Stopped Service"
msg_info "Backing up data"
mkdir -p /tmp/lubeloggerData/data
cp /opt/lubelogger/appsettings.json /tmp/lubeloggerData/appsettings.json
cp -r /opt/lubelogger/data/ /tmp/lubeloggerData/
# Lubelogger has moved multiples folders to the 'data' folder, and we need to move them before the update to keep the user data
# Github Discussion: https://github.com/hargata/lubelog/discussions/787
[[ -e /opt/lubelogger/config ]] && cp -r /opt/lubelogger/config /tmp/lubeloggerData/data/
[[ -e /opt/lubelogger/wwwroot/translations ]] && cp -r /opt/lubelogger/wwwroot/translations /tmp/lubeloggerData/data/
[[ -e /opt/lubelogger/wwwroot/documents ]] && cp -r /opt/lubelogger/wwwroot/documents /tmp/lubeloggerData/data/
[[ -e /opt/lubelogger/wwwroot/images ]] && cp -r /opt/lubelogger/wwwroot/images /tmp/lubeloggerData/data/
[[ -e /opt/lubelogger/wwwroot/temp ]] && cp -r /opt/lubelogger/wwwroot/temp /tmp/lubeloggerData/data/
[[ -e /opt/lubelogger/log ]] && cp -r /opt/lubelogger/log /tmp/lubeloggerData/
rm -rf /opt/lubelogger
msg_ok "Backed up data"
fetch_and_deploy_gh_release "lubelogger" "hargata/lubelog" "prebuild" "latest" "/opt/lubelogger" "LubeLogger*linux_x64.zip"
msg_info "Configuring LubeLogger"
chmod 700 /opt/lubelogger/CarCareTracker
cp -rf /tmp/lubeloggerData/* /opt/lubelogger/
rm -rf /tmp/lubeloggerData
msg_ok "Configured LubeLogger"
msg_info "Starting Service"
systemctl start lubelogger
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}:5000${CL}"

47
ct/arm/pihole.sh Normal file
View File

@@ -0,0 +1,47 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/asylumexp/Proxmox/raw/main/LICENSE
# Source: https://pi-hole.net/
APP="Pihole"
var_tags="${var_tags:-adblock}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-2}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /etc/pihole ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating PiHole"
set +e
$STD apt update
$STD apt upgrade -y
/usr/local/bin/pihole -up
msg_ok "Updated PiHole"
msg_ok "Updated successfully!"
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}/admin${CL}"

63
ct/arm/rdtclient.sh Normal file
View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/asylumexp/Proxmox/raw/main/LICENSE
# Source: https://github.com/rogerfar/rdt-client
APP="RDTClient"
var_tags="${var_tags:-torrent}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/rdtc/ ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "rdt-client" "rogerfar/rdt-client"; then
msg_info "Stopping Service"
systemctl stop rdtc
msg_ok "Stopped Service"
msg_info "Creating backup"
mkdir -p /opt/rdtc-backup
cp -R /opt/rdtc/appsettings.json /opt/rdtc-backup/
msg_ok "Backup created"
fetch_and_deploy_gh_release "rdt-client" "rogerfar/rdt-client" "prebuild" "latest" "/opt/rdtc" "RealDebridClient.zip"
cp -R /opt/rdtc-backup/appsettings.json /opt/rdtc/
if dpkg-query -W dotnet-sdk-8.0 >/dev/null 2>&1; then
$STD apt remove --purge -y dotnet-sdk-8.0
ensure_dependencies aspnetcore-runtime-9.0
fi
rm -rf /opt/rdtc-backup
msg_info "Starting Service"
systemctl start rdtc
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}:6500${CL}"

119
ct/arm/vaultwarden.sh Normal file
View File

@@ -0,0 +1,119 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/asylumexp/Proxmox/raw/main/LICENSE
# Source: https://github.com/dani-garcia/vaultwarden
APP="Vaultwarden"
var_tags="${var_tags:-password-manager}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-6144}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/vaultwarden.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
VAULT=$(get_latest_github_release "dani-garcia/vaultwarden")
WVRELEASE=$(get_latest_github_release "dani-garcia/bw_web_builds")
UPD=$(msg_menu "Vaultwarden Update Options" \
"1" "Update VaultWarden + Web-Vault" \
"2" "Set Admin Token")
if [ "$UPD" == "1" ]; then
if check_for_gh_release "vaultwarden" "dani-garcia/vaultwarden"; then
msg_info "Stopping Service"
systemctl stop vaultwarden
msg_ok "Stopped Service"
fetch_and_deploy_gh_release "vaultwarden" "dani-garcia/vaultwarden" "tarball" "latest" "/tmp/vaultwarden-src"
msg_info "Updating VaultWarden to $VAULT (Patience)"
cd /tmp/vaultwarden-src
VW_VERSION="$VAULT"
export VW_VERSION
$STD cargo build --features "sqlite,mysql,postgresql" --release
if [[ -f /usr/bin/vaultwarden ]]; then
cp target/release/vaultwarden /usr/bin/
else
cp target/release/vaultwarden /opt/vaultwarden/bin/
fi
cd ~ && rm -rf /tmp/vaultwarden-src
msg_ok "Updated VaultWarden to ${VAULT}"
msg_info "Starting Service"
systemctl start vaultwarden
msg_ok "Started Service"
else
msg_ok "VaultWarden is already up-to-date"
fi
if check_for_gh_release "vaultwarden_webvault" "dani-garcia/bw_web_builds"; then
msg_info "Stopping Service"
systemctl stop vaultwarden
msg_ok "Stopped Service"
msg_info "Updating Web-Vault to $WVRELEASE"
rm -rf /opt/vaultwarden/web-vault
mkdir -p /opt/vaultwarden/web-vault
fetch_and_deploy_gh_release "vaultwarden_webvault" "dani-garcia/bw_web_builds" "prebuild" "latest" "/opt/vaultwarden/web-vault" "bw_web_*.tar.gz"
chown -R root:root /opt/vaultwarden/web-vault/
msg_ok "Updated Web-Vault to ${WVRELEASE}"
msg_info "Starting Service"
systemctl start vaultwarden
msg_ok "Started Service"
else
msg_ok "Web-Vault is already up-to-date"
fi
msg_ok "Updated successfully!"
exit
fi
if [ "$UPD" == "2" ]; then
if [[ "${PHS_SILENT:-0}" == "1" ]]; then
msg_warn "Set Admin Token requires interactive mode, skipping."
exit
fi
read -r -s -p "Set the ADMIN_TOKEN: " NEWTOKEN
echo ""
if [[ -n "$NEWTOKEN" ]]; then
ensure_dependencies argon2
TOKEN=$(echo -n "${NEWTOKEN}" | argon2 "$(openssl rand -base64 32)" -t 2 -m 16 -p 4 -l 64 -e)
sed -i "s|ADMIN_TOKEN=.*|ADMIN_TOKEN='${TOKEN}'|" /opt/vaultwarden/.env
if [[ -f /opt/vaultwarden/data/config.json ]]; then
sed -i "s|\"admin_token\":.*|\"admin_token\": \"${TOKEN}\"|" /opt/vaultwarden/data/config.json
fi
systemctl restart vaultwarden
msg_ok "Admin token updated"
fi
exit
fi
}
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}https://${IP}:8000${CL}"

View File

@@ -1,113 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/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/booklore-app/BookLore
APP="BookLore"
var_tags="${var_tags:-books;library}"
var_cpu="${var_cpu:-3}"
var_ram="${var_ram:-3072}"
var_disk="${var_disk:-7}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/booklore ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "booklore" "booklore-app/BookLore"; then
JAVA_VERSION="25" setup_java
NODE_VERSION="22" setup_nodejs
setup_mariadb
setup_yq
msg_info "Stopping Service"
systemctl stop booklore
msg_ok "Stopped Service"
if grep -qE "^BOOKLORE_(DATA_PATH|BOOKDROP_PATH|BOOKS_PATH|PORT)=" /opt/booklore_storage/.env 2>/dev/null; then
msg_info "Migrating old environment variables"
sed -i 's/^BOOKLORE_DATA_PATH=/APP_PATH_CONFIG=/g' /opt/booklore_storage/.env
sed -i 's/^BOOKLORE_BOOKDROP_PATH=/APP_BOOKDROP_FOLDER=/g' /opt/booklore_storage/.env
sed -i '/^BOOKLORE_BOOKS_PATH=/d' /opt/booklore_storage/.env
sed -i '/^BOOKLORE_PORT=/d' /opt/booklore_storage/.env
msg_ok "Migrated old environment variables"
fi
msg_info "Backing up old installation"
mv /opt/booklore /opt/booklore_bak
msg_ok "Backed up old installation"
fetch_and_deploy_gh_release "booklore" "booklore-app/BookLore" "tarball"
msg_info "Building Frontend"
cd /opt/booklore/booklore-ui
$STD npm install --force
$STD npm run build --configuration=production
msg_ok "Built Frontend"
msg_info "Embedding Frontend into Backend"
mkdir -p /opt/booklore/booklore-api/src/main/resources/static
cp -r /opt/booklore/booklore-ui/dist/booklore/browser/* /opt/booklore/booklore-api/src/main/resources/static/
msg_ok "Embedded Frontend into Backend"
msg_info "Building Backend"
cd /opt/booklore/booklore-api
APP_VERSION=$(get_latest_github_release "booklore-app/BookLore")
yq eval ".app.version = \"${APP_VERSION}\"" -i src/main/resources/application.yaml
$STD ./gradlew clean build -x test --no-daemon
mkdir -p /opt/booklore/dist
JAR_PATH=$(find /opt/booklore/booklore-api/build/libs -maxdepth 1 -type f -name "booklore-api-*.jar" ! -name "*plain*" | head -n1)
if [[ -z "$JAR_PATH" ]]; then
msg_error "Backend JAR not found"
exit
fi
cp "$JAR_PATH" /opt/booklore/dist/app.jar
msg_ok "Built Backend"
if systemctl is-active --quiet nginx 2>/dev/null; then
msg_info "Removing Nginx (no longer needed)"
systemctl disable --now nginx
$STD apt-get purge -y nginx nginx-common
msg_ok "Removed Nginx"
fi
if ! grep -q "^SERVER_PORT=" /opt/booklore_storage/.env 2>/dev/null; then
echo "SERVER_PORT=6060" >>/opt/booklore_storage/.env
fi
sed -i 's|ExecStart=/usr/bin/java -jar|ExecStart=/usr/bin/java -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -jar|' /etc/systemd/system/booklore.service
systemctl daemon-reload
msg_info "Starting Service"
systemctl start booklore
rm -rf /opt/booklore_bak
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}:6060${CL}"

View File

@@ -29,10 +29,40 @@ function update_script() {
exit
fi
msg_info "Updating Debian LXC"
$STD apt update
$STD apt upgrade -y
msg_ok "Updated Debian LXC"
if check_for_gh_release "caddymanager" "caddymanager/caddymanager"; then
msg_info "Stopping Service"
systemctl stop caddymanager-backend
systemctl stop caddymanager-frontend
msg_ok "Stopped Service"
msg_info "Backing up configuration"
cp /opt/caddymanager/caddymanager.env /opt/
cp /opt/caddymanager/caddymanager.sqlite /opt/
cp /opt/caddymanager/frontend/Caddyfile /opt/
msg_ok "Backed up configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "caddymanager" "caddymanager/caddymanager" "tarball"
msg_info "Installing CaddyManager"
cd /opt/caddymanager/backend
$STD npm install
cd /opt/caddymanager/frontend
$STD npm install
$STD npm run build
msg_ok "Installed CaddyManager"
msg_info "Restoring configuration"
mv /opt/caddymanager.env /opt/caddymanager/
mv /opt/caddymanager.sqlite /opt/caddymanager/
mv -f /opt/Caddyfile /opt/caddymanager/frontend/
msg_ok "Restored configuration"
msg_info "Starting Service"
systemctl start caddymanager-backend
systemctl start caddymanager-frontend
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
cleanup_lxc
exit
}

View File

@@ -1,46 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: mitchscobell
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://ddclient.net/
APP="ddclient"
var_tags="${var_tags:-network}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-2}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/ddclient.conf ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating ddclient"
$STD apt update
$STD apt install --only-upgrade -y ddclient
$STD systemctl restart ddclient
msg_ok "Updated ddclient"
msg_ok "Updated successfully!"
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"

View File

@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster) | Co-Author: MickLesk (Canbiz) | Co-Author: CrazyWolf13
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://homarr.dev/
APP="alpine-homarr"

View File

@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (Canbiz)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/community-scripts/ProxmoxVE
APP="Docspell"

View File

@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Nícolas Pastorello (opastorello)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/jumpserver/jumpserver
APP="JumpServer"

View File

@@ -2,7 +2,7 @@
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://petio.tv/
APP="Petio"

View File

@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://nginxproxymanager.com/
APP="Nginx Proxy Manager"

View File

@@ -53,7 +53,7 @@
"type": "info"
},
{
"text": "**Optional Full-text Search with Apache Tika**: requires your own Tika LXC. See `https://community-scripts.github.io/ProxmoxVE/scripts?id=apache-tika`",
"text": "**Optional Full-text Search with Apache Tika**: requires your own Tika LXC. See `https://community-scripts.github.io/ProxmoxVED/scripts?id=apache-tika`",
"type": "info"
},
{
@@ -61,4 +61,4 @@
"type": "info"
}
]
}
}

View File

@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source:
APP="Roundcubemail"

View File

@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (Canbiz)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source:
APP="Squirrel Servers Manager"

View File

@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2026 community-scripts ORG
# Author: SunFlowerOwl
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/haugene/docker-transmission-openvpn
APP="transmission-openvpn"

73
ct/degoog.sh Normal file
View File

@@ -0,0 +1,73 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/fccview/degoog
APP="degoog"
var_tags="${var_tags:-search;privacy;plugins}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-6}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/degoog ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "degoog" "fccview/degoog"; then
msg_info "Stopping Service"
systemctl stop degoog
msg_ok "Stopped Service"
msg_info "Backing up Configuration & Data"
[[ -f /opt/degoog/.env ]] && cp /opt/degoog/.env /opt/degoog.env.bak
[[ -d /opt/degoog/data ]] && mv /opt/degoog/data /opt/degoog_data_backup
msg_ok "Backed up Configuration & Data"
if ! command -v bun >/dev/null 2>&1; then
msg_info "Installing Bun"
export BUN_INSTALL="/root/.bun"
curl -fsSL https://bun.sh/install | $STD bash
ln -sf /root/.bun/bin/bun /usr/local/bin/bun
ln -sf /root/.bun/bin/bunx /usr/local/bin/bunx
msg_ok "Installed Bun"
fi
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "degoog" "fccview/degoog" "prebuild" "latest" "/opt/degoog" "degoog_*_prebuild.tar.gz"
msg_info "Restoring Configuration & Data"
[[ -f /opt/degoog.env.bak ]] && mv /opt/degoog.env.bak /opt/degoog/.env
[[ -d /opt/degoog_data_backup ]] && mv /opt/degoog_data_backup /opt/degoog/data
msg_ok "Restored Configuration & Data"
msg_info "Starting Service"
systemctl start degoog
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}:4444${CL}"

View File

@@ -73,5 +73,5 @@ 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}${CL}"
echo -e "${INFO}${YW} Admin Setup:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}Create the first account in the web UI (use admin@local to match developer emails)${CL}"
echo -e "${INFO}${YW} Credentials saved in:${CL}"
echo -e "${TAB}/root/discourse.creds"

View File

@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Simon Friedrich
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://forgejo.org/
APP="Forgejo-Runner"

View File

@@ -1,43 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Authors: MickLesk (CanbiZ) | Co-Author: remz1337
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://frigate.video/
APP="Frigate"
var_tags="${var_tags:-nvr}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-0}"
var_gpu="${var_gpu:-yes}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/frigate.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "To update Frigate, create a new container and transfer your configuration."
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}:5000${CL}"

69
ct/github-runner.sh Normal file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/actions/runner
APP="GitHub-Runner"
var_tags="${var_tags:-ci}"
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_unprivileged="${var_unprivileged:-1}"
var_nesting="${var_nesting:-1}"
var_keyctl="${var_keyctl:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /opt/actions-runner/run.sh ]]; then
msg_error "No ${APP} Installation Found!"
exit 1
fi
if check_for_gh_release "actions-runner" "actions/runner"; then
msg_info "Stopping Service"
systemctl stop actions-runner
msg_ok "Stopped Service"
msg_info "Backing up runner configuration"
BACKUP_DIR="/opt/actions-runner.backup"
mkdir -p "$BACKUP_DIR"
[[ -f /opt/actions-runner/.runner ]] && cp -a /opt/actions-runner/.runner "$BACKUP_DIR/"
[[ -f /opt/actions-runner/.credentials ]] && cp -a /opt/actions-runner/.credentials "$BACKUP_DIR/"
msg_ok "Backed up configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "actions-runner" "actions/runner" "prebuild" "latest" "/opt/actions-runner" "actions-runner-linux-x64-*.tar.gz"
msg_info "Restoring runner configuration"
[[ -f "$BACKUP_DIR/.runner" ]] && cp -a "$BACKUP_DIR/.runner" /opt/actions-runner/
[[ -f "$BACKUP_DIR/.credentials" ]] && cp -a "$BACKUP_DIR/.credentials" /opt/actions-runner/
rm -rf "$BACKUP_DIR"
msg_ok "Restored configuration"
msg_info "Starting Service"
systemctl start actions-runner
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} After first boot, run config.sh with your token and start the service.${CL}"

6
ct/headers/localagi Normal file
View File

@@ -0,0 +1,6 @@
__ __ ___ __________
/ / ____ ________ _/ / / | / ____/ _/
/ / / __ \/ ___/ __ `/ / / /| |/ / __ / /
/ /___/ /_/ / /__/ /_/ / / / ___ / /_/ // /
/_____/\____/\___/\__,_/_/ /_/ |_\____/___/

View File

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

View File

@@ -1,6 +0,0 @@
 ____
/ __ \____ _____ _________ _
/ /_/ / __ `/ __ \/ ___/ __ `/
/ ____/ /_/ / /_/ / / / /_/ /
/_/ \__,_/ .___/_/ \__,_/
/_/

View File

@@ -1,408 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://immich.app
APP="immich"
var_tags="${var_tags:-photos}"
var_disk="${var_disk:-20}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-6144}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
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/immich ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if [[ -f /etc/apt/sources.list.d/immich.list ]]; then
msg_error "Wrong Debian version detected!"
msg_error "You must upgrade your LXC to Debian Trixie before updating."
msg_error "Please visit https://github.com/community-scripts/ProxmoxVE/discussions/7726 for details."
echo "${TAB3} If you have upgraded your LXC to Trixie and you still see this message, please open an Issue in the Community-Scripts repo."
exit
fi
setup_uv
PNPM_VERSION="$(curl -fsSL "https://raw.githubusercontent.com/immich-app/immich/refs/heads/main/package.json" | jq -r '.packageManager | split("@")[1]')"
NODE_VERSION="24" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs
if [[ ! -f /etc/apt/preferences.d/preferences ]]; then
msg_info "Adding Debian Testing repo"
sed -i 's/ trixie-updates/ trixie-updates testing/g' /etc/apt/sources.list.d/debian.sources
cat <<EOF >/etc/apt/preferences.d/preferences
Package: *
Pin: release a=unstable
Pin-Priority: 450
Package: *
Pin:release a=testing
Pin-Priority: 450
EOF
if [[ -f /etc/apt/preferences.d/immich ]]; then
rm /etc/apt/preferences.d/immich
fi
$STD apt update
msg_ok "Added Debian Testing repo"
fi
if ! dpkg -l "libmimalloc3" | grep -q '3.1' || ! dpkg -l "libde265-dev" | grep -q '1.0.16'; then
msg_info "Installing/upgrading Testing repo packages"
$STD apt install -t testing libmimalloc3 libde265-dev -y
msg_ok "Installed/upgraded Testing repo packages"
fi
if [[ ! -f /etc/apt/sources.list.d/mise.list ]]; then
msg_info "Installing Mise"
curl -fSs https://mise.jdx.dev/gpg-key.pub | tee /etc/apt/keyrings/mise-archive-keyring.pub 1>/dev/null
echo "deb [signed-by=/etc/apt/keyrings/mise-archive-keyring.pub arch=amd64] https://mise.jdx.dev/deb stable main" >/etc/apt/sources.list.d/mise.list
$STD apt update
$STD apt install -y mise
msg_ok "Installed Mise"
fi
STAGING_DIR=/opt/staging
BASE_DIR=${STAGING_DIR}/base-images
SOURCE_DIR=${STAGING_DIR}/image-source
cd /tmp
if [[ -f ~/.intel_version ]]; then
curl -fsSLO https://raw.githubusercontent.com/immich-app/base-images/refs/heads/main/server/Dockerfile
readarray -t INTEL_URLS < <(
sed -n "/intel-[igc|opencl]/p" ./Dockerfile | awk '{print $2}'
sed -n "/libigdgmm12/p" ./Dockerfile | awk '{print $3}'
)
INTEL_RELEASE="$(grep "intel-opencl-icd_" ./Dockerfile | awk -F '_' '{print $2}')"
if [[ "$INTEL_RELEASE" != "$(cat ~/.intel_version)" ]]; then
msg_info "Updating Intel iGPU dependencies"
for url in "${INTEL_URLS[@]}"; do
curl -fsSLO "$url"
done
$STD apt-mark unhold libigdgmm12
$STD apt install -y ./libigdgmm12*.deb
rm ./libigdgmm12*.deb
$STD apt install -y ./*.deb
rm ./*.deb
$STD apt-mark hold libigdgmm12
dpkg-query -W -f='${Version}\n' intel-opencl-icd >~/.intel_version
msg_ok "Intel iGPU dependencies updated"
fi
rm ./Dockerfile
fi
if [[ -f ~/.immich_library_revisions ]]; then
libraries=("libjxl" "libheif" "libraw" "imagemagick" "libvips")
cd "$BASE_DIR"
msg_info "Checking for updates to custom image-processing libraries"
$STD git pull
for library in "${libraries[@]}"; do
compile_"$library"
done
msg_ok "Image-processing libraries up to date"
fi
RELEASE="v2.5.2"
if check_for_gh_tag "immich" "immich-app/immich" "${RELEASE}"; then
msg_info "Stopping Services"
systemctl stop immich-web
systemctl stop immich-ml
msg_ok "Stopped Services"
VCHORD_RELEASE="0.5.3"
if [[ ! -f ~/.vchord_version ]] || [[ "$VCHORD_RELEASE" != "$(cat ~/.vchord_version)" ]]; then
msg_info "Upgrading VectorChord"
curl -fsSL "https://github.com/tensorchord/vectorchord/releases/download/${VCHORD_RELEASE}/postgresql-16-vchord_${VCHORD_RELEASE}-1_amd64.deb" -o vchord.deb
$STD apt install -y ./vchord.deb
systemctl restart postgresql
$STD sudo -u postgres psql -d immich -c "ALTER EXTENSION vector UPDATE;"
$STD sudo -u postgres psql -d immich -c "ALTER EXTENSION vchord UPDATE;"
$STD sudo -u postgres psql -d immich -c "REINDEX INDEX face_index;"
$STD sudo -u postgres psql -d immich -c "REINDEX INDEX clip_index;"
echo "$VCHORD_RELEASE" >~/.vchord_version
rm ./vchord.deb
msg_ok "Upgraded VectorChord to v${VCHORD_RELEASE}"
fi
if ! dpkg -l | grep -q ccache; then
$STD apt install -yqq ccache
fi
INSTALL_DIR="/opt/${APP}"
UPLOAD_DIR="$(sed -n '/^IMMICH_MEDIA_LOCATION/s/[^=]*=//p' /opt/immich/.env)"
SRC_DIR="${INSTALL_DIR}/source"
APP_DIR="${INSTALL_DIR}/app"
PLUGIN_DIR="${APP_DIR}/corePlugin"
ML_DIR="${APP_DIR}/machine-learning"
GEO_DIR="${INSTALL_DIR}/geodata"
cp "$ML_DIR"/ml_start.sh "$INSTALL_DIR"
if grep -qs "set -a" "$APP_DIR"/bin/start.sh; then
cp "$APP_DIR"/bin/start.sh "$INSTALL_DIR"
else
cat <<EOF >"$INSTALL_DIR"/start.sh
#!/usr/bin/env bash
set -a
. ${INSTALL_DIR}/.env
set +a
/usr/bin/node ${APP_DIR}/dist/main.js "\$@"
EOF
chmod +x "$INSTALL_DIR"/start.sh
fi
(
shopt -s dotglob
rm -rf "${APP_DIR:?}"/*
)
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "immich" "immich-app/immich" "tag" "${RELEASE}" "$SRC_DIR"
msg_info "Updating Immich web and microservices"
cd "$SRC_DIR"/server
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
export CI=1
corepack enable
# server build
export SHARP_IGNORE_GLOBAL_LIBVIPS=true
$STD pnpm --filter immich --frozen-lockfile build
unset SHARP_IGNORE_GLOBAL_LIBVIPS
export SHARP_FORCE_GLOBAL_LIBVIPS=true
$STD pnpm --filter immich --frozen-lockfile --prod --no-optional deploy "$APP_DIR"
cp "$APP_DIR"/package.json "$APP_DIR"/bin
sed -i 's|^start|./start|' "$APP_DIR"/bin/immich-admin
# openapi & web build
cd "$SRC_DIR"
echo "packageImportMethod: hardlink" >>./pnpm-workspace.yaml
$STD pnpm --filter @immich/sdk --filter immich-web --frozen-lockfile --force install
unset SHARP_FORCE_GLOBAL_LIBVIPS
export SHARP_IGNORE_GLOBAL_LIBVIPS=true
$STD pnpm --filter @immich/sdk --filter immich-web build
cp -a web/build "$APP_DIR"/www
cp LICENSE "$APP_DIR"
# cli build
$STD pnpm --filter @immich/sdk --filter @immich/cli --frozen-lockfile install
$STD pnpm --filter @immich/sdk --filter @immich/cli build
$STD pnpm --filter @immich/cli --prod --no-optional deploy "$APP_DIR"/cli
cd "$APP_DIR"
mv "$INSTALL_DIR"/start.sh "$APP_DIR"/bin
# plugins
cd "$SRC_DIR"
$STD mise trust --ignore ./mise.toml
$STD mise trust ./plugins/mise.toml
cd plugins
$STD mise install
$STD mise run build
mkdir -p "$PLUGIN_DIR"
cp -r ./dist "$PLUGIN_DIR"/dist
cp ./manifest.json "$PLUGIN_DIR"
msg_ok "Updated Immich server, web, cli and plugins"
cd "$SRC_DIR"/machine-learning
mkdir -p "$ML_DIR" && chown -R immich:immich "$ML_DIR"
chown immich:immich ./uv.lock
export VIRTUAL_ENV="${ML_DIR}"/ml-venv
if [[ -f ~/.openvino ]]; then
msg_info "Updating HW-accelerated machine-learning"
# Remove old venv if Python version changed (3.12 -> 3.13)
if [[ -d "${VIRTUAL_ENV}" ]] && ! "${VIRTUAL_ENV}/bin/python3" --version 2>/dev/null | grep -q "3.13"; then
rm -rf "${VIRTUAL_ENV}"
fi
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv sync --extra openvino --no-dev --active --link-mode copy -n -p python3.13 --managed-python
patchelf --clear-execstack "${VIRTUAL_ENV}/lib/python3.13/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-313-x86_64-linux-gnu.so"
# Add workaround for onnxruntime-openvino 1.23.x crash if not present
if ! grep -q "MACHINE_LEARNING_OPENVINO_NUM_THREADS" "$INSTALL_DIR/.env" 2>/dev/null; then
sed -i '/MACHINE_LEARNING_CACHE_FOLDER/a ## - For OpenVINO only - workaround for onnxruntime-openvino 1.23.x crash\n## - See: https://github.com/immich-app/immich/pull/11240\nMACHINE_LEARNING_OPENVINO_NUM_THREADS=$(nproc)' "$INSTALL_DIR/.env"
fi
msg_ok "Updated HW-accelerated machine-learning"
else
msg_info "Updating machine-learning"
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv sync --extra cpu --no-dev --active --link-mode copy -n -p python3.11 --managed-python
msg_ok "Updated machine-learning"
fi
cd "$SRC_DIR"
cp -a machine-learning/{ann,immich_ml} "$ML_DIR"
mv "$INSTALL_DIR"/ml_start.sh "$ML_DIR"
if [[ -f ~/.openvino ]]; then
sed -i "/intra_op/s/int = 0/int = os.cpu_count() or 0/" "$ML_DIR"/immich_ml/config.py
fi
ln -sf "$APP_DIR"/resources "$INSTALL_DIR"
cd "$APP_DIR"
grep -rl /usr/src | xargs -n1 sed -i "s|\/usr/src|$INSTALL_DIR|g"
grep -rlE "'/build'" | xargs -n1 sed -i "s|'/build'|'$APP_DIR'|g"
sed -i "s@\"/cache\"@\"$INSTALL_DIR/cache\"@g" "$ML_DIR"/immich_ml/config.py
ln -s "${UPLOAD_DIR:-/opt/immich/upload}" "$APP_DIR"/upload
ln -s "${UPLOAD_DIR:-/opt/immich/upload}" "$ML_DIR"/upload
ln -s "$GEO_DIR" "$APP_DIR"
chown -R immich:immich "$INSTALL_DIR"
systemctl restart immich-ml immich-web
msg_ok "Updated successfully!"
fi
exit
}
function compile_libjxl() {
SOURCE=${SOURCE_DIR}/libjxl
JPEGLI_LIBJPEG_LIBRARY_SOVERSION="62"
JPEGLI_LIBJPEG_LIBRARY_VERSION="62.3.0"
: "${LIBJXL_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libjxl.json)}"
if [[ "$LIBJXL_REVISION" != "$(grep 'libjxl' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
msg_info "Recompiling libjxl"
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
$STD git clone https://github.com/libjxl/libjxl.git "$SOURCE"
cd "$SOURCE"
$STD git reset --hard "$LIBJXL_REVISION"
$STD git submodule update --init --recursive --depth 1 --recommend-shallow
$STD git apply "$BASE_DIR"/server/sources/libjxl-patches/jpegli-empty-dht-marker.patch
$STD git apply "$BASE_DIR"/server/sources/libjxl-patches/jpegli-icc-warning.patch
mkdir build
cd build
$STD cmake \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=OFF \
-DJPEGXL_ENABLE_DOXYGEN=OFF \
-DJPEGXL_ENABLE_MANPAGES=OFF \
-DJPEGXL_ENABLE_PLUGIN_GIMP210=OFF \
-DJPEGXL_ENABLE_BENCHMARK=OFF \
-DJPEGXL_ENABLE_EXAMPLES=OFF \
-DJPEGXL_FORCE_SYSTEM_BROTLI=ON \
-DJPEGXL_FORCE_SYSTEM_HWY=ON \
-DJPEGXL_ENABLE_JPEGLI=ON \
-DJPEGXL_ENABLE_JPEGLI_LIBJPEG=ON \
-DJPEGXL_INSTALL_JPEGLI_LIBJPEG=ON \
-DJPEGXL_ENABLE_PLUGINS=ON \
-DJPEGLI_LIBJPEG_LIBRARY_SOVERSION="$JPEGLI_LIBJPEG_LIBRARY_SOVERSION" \
-DJPEGLI_LIBJPEG_LIBRARY_VERSION="$JPEGLI_LIBJPEG_LIBRARY_VERSION" \
-DLIBJPEG_TURBO_VERSION_NUMBER=2001005 \
..
$STD cmake --build . -- -j"$(nproc)"
$STD cmake --install .
ldconfig /usr/local/lib
$STD make clean
cd "$STAGING_DIR"
rm -rf "$SOURCE"/{build,third_party}
sed -i "s/libjxl: .*$/libjxl: $LIBJXL_REVISION/" ~/.immich_library_revisions
msg_ok "Recompiled libjxl"
fi
}
function compile_libheif() {
SOURCE=${SOURCE_DIR}/libheif
if ! dpkg -l | grep -q libaom; then
$STD apt install -y libaom-dev
local update="required"
fi
: "${LIBHEIF_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libheif.json)}"
if [[ "${update:-}" ]] || [[ "$LIBHEIF_REVISION" != "$(grep 'libheif' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
msg_info "Recompiling libheif"
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
$STD git clone https://github.com/strukturag/libheif.git "$SOURCE"
cd "$SOURCE"
$STD git reset --hard "$LIBHEIF_REVISION"
mkdir build
cd build
$STD cmake --preset=release-noplugins \
-DWITH_DAV1D=ON \
-DENABLE_PARALLEL_TILE_DECODING=ON \
-DWITH_LIBSHARPYUV=ON \
-DWITH_LIBDE265=ON \
-DWITH_AOM_DECODER=OFF \
-DWITH_AOM_ENCODER=ON \
-DWITH_X265=OFF \
-DWITH_EXAMPLES=OFF \
..
$STD make install -j "$(nproc)"
ldconfig /usr/local/lib
$STD make clean
cd "$STAGING_DIR"
rm -rf "$SOURCE"/build
sed -i "s/libheif: .*$/libheif: $LIBHEIF_REVISION/" ~/.immich_library_revisions
msg_ok "Recompiled libheif"
fi
}
function compile_libraw() {
SOURCE=${SOURCE_DIR}/libraw
: "${LIBRAW_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libraw.json)}"
if [[ "$LIBRAW_REVISION" != "$(grep 'libraw' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
msg_info "Recompiling libraw"
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
$STD git clone https://github.com/libraw/libraw.git "$SOURCE"
cd "$SOURCE"
$STD git reset --hard "$LIBRAW_REVISION"
$STD autoreconf --install
$STD ./configure --disable-examples
$STD make -j"$(nproc)"
$STD make install
ldconfig /usr/local/lib
$STD make clean
cd "$STAGING_DIR"
sed -i "s/libraw: .*$/libraw: $LIBRAW_REVISION/" ~/.immich_library_revisions
msg_ok "Recompiled libraw"
fi
}
function compile_imagemagick() {
SOURCE=$SOURCE_DIR/imagemagick
: "${IMAGEMAGICK_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/imagemagick.json)}"
if [[ "$IMAGEMAGICK_REVISION" != "$(grep 'imagemagick' ~/.immich_library_revisions | awk '{print $2}')" ]] ||
! grep -q 'DMAGICK_LIBRAW' /usr/local/lib/ImageMagick-7*/config-Q16HDRI/configure.xml; then
msg_info "Recompiling ImageMagick"
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
$STD git clone https://github.com/ImageMagick/ImageMagick.git "$SOURCE"
cd "$SOURCE"
$STD git reset --hard "$IMAGEMAGICK_REVISION"
$STD ./configure --with-modules CPPFLAGS="-DMAGICK_LIBRAW_VERSION_TAIL=202502"
$STD make -j"$(nproc)"
$STD make install
ldconfig /usr/local/lib
$STD make clean
cd "$STAGING_DIR"
sed -i "s/imagemagick: .*$/imagemagick: $IMAGEMAGICK_REVISION/" ~/.immich_library_revisions
msg_ok "Recompiled ImageMagick"
fi
}
function compile_libvips() {
SOURCE=$SOURCE_DIR/libvips
: "${LIBVIPS_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libvips.json)}"
if [[ "$LIBVIPS_REVISION" != "$(grep 'libvips' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
msg_info "Recompiling libvips"
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
$STD git clone https://github.com/libvips/libvips.git "$SOURCE"
cd "$SOURCE"
$STD git reset --hard "$LIBVIPS_REVISION"
$STD meson setup build --buildtype=release --libdir=lib -Dintrospection=disabled -Dtiff=disabled
cd build
$STD ninja install
ldconfig /usr/local/lib
cd "$STAGING_DIR"
rm -rf "$SOURCE"/build
sed -i "s/libvips: .*$/libvips: $LIBVIPS_REVISION/" ~/.immich_library_revisions
msg_ok "Recompiled libvips"
fi
}
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}:2283${CL}"

View File

@@ -1,75 +0,0 @@
#!/usr/bin/env bash
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main}"
source <(curl -fsSL "$COMMUNITY_SCRIPTS_URL/misc/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Thiago Canozzo Lahr (tclahr)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/immichFrame/ImmichFrame
APP="ImmichFrame"
var_tags="${var_tags:-photos;slideshow}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/immichframe ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "immichframe" "immichFrame/ImmichFrame"; then
msg_info "Stopping Service"
systemctl stop immichframe
msg_ok "Stopped Service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "immichframe" "immichFrame/ImmichFrame" "tarball" "latest" "/tmp/immichframe"
msg_info "Building Application"
cd /tmp/immichframe
$STD dotnet publish ImmichFrame.WebApi/ImmichFrame.WebApi.csproj \
--configuration Release \
--runtime linux-x64 \
--self-contained false \
--output /opt/immichframe
cd /tmp/immichframe/immichFrame.Web
$STD npm ci --silent
$STD npm run build
rm -rf /opt/immichframe/wwwroot/*
cp -r build/* /opt/immichframe/wwwroot
rm -rf /tmp/immichframe
chown -R immichframe:immichframe /opt/immichframe
msg_ok "Application Built"
msg_info "Starting Service"
systemctl start immichframe
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}:8080${CL}"
echo -e "${INFO}${YW} Configuration file location:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}/opt/immichframe/Config/Settings.yml${CL}"
echo -e "${INFO}${YW} Edit the config file and set ImmichServerUrl and ApiKey before use!${CL}"

71
ct/invidious.sh Normal file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/iv-org/invidious
APP="Invidious"
var_tags="${var_tags:-streaming}"
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_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/invidious ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "Invidious" "iv-org/invidious"; then
msg_info "Stopping services"
$STD systemctl stop invidious-companion invidious
msg_ok "Stopped services"
msg_info "Backing up config"
cp /opt/invidious/config/config.yml /opt/invidious-config.yml
msg_ok "Backed up config"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Invidious" "iv-org/invidious" "tarball" "latest" "/opt/invidious"
if check_for_gh_release "Invidious-Companion" "iv-org/invidious-companion"; then
CLEAN_INSTALL fetch_and_deploy_gh_release "Invidious-Companion" "iv-org/invidious-companion" "prebuild" "latest" "/opt/invidious-companion" "invidious_companion-x86_64-unknown-linux-gnu.tar.gz"
fi
msg_info "Updating Invidious"
PG_DB_PASS="$(sed -n '/Password:/s/[^:]*:[[:space:]]//p' ~/oxicloud.creds)"
cd /opt/oxicloud
export DATABASE_URL="postgres://oxicloud:${PG_DB_PASS}@localhost/oxicloud"
export RUSTFLAGS="-C target-cpu=native"
$STD cargo build --release
mv target/release/oxicloud /usr/bin/oxicloud && chmod +x /usr/bin/oxicloud
msg_ok "Updated Invidious"
msg_info "Starting Invidious"
$STD systemctl start oxicloud
msg_ok "Started Invidious"
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}:8086${CL}"

View File

@@ -1,75 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Matthew Stern (sternma)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/dmunozv04/iSponsorBlockTV
APP="iSponsorBlockTV"
var_tags="${var_tags:-media;automation}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/isponsorblocktv ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "isponsorblocktv" "dmunozv04/iSponsorBlockTV"; then
msg_info "Stopping Service"
systemctl stop isponsorblocktv
msg_ok "Stopped Service"
if [[ -d /var/lib/isponsorblocktv ]]; then
msg_info "Backing up Data"
cp -r /var/lib/isponsorblocktv /var/lib/isponsorblocktv_data_backup
msg_ok "Backed up Data"
fi
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "isponsorblocktv" "dmunozv04/iSponsorBlockTV"
msg_info "Setting up iSponsorBlockTV"
$STD python3 -m venv /opt/isponsorblocktv/venv
$STD /opt/isponsorblocktv/venv/bin/pip install --upgrade pip
$STD /opt/isponsorblocktv/venv/bin/pip install /opt/isponsorblocktv
msg_ok "Set up iSponsorBlockTV"
if [[ -d /var/lib/isponsorblocktv_data_backup ]]; then
msg_info "Restoring Data"
rm -rf /var/lib/isponsorblocktv
cp -r /var/lib/isponsorblocktv_data_backup /var/lib/isponsorblocktv
rm -rf /var/lib/isponsorblocktv_data_backup
msg_ok "Restored Data"
fi
msg_info "Starting Service"
systemctl start isponsorblocktv
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} Run the setup wizard inside the container with:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}iSponsorBlockTV setup${CL}"

101
ct/librechat.sh Normal file
View File

@@ -0,0 +1,101 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/danny-avila/LibreChat
APP="LibreChat"
var_tags="${var_tags:-ai;chat}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-6144}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/librechat ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_tag "librechat" "danny-avila/LibreChat" "v"; then
msg_info "Stopping Services"
systemctl stop librechat rag-api
msg_ok "Stopped Services"
msg_info "Backing up Configuration"
cp /opt/librechat/.env /opt/librechat.env.bak
msg_ok "Backed up Configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_tag "librechat" "danny-avila/LibreChat"
msg_info "Installing Dependencies"
cd /opt/librechat
$STD npm ci
msg_ok "Installed Dependencies"
msg_info "Building Frontend"
$STD npm run frontend
$STD npm prune --production
$STD npm cache clean --force
msg_ok "Built Frontend"
msg_info "Restoring Configuration"
cp /opt/librechat.env.bak /opt/librechat/.env
rm -f /opt/librechat.env.bak
msg_ok "Restored Configuration"
msg_info "Starting Services"
systemctl start rag-api librechat
msg_ok "Started Services"
msg_ok "Updated LibreChat Successfully!"
fi
if check_for_gh_release "rag-api" "danny-avila/rag_api"; then
msg_info "Stopping RAG API"
systemctl stop rag-api
msg_ok "Stopped RAG API"
msg_info "Backing up RAG API Configuration"
cp /opt/rag-api/.env /opt/rag-api.env.bak
msg_ok "Backed up RAG API Configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "rag-api" "danny-avila/rag_api" "tarball"
msg_info "Updating RAG API Dependencies"
cd /opt/rag-api
$STD .venv/bin/pip install -r requirements.lite.txt
msg_ok "Updated RAG API Dependencies"
msg_info "Restoring RAG API Configuration"
cp /opt/rag-api.env.bak /opt/rag-api/.env
rm -f /opt/rag-api.env.bak
msg_ok "Restored RAG API Configuration"
msg_info "Starting RAG API"
systemctl start rag-api
msg_ok "Started RAG API"
msg_ok "Updated RAG API 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}:3080${CL}"

71
ct/localagi.sh Normal file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/env bash
source <(curl -sSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: BillyOutlast
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/mudler/LocalAGI
APP="LocalAGI"
var_tags="${var_tags:-ai}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
var_gpu="${var_gpu:-no}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if check_for_gh_release "localagi" "mudler/LocalAGI"; then
msg_info "Stopping Service"
systemctl stop localagi
msg_ok "Stopped Service"
if [[ -f /opt/localagi/.env ]]; then
msg_info "Backing up existing LocalAGI configuration"
cp /opt/localagi/.env /opt/localagi.env
msg_ok "Backed up LocalAGI configuration"
fi
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "localagi" "mudler/LocalAGI" "tarball" "latest" "/opt/localagi"
if [[ -f /opt/localagi.env ]]; then
msg_info "Restoring LocalAGI configuration"
cp /opt/localagi.env /opt/localagi/.env
msg_ok "Restored LocalAGI configuration"
fi
msg_info "Building LocalAGI"
cd /opt/localagi/webui/react-ui
$STD bun install
$STD bun run build
cd /opt/localagi
$STD go build -o /usr/local/bin/localagi
msg_ok "Updated LocalAGI successfully"
msg_info "Starting Service"
systemctl start localagi
msg_ok "Started Service"
msg_ok "Updated successfully!"
exit
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}:3000${CL}"

View File

@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2025 minthcm
# Author: MintHCM
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/minthcm/minthcm
APP="MintHCM"

View File

@@ -1,49 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: TechHutTV
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://netbird.io/
APP="NetBird"
var_tags="${var_tags:-network;vpn}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
var_tun="${var_tun:-yes}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/netbird/config.json ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating Netbird"
$STD apt update
$STD apt upgrade -y
msg_ok "Updated successfully!"
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access NetBird by entering the container and running:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}netbird up${CL}"

87
ct/netboot-xyz.sh Normal file
View File

@@ -0,0 +1,87 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Michel Roegl-Brunner (michelroegl-brunner)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://netboot.xyz
APP="netboot.xyz"
var_tags="${var_tags:-network;pxe;boot}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f ~/.netboot-xyz ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "netboot-xyz" "netbootxyz/netboot.xyz"; then
msg_info "Backing up Configuration"
cp /var/www/html/boot.cfg /opt/netboot-xyz-boot.cfg.bak
msg_ok "Backed up Configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "netboot-xyz" "netbootxyz/netboot.xyz" "prebuild" "latest" "/var/www/html" "menus.tar.gz"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-efi" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-efi-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.efi.dsk"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-snp.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-snp-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-snp.efi.dsk"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-snponly.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal.efi.dsk"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-snp.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-snp-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-snp.efi.dsk"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-snponly.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-kpxe" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.kpxe"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-undionly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-undionly.kpxe"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-kpxe" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal.kpxe"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-lkrn" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.lkrn"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-linux-bin" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-linux.bin"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-dsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.dsk"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-pdsk" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.pdsk"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64-snp.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64-snponly.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-arm64" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-arm64.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-arm64-snp" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-arm64-snp.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-metal-arm64-snponly" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-metal-arm64-snponly.efi"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-iso" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.iso"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-img" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz.img"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-iso" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64.iso"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-arm64-img" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-arm64.img"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-multiarch-iso" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-multiarch.iso"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-multiarch-img" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-multiarch.img"
USE_ORIGINAL_FILENAME=true fetch_and_deploy_gh_release "netboot-xyz-checksums" "netbootxyz/netboot.xyz" "singlefile" "latest" "/var/www/html" "netboot.xyz-sha256-checksums.txt"
msg_info "Restoring Configuration"
cp /opt/netboot-xyz-boot.cfg.bak /var/www/html/boot.cfg
rm -f /opt/netboot-xyz-boot.cfg.bak
msg_ok "Restored Configuration"
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}${CL}"

225
ct/nginxproxymanager.sh Normal file
View File

@@ -0,0 +1,225 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | Co-Author: CrazyWolf13
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://nginxproxymanager.com/ | Github: https://github.com/NginxProxyManager/nginx-proxy-manager
APP="Nginx Proxy Manager"
var_tags="${var_tags:-proxy}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
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 /lib/systemd/system/npm.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if [[ $(grep -E '^VERSION_ID=' /etc/os-release) == *"12"* ]]; then
msg_error "Wrong Debian version detected!"
msg_error "Please create a snapshot first. You must upgrade your LXC to Debian Trixie before updating. Visit: https://github.com/community-scripts/ProxmoxVE/discussions/7489"
exit
fi
if command -v node &>/dev/null; then
CURRENT_NODE_VERSION=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
if [[ "$CURRENT_NODE_VERSION" != "22" ]]; then
systemctl stop openresty
$STD apt purge -y nodejs npm
$STD apt autoremove -y
rm -rf /usr/local/bin/node /usr/local/bin/npm
rm -rf /usr/local/lib/node_modules
rm -rf ~/.npm
rm -rf /root/.npm
fi
fi
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
RELEASE=$(get_latest_github_release "NginxProxyManager/nginx-proxy-manager")
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "nginxproxymanager" "NginxProxyManager/nginx-proxy-manager" "tarball" "v${RELEASE}" "/opt/nginxproxymanager"
msg_info "Stopping Services"
systemctl stop openresty
systemctl stop npm
msg_ok "Stopped Services"
msg_info "Cleaning old files"
$STD rm -rf /app \
/var/www/html \
/etc/nginx \
/var/log/nginx \
/var/lib/nginx \
/var/cache/nginx
msg_ok "Cleaned old files"
msg_info "Migrating to OpenResty from source"
rm -f /etc/apt/trusted.gpg.d/openresty-archive-keyring.gpg /etc/apt/trusted.gpg.d/openresty.gpg
rm -f /etc/apt/sources.list.d/openresty.list /etc/apt/sources.list.d/openresty.sources
if dpkg -l openresty &>/dev/null; then
$STD apt remove -y openresty
$STD apt autoremove -y
fi
$STD apt install -y build-essential libpcre3-dev libssl-dev zlib1g-dev
msg_ok "Migrated to OpenResty from source"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "openresty" "openresty/openresty" "prebuild" "latest" "/opt/openresty" "openresty-*.tar.gz"
msg_info "Building OpenResty"
cd /opt/openresty
$STD ./configure \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_sub_module \
--with-http_auth_request_module \
--with-pcre-jit \
--with-stream \
--with-stream_ssl_module
$STD make -j"$(nproc)"
$STD make install
rm -rf /opt/openresty
cat <<'EOF' >/lib/systemd/system/openresty.service
[Unit]
Description=The OpenResty Application Platform
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=simple
ExecStartPre=/usr/local/openresty/nginx/sbin/nginx -t
ExecStart=/usr/local/openresty/nginx/sbin/nginx -g 'daemon off;'
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
msg_ok "Built OpenResty"
msg_info "Setting up Environment"
ln -sf /usr/bin/python3 /usr/bin/python
ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/sbin/nginx
ln -sf /usr/local/openresty/nginx/ /etc/nginx
sed -i "0,/\"version\": \"[^\"]*\"/s|\"version\": \"[^\"]*\"|\"version\": \"$RELEASE\"|" /opt/nginxproxymanager/backend/package.json
sed -i "0,/\"version\": \"[^\"]*\"/s|\"version\": \"[^\"]*\"|\"version\": \"$RELEASE\"|" /opt/nginxproxymanager/frontend/package.json
sed -i 's+^daemon+#daemon+g' /opt/nginxproxymanager/docker/rootfs/etc/nginx/nginx.conf
NGINX_CONFS=$(find /opt/nginxproxymanager -type f -name "*.conf")
for NGINX_CONF in $NGINX_CONFS; do
sed -i 's+include conf.d+include /etc/nginx/conf.d+g' "$NGINX_CONF"
done
mkdir -p /var/www/html /etc/nginx/logs
cp -r /opt/nginxproxymanager/docker/rootfs/var/www/html/* /var/www/html/
cp -r /opt/nginxproxymanager/docker/rootfs/etc/nginx/* /etc/nginx/
cp /opt/nginxproxymanager/docker/rootfs/etc/letsencrypt.ini /etc/letsencrypt.ini
cp /opt/nginxproxymanager/docker/rootfs/etc/logrotate.d/nginx-proxy-manager /etc/logrotate.d/nginx-proxy-manager
ln -sf /etc/nginx/nginx.conf /etc/nginx/conf/nginx.conf
rm -f /etc/nginx/conf.d/dev.conf
mkdir -p /tmp/nginx/body \
/run/nginx \
/data/nginx \
/data/custom_ssl \
/data/logs \
/data/access \
/data/nginx/default_host \
/data/nginx/default_www \
/data/nginx/proxy_host \
/data/nginx/redirection_host \
/data/nginx/stream \
/data/nginx/dead_host \
/data/nginx/temp \
/var/lib/nginx/cache/public \
/var/lib/nginx/cache/private \
/var/cache/nginx/proxy_temp
chmod -R 777 /var/cache/nginx
chown root /tmp/nginx
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then
$STD openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem
fi
mkdir -p /app/frontend/images
cp -r /opt/nginxproxymanager/backend/* /app
msg_ok "Set up Environment"
msg_info "Building Frontend"
export NODE_OPTIONS="--max_old_space_size=2048 --openssl-legacy-provider"
cd /opt/nginxproxymanager/frontend
# Replace node-sass with sass in package.json before installation
sed -E -i 's/"node-sass" *: *"([^"]*)"/"sass": "\1"/g' package.json
$STD yarn install --network-timeout 600000
$STD yarn locale-compile
$STD yarn build
cp -r /opt/nginxproxymanager/frontend/dist/* /app/frontend
cp -r /opt/nginxproxymanager/frontend/public/images/* /app/frontend/images
msg_ok "Built Frontend"
msg_info "Initializing Backend"
rm -rf /app/config/default.json
if [ ! -f /app/config/production.json ]; then
cat <<'EOF' >/app/config/production.json
{
"database": {
"engine": "knex-native",
"knex": {
"client": "better-sqlite3",
"connection": {
"filename": "/data/database.sqlite"
},
"useNullAsDefault": true
}
}
}
EOF
fi
sed -i 's/"client": "sqlite3"/"client": "better-sqlite3"/' /app/config/production.json
cd /app
$STD yarn install --network-timeout 600000
msg_ok "Initialized Backend"
msg_info "Updating Certbot"
if [ -d /opt/certbot ]; then
$STD /opt/certbot/bin/pip install --upgrade pip setuptools wheel
$STD /opt/certbot/bin/pip install --upgrade certbot certbot-dns-cloudflare
fi
msg_ok "Updated Certbot"
msg_info "Starting Services"
sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager
systemctl daemon-reload
systemctl enable -q --now openresty
systemctl enable -q --now npm
msg_ok "Started Services"
msg_ok "Updated successfully!"
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:81${CL}"

66
ct/oxicloud.sh Normal file
View File

@@ -0,0 +1,66 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/DioCrafts/OxiCloud
APP="OxiCloud"
var_tags="${var_tags:-files;documents}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-3072}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/oxicloud ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "OxiCloud" "DioCrafts/OxiCloud"; then
msg_info "Stopping OxiCloud"
$STD systemctl stop oxicloud
msg_ok "Stopped OxiCloud"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "OxiCloud" "DioCrafts/OxiCloud" "tarball" "latest" "/opt/oxicloud"
TOOLCHAIN="$(sed -n '2s/[^:]*://p' /opt/oxicloud/Dockerfile | awk -F- '{print $1}')"
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
msg_info "Updating OxiCloud"
PG_DB_PASS="$(sed -n '/Password:/s/[^:]*:[[:space:]]//p' ~/oxicloud.creds)"
cd /opt/oxicloud
export DATABASE_URL="postgres://oxicloud:${PG_DB_PASS}@localhost/oxicloud"
export RUSTFLAGS="-C target-cpu=native"
$STD cargo build --release
mv target/release/oxicloud /usr/bin/oxicloud && chmod +x /usr/bin/oxicloud
msg_ok "Updated OxiCloud"
msg_info "Starting OxiCloud"
$STD systemctl start oxicloud
msg_ok "Started OxiCloud"
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}:8086${CL}"

View File

@@ -1,63 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/papra-hq/papra
APP="Papra"
var_tags="${var_tags:-document-management}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-10}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/papra ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
RELEASE=$(curl -fsSL https://api.github.com/repos/papra-hq/papra/releases | grep -oP '"tag_name":\s*"\K@papra/app@[^"]+' | head -n1)
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt 2>/dev/null)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
msg_info "Stopping Service"
systemctl stop papra
msg_ok "Stopped Service"
msg_info "Updating ${APP} to ${RELEASE}"
cd /opt/papra
fetch_and_deploy_gh_release "papra" "papra-hq/papra" "tarball" "${RELEASE}" "/opt/papra"
$STD pnpm install --frozen-lockfile
$STD pnpm --filter "@papra/app-client..." run build
$STD pnpm --filter "@papra/app-server..." run build
echo "${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated ${APP} to ${RELEASE}"
msg_info "Starting Service"
systemctl start papra
msg_ok "Started Service"
msg_ok "Updated successfully!"
else
msg_ok "No update required. ${APP} is already at ${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}:1221${CL}"

79
ct/protonmail-bridge.sh Normal file
View File

@@ -0,0 +1,79 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Stephen Chin (steveonjava)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/ProtonMail/proton-bridge
APP="ProtonMail-Bridge"
var_tags="${var_tags:-mail;proton}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-8}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -x /usr/bin/protonmail-bridge ]]; then
msg_error "No ${APP} Installation Found!"
exit 1
fi
if check_for_gh_release "protonmail-bridge" "ProtonMail/proton-bridge"; then
local -a bridge_units=(
protonmail-bridge
protonmail-bridge-imap.socket
protonmail-bridge-smtp.socket
protonmail-bridge-imap-proxy
protonmail-bridge-smtp-proxy
)
local unit
declare -A was_active
for unit in "${bridge_units[@]}"; do
if systemctl is-active --quiet "$unit" 2>/dev/null; then
was_active["$unit"]=1
else
was_active["$unit"]=0
fi
done
msg_info "Stopping Services"
systemctl stop protonmail-bridge-imap.socket protonmail-bridge-smtp.socket protonmail-bridge-imap-proxy protonmail-bridge-smtp-proxy protonmail-bridge
msg_ok "Stopped Services"
fetch_and_deploy_gh_release "protonmail-bridge" "ProtonMail/proton-bridge" "binary"
if [[ -f /home/protonbridge/.protonmailbridge-initialized ]]; then
msg_info "Starting Services"
for unit in "${bridge_units[@]}"; do
if [[ "${was_active[$unit]:-0}" == "1" ]]; then
systemctl start "$unit"
fi
done
msg_ok "Started Services"
else
msg_ok "Initialization not completed. Services remain disabled."
fi
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}One-time configuration is required before Bridge services are enabled.${CL}"
echo -e "${INFO}${YW}Run this command in the container: protonmailbridge-configure${CL}"

View File

@@ -1,55 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/seaweedfs/seaweedfs
APP="SeaweedFS"
var_tags="${var_tags:-storage;s3;filesystem}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-16}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /opt/seaweedfs/weed ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "seaweedfs" "seaweedfs/seaweedfs"; then
msg_info "Stopping Service"
systemctl stop seaweedfs
msg_ok "Stopped Service"
fetch_and_deploy_gh_release "seaweedfs" "seaweedfs/seaweedfs" "prebuild" "latest" "/opt/seaweedfs" "linux_amd64.tar.gz"
msg_info "Starting Service"
systemctl start seaweedfs
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}:9333${CL}"

View File

@@ -53,7 +53,7 @@ function update_script() {
msg_info "Running Database Migrations"
cd /opt/simplelogin
cp /opt/simplelogin_env.bak /opt/simplelogin/.env
$STD .venv/bin/flask db upgrade
$STD .venv/bin/alembic upgrade head
msg_ok "Ran Database Migrations"
msg_info "Restoring Data"

View File

@@ -1,67 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: johanngrobe
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/oss-apps/split-pro
APP="Split-Pro"
var_tags="${var_tags:-finance;expense-sharing}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-6}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/split-pro ]]; then
msg_error "No Split Pro Installation Found!"
exit
fi
if check_for_gh_release "split-pro" "oss-apps/split-pro"; then
msg_info "Stopping Service"
systemctl stop split-pro
msg_ok "Stopped Service"
msg_info "Backing up Data"
cp /opt/split-pro/.env /opt/split-pro.env
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "split-pro" "oss-apps/split-pro" "tarball" "latest" "/opt/split-pro"
msg_info "Building Application"
cd /opt/split-pro
$STD pnpm install --frozen-lockfile
$STD pnpm build
cp /opt/split-pro.env /opt/split-pro/.env
rm -f /opt/split-pro.env
ln -sf /opt/split-pro_data/uploads /opt/split-pro/uploads
$STD pnpm exec prisma migrate deploy
msg_ok "Built Application"
msg_info "Starting Service"
systemctl start split-pro
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}:3000${CL}"

View File

@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2025 community-scripts ORG
# Author: KernelSailor
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://snowflake.torproject.org/
APP="tor-snowflake"

View File

@@ -9,7 +9,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
APP="Twenty"
var_tags="${var_tags:-crm;business;contacts}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-8192}"
var_ram="${var_ram:-10240}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"

View File

@@ -1,83 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/FuzzyGrim/Yamtrack
APP="Yamtrack"
var_tags="${var_tags:-media;tracker;movies;anime}"
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_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/yamtrack ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "yamtrack" "FuzzyGrim/Yamtrack"; then
msg_info "Stopping Services"
systemctl stop yamtrack yamtrack-celery
msg_ok "Stopped Services"
msg_info "Backing up Data"
cp /opt/yamtrack/src/.env /opt/yamtrack_env.bak
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "yamtrack" "FuzzyGrim/Yamtrack" "tarball"
msg_info "Installing Python Dependencies"
cd /opt/yamtrack
$STD uv venv .venv
$STD uv pip install --no-cache-dir -r requirements.txt
msg_ok "Installed Python Dependencies"
msg_info "Restoring Data"
cp /opt/yamtrack_env.bak /opt/yamtrack/src/.env
rm -f /opt/yamtrack_env.bak
msg_ok "Restored Data"
msg_info "Updating Yamtrack"
cd /opt/yamtrack/src
$STD /opt/yamtrack/.venv/bin/python manage.py migrate
$STD /opt/yamtrack/.venv/bin/python manage.py collectstatic --noinput
msg_ok "Updated Yamtrack"
msg_info "Updating Nginx Configuration"
cp /opt/yamtrack/nginx.conf /etc/nginx/nginx.conf
sed -i 's|user abc;|user www-data;|' /etc/nginx/nginx.conf
sed -i 's|/yamtrack/staticfiles/|/opt/yamtrack/src/staticfiles/|' /etc/nginx/nginx.conf
$STD systemctl reload nginx
msg_ok "Updated Nginx Configuration"
msg_info "Starting Services"
systemctl start yamtrack yamtrack-celery
msg_ok "Started Services"
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}:8000${CL}"

View File

@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2026 community-scripts ORG
# Author: dave-yap (dave-yap) | Co-author: remz1337
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://zitadel.com/
APP="Zitadel"

View File

@@ -705,7 +705,7 @@ cleanup_lxc
- [ ] `motd_ssh`, `customize`, `cleanup_lxc` at the end
- [ ] No custom download/version-check logic
- [ ] No default `(Patience)` text in msg_info labels
- [ ] JSON metadata file created in `frontend/public/json/<appname>.json`
- [ ] JSON metadata file created in `json/<appname>.json`
---
@@ -727,7 +727,7 @@ cleanup_lxc
## <20> JSON Metadata Files
Every application requires a JSON metadata file in `frontend/public/json/<appname>.json`.
Every application requires a JSON metadata file in `json/<appname>.json`.
### JSON Structure

View File

@@ -1,106 +1,142 @@
# Community Scripts Contribution Guide
## **Welcome to the communty-scripts Repository!**
## Welcome to the community-scripts repository
📜 These documents outline the essential coding standards for all our scripts and JSON files. Adhering to these standards ensures that our codebase remains consistent, readable, and maintainable. By following these guidelines, we can improve collaboration, reduce errors, and enhance the overall quality of our project.
These documents outline the coding standards and contribution flow for the ProxmoxVED repository.
### Why Coding Standards Matter
The important reality check is simple:
Coding standards are crucial for several reasons:
- contributors primarily submit shell scripts
- website metadata is **not** contributed as repo JSON files
- metadata changes belong to the website / maintainer workflow
1. **Consistency**: Consistent code is easier to read, understand, and maintain. It helps new team members quickly get up to speed and reduces the learning curve.
2. **Readability**: Clear and well-structured code is easier to debug and extend. It allows developers to quickly identify and fix issues.
3. **Maintainability**: Code that follows a standard structure is easier to refactor and update. It ensures that changes can be made with minimal risk of introducing new bugs.
4. **Collaboration**: When everyone follows the same standards, it becomes easier to collaborate on code. It reduces friction and misunderstandings during code reviews and merges.
## Scope of these documents
### Scope of These Documents
This contribution guide covers:
These documents cover the coding standards for the following types of files in our project:
- `ct/$AppName.sh` scripts for container creation and update entrypoints
- `install/$AppName-install.sh` scripts for in-container installation logic
- the supporting workflow for testing from your fork before opening a PR
- **`install/$AppName-install.sh` Scripts**: These scripts are responsible for the installation of applications.
- **`ct/$AppName.sh` Scripts**: These scripts handle the creation and updating of containers.
- **`json/$AppName.json`**: These files store structured data and are used for the website.
## Getting started
Each section provides detailed guidelines on various aspects of coding, including shebang usage, comments, variable naming, function naming, indentation, error handling, command substitution, quoting, script structure, and logging. Additionally, examples are provided to illustrate the application of these standards.
Before contributing, set up:
By following the coding standards outlined in this document, we ensure that our scripts and JSON files are of high quality, making our project more robust and easier to manage. Please refer to this guide whenever you create or update scripts and JSON files to maintain a high standard of code quality across the project. 📚🔍
1. Visual Studio Code or another editor with ShellCheck support
2. a fork of `community-scripts/ProxmoxVED`
3. a local clone of your fork
Let's work together to keep our codebase clean, efficient, and maintainable! 💪🚀
### Recommended extensions
- [Shell Syntax](https://marketplace.visualstudio.com/items?itemName=bmalehorn.shell-syntax)
- [ShellCheck](https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck)
- [Shell Format](https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format)
## Getting Started
### Templates
Before contributing, please ensure that you have the following setup:
Use these templates as your starting point:
1. **Visual Studio Code** (recommended for script development)
2. **Recommended VS Code Extensions:**
- [Shell Syntax](https://marketplace.visualstudio.com/items?itemName=bmalehorn.shell-syntax)
- [ShellCheck](https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck)
- [Shell Format](https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format)
- [CT template: `AppName.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh)
- [Install template: `AppName-install.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
### Important Notes
- Use [AppName.sh](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh) and [AppName-install.sh](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh) as templates when creating new scripts.
## Script types
---
### Application script: `ct/AppName.sh`
# 🚀 The Application Script (ct/AppName.sh)
Reference guide:
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md).
- These scripts are responsible for container creation, setting the necessary variables and handling the update of the application once installed.
- [CT coding guide for `AppName.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md)
---
This script is responsible for:
# 🛠 The Installation Script (install/AppName-install.sh)
- host-side container orchestration
- app variables and defaults
- update wiring for the installed app
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md).
- These scripts are responsible for the installation of the application.
### Installation script: `install/AppName-install.sh`
---
Reference guide:
## 🚀 Building Your Own Scripts
- [Install coding guide for `AppName-install.sh`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md)
Start with the [template script](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
This script is responsible for:
---
- container-internal installation logic
- package/runtime setup
- final application configuration
## 🤝 Contribution Process
## Contribution process
### 1. Fork the repository
Fork to your GitHub account
### 2. Clone your fork on your local environment
Fork `community-scripts/ProxmoxVED` to your GitHub account.
### 2. Clone your fork
```bash
git clone https://github.com/yourUserName/ForkName
```
### 3. Create a new branch
### 3. Create a branch
```bash
git switch -c your-feature-branch
```
### 4. Change paths in build.func install.func and AppName.sh
To be able to develop from your own branch you need to change `https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main` to `https://raw.githubusercontent.com/[USER]/[REPOSITORY]/refs/heads/[BRANCH]`. You need to make this change atleast in misc/build.func misc/install.func and in your ct/AppName.sh. This change is only for testing. Before opening a Pull Request you should change this line change all this back to point to `https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main`.
### 4. Configure your fork for testing
Use the helper script:
```bash
bash docs/contribution/setup-fork.sh --full
```
This prepares the raw GitHub URLs in your working copy so you can test against your own fork instead of the upstream repository.
### 5. Build and test from your fork
Use the curl/bash execution model that matches real user behavior, for example:
```bash
bash -c "$(curl -fsSL https://raw.githubusercontent.com/<USER>/<REPO>/refs/heads/<BRANCH>/ct/myapp.sh)"
```
Do **not** document or optimize only for local manual execution if the real path is curl-based execution.
### 6. Commit only your intended contribution
### 4. Commit changes (without build.func and install.func!)
```bash
git commit -m "Your commit message"
```
### 5. Push to your fork
### 7. Push your branch
```bash
git push origin your-feature-branch
```
### 6. Create a Pull Request
Open a Pull Request from your feature branch to the main repository branch. You must only include your **$AppName.sh**, **$AppName-install.sh** and **$AppName.json** files in the pull request.
### 8. Open a pull request
---
Open a PR from your branch to `community-scripts/ProxmoxVED/main`.
## 📚 Pages
Your PR should contain only the files that belong to the script contribution itself, typically:
- `ct/myapp.sh`
- `install/myapp-install.sh`
## Website metadata
Website metadata is maintained outside this repository's script contribution flow.
That means:
- do not add repo JSON metadata files as part of the normal contribution path
- do not assume a `frontend/public/json/...` workflow exists for the live site
- route metadata creation or metadata changes through the website / maintainer workflow
## Pages
- [CT Template: AppName.sh](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh)
- [Install Template: AppName-install.sh](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
- [JSON Template: AppName.json](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/CONTRIBUTOR_AND_GUIDES/json/AppName.json)
- [Fork setup guide](./FORK_SETUP.md)
- [Contribution README](./README.md)

View File

@@ -172,6 +172,7 @@ var_unprivileged="1" # 1=unprivileged (secure), 0=privileged (rarely n
```
**Variable Naming Convention**:
- Variables exposed to user: `var_*` (e.g., `var_cpu`, `var_hostname`, `var_ssh`)
- Internal variables: lowercase (e.g., `container_id`, `app_version`)
@@ -273,6 +274,7 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
**Triggered by**: Called automatically at script start
**Behavior**:
1. Parse command-line arguments (if any)
2. Generate random UUID for session tracking
3. Load container storage from Proxmox
@@ -284,6 +286,7 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
**Purpose**: Launch the container creation menu with 5 installation modes
**Menu Options**:
```
1. Default Installation (Quick setup, predefined settings)
2. Advanced Installation (19-step wizard with full control)
@@ -297,6 +300,7 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
**Purpose**: Main orchestrator for LXC container creation
**Operations**:
1. Validates all variables
2. Creates LXC container via `pct create`
3. Executes `install/AppName-install.sh` inside container
@@ -398,6 +402,7 @@ msg_ok "Completed successfully!\n"
**Symptom**: `pct create` exits with error code 209
**Solution**:
```bash
# Check existing containers
pct list | grep CTID
@@ -411,6 +416,7 @@ pct destroy CTID
### Update Function Doesn't Detect New Version
**Debug**:
```bash
# Check version file
cat /opt/AppName_version.txt
@@ -426,6 +432,7 @@ curl -fsSL https://api.github.com/repos/user/repo/releases/latest | grep tag_nam
Before submitting a PR:
### Script Structure
- [ ] Shebang is `#!/usr/bin/env bash`
- [ ] Imports `build.func` from community-scripts repo
- [ ] Copyright header with author and source URL
@@ -433,17 +440,20 @@ Before submitting a PR:
- [ ] `var_tags` are semicolon-separated (no spaces)
### Default Values
- [ ] `var_cpu` set appropriately (2-4 for most apps)
- [ ] `var_ram` set appropriately (1024-4096 MB minimum)
- [ ] `var_disk` sufficient for app + data (5-20 GB)
- [ ] `var_os` is realistic
### Functions
- [ ] `update_script()` implemented
- [ ] Update function checks if app installed
- [ ] Proper error handling with `msg_error`
### Testing
- [ ] Script tested with default installation
- [ ] Script tested with advanced (19-step) installation
- [ ] Update function tested on existing installation

268
docs/guides/netboot-xyz.md Normal file
View File

@@ -0,0 +1,268 @@
# netboot.xyz — Self-Hosted PXE Boot Server on Proxmox
## What is netboot.xyz?
netboot.xyz is a **network boot (PXE) utility**. It lets any machine on your network boot from a menu of operating systems and tools — without a USB stick, CD/DVD, or pre-downloaded ISO.
Think of it like a universal boot menu that loads over the network.
### What your self-hosted container actually does
Your LXC container hosts only two things:
- **iPXE bootloader binaries** (`.efi`, `.kpxe` files — a few hundred KB each)
- **iPXE menu files** (plain text `.ipxe` scripts that define the menu structure)
That's it. The container serves ~80 MB of files total (bootloaders + menus).
When a machine PXE-boots, it:
1. Fetches the bootloader binary from your container (via TFTP or HTTP)
2. The bootloader loads the menu from your container
3. You pick an OS
4. The OS installer or live system loads **directly from upstream internet mirrors** at boot time
Your container is the **signpost**. The internet is the **library**.
> **Important:** Clients need internet access to actually install/boot an OS. Your container itself does not need to store or proxy OS images.
### What you can boot
| Category | Examples |
| ------------------ | ------------------------------------------------------------- |
| **OS Installers** | Debian, Ubuntu, Fedora, Rocky Linux, Alpine, Arch, NixOS, ... |
| **Live Systems** | Kali Live, Tails, Mint Live, Manjaro Live, ... |
| **Rescue Tools** | SystemRescue, Clonezilla, GParted, Rescuezilla, Memtest86 |
| **Virtualization** | Proxmox VE, Harvester, VMware ESXi |
| **BSD** | FreeBSD, OpenBSD |
| **Utilities** | ShredOS (disk wipe), DBAN, ZFSBootMenu, Super Grub2 |
---
## Installation
Run on your **Proxmox host**:
```bash
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/netboot-xyz.sh)"
```
Creates a minimal Debian 13 LXC container:
| Resource | Value |
| ----------- | ------ |
| CPU | 1 core |
| RAM | 512 MB |
| Disk | 8 GB |
| Port (HTTP) | 80/TCP |
| Port (TFTP) | 69/UDP |
After installation, the web interface is available at:
```
http://<container-ip>/
```
It shows a directory listing of all available bootloaders and menu files.
---
## How to PXE Boot a Machine
### Step 1 — Configure your DHCP server
Your DHCP server needs to tell PXE clients where to find the bootloader.
**Required settings:**
| Setting | Value |
| --------------------------- | ------------------ |
| Next Server (TFTP) | `<container-ip>` |
| Boot filename (UEFI) | `netboot.xyz.efi` |
| Boot filename (BIOS/Legacy) | `netboot.xyz.kpxe` |
**OPNsense / pfSense:**
`Services → DHCP Server → [interface] → Network Booting`
- _Enable_: checked
- _Next server_: `<container-ip>`
- _Default BIOS filename_: `netboot.xyz.kpxe`
- _UEFI 64-bit filename_: `netboot.xyz.efi`
**dnsmasq (Pi-hole, AdGuard Home, OpenWrt):**
```
dhcp-boot=netboot.xyz.kpxe,<container-ip> # BIOS
# or:
dhcp-boot=netboot.xyz.efi,<container-ip> # UEFI
```
**ISC DHCP (`dhcpd.conf`):**
```
next-server <container-ip>;
filename "netboot.xyz.efi";
```
### Step 2 — Enable PXE boot on your client
In the machine's BIOS/UEFI:
- Enable **Network Boot** / **PXE Boot**
- Set boot order: Network first (or select once via boot menu, usually F11/F12)
### Step 3 — Boot
Power on the machine. The iPXE bootloader loads from your container, shows the menu, and you navigate with arrow keys.
---
## UEFI HTTP Boot (no DHCP changes)
Modern UEFI firmware supports booting directly from an HTTP URL — no DHCP options needed.
Load the bootloader directly in the UEFI shell:
```
http://<container-ip>/netboot.xyz.efi
```
**Proxmox VMs:** Set the VM network boot URL in the UEFI shell, or use iPXE chaining in the VM BIOS.
---
## Available Bootloader Files
All files are served at `http://<container-ip>/` and `http://<container-ip>/ipxe/`:
### x86_64 UEFI
| File | Use case |
| ------------------------- | ----------------------------------------------- |
| `netboot.xyz.efi` | Standard UEFI — recommended starting point |
| `netboot.xyz.efi.dsk` | Virtual floppy/disk image of the EFI bootloader |
| `netboot.xyz-snp.efi` | UEFI SNP — tries all network devices |
| `netboot.xyz-snp.efi.dsk` | Disk image of SNP EFI bootloader |
| `netboot.xyz-snponly.efi` | UEFI SNP — only boots from chained device |
### x86_64 UEFI Metal (Secure Boot / code-signed)
| File | Use case |
| ------------------------------- | ------------------------------------------- |
| `netboot.xyz-metal.efi` | Secure Boot compatible UEFI bootloader |
| `netboot.xyz-metal.efi.dsk` | Disk image of metal EFI bootloader |
| `netboot.xyz-metal-snp.efi` | Secure Boot SNP — tries all network devices |
| `netboot.xyz-metal-snp.efi.dsk` | Disk image of metal SNP EFI bootloader |
| `netboot.xyz-metal-snponly.efi` | Secure Boot SNP — only chained device |
### x86_64 BIOS / Legacy
| File | Use case |
| --------------------------- | ------------------------------------------------- |
| `netboot.xyz.kpxe` | BIOS PXE — built-in iPXE NIC drivers |
| `netboot.xyz-undionly.kpxe` | BIOS PXE fallback — use if NIC has driver issues |
| `netboot.xyz-metal.kpxe` | BIOS PXE — Secure Boot / code-signed variant |
| `netboot.xyz.lkrn` | Kernel module — load from GRUB/EXTLINUX |
| `netboot.xyz-linux.bin` | Linux binary — chainload from existing Linux boot |
| `netboot.xyz.dsk` | Virtual floppy disk for DRAC/iLO, VMware, etc. |
| `netboot.xyz.pdsk` | Padded virtual floppy disk |
### ARM64
| File | Use case |
| ------------------------------------- | ------------------------------------------- |
| `netboot.xyz-arm64.efi` | ARM64 UEFI — standard |
| `netboot.xyz-arm64-snp.efi` | ARM64 UEFI SNP — tries all network devices |
| `netboot.xyz-arm64-snponly.efi` | ARM64 UEFI SNP — only chained device |
| `netboot.xyz-metal-arm64.efi` | ARM64 Secure Boot UEFI |
| `netboot.xyz-metal-arm64-snp.efi` | ARM64 Secure Boot SNP |
| `netboot.xyz-metal-arm64-snponly.efi` | ARM64 Secure Boot SNP — only chained device |
### ISO / IMG (for media creation or virtual boot)
| File | Use case |
| --------------------------- | ------------------------------------------------- |
| `netboot.xyz.iso` | x86_64 ISO — CD/DVD, virtual CD, DRAC/iLO, VMware |
| `netboot.xyz.img` | x86_64 IMG — USB key creation |
| `netboot.xyz-arm64.iso` | ARM64 ISO |
| `netboot.xyz-arm64.img` | ARM64 IMG — USB key creation |
| `netboot.xyz-multiarch.iso` | Combined x86_64 + ARM64 ISO |
| `netboot.xyz-multiarch.img` | Combined x86_64 + ARM64 IMG |
### Checksums
| File | Use case |
| ---------------------------------- | --------------------------- |
| `netboot.xyz-sha256-checksums.txt` | SHA256 hashes for all files |
> **BIOS vs UEFI:** Use `.efi` for UEFI systems, `.kpxe` for legacy BIOS. Mixing them causes silent failures.
>
> **Secure Boot:** Use the `-metal-` variants if your firmware enforces Secure Boot.
---
## Customizing the Menu
Edit `/var/www/html/boot.cfg` inside the container:
```bash
# SSH into the container, then:
nano /var/www/html/boot.cfg
```
Changes take effect immediately — no service restart needed.
Common customizations:
```bash
# Set a default boot entry with 10-second timeout:
set menu-timeout 10000
set menu-default linux
# Override the mirror used for Ubuntu:
set mirror http://de.archive.ubuntu.com/ubuntu
```
Full documentation: [netboot.xyz/docs](https://netboot.xyz/docs/)
---
## Updating
The update script preserves your `boot.cfg` customizations, updates menus and bootloaders to the latest release:
```bash
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/netboot-xyz.sh)"
```
---
## Troubleshooting
### Client can't reach the container / TFTP timeout
- Check that UDP/69 (TFTP) and TCP/80 (HTTP) are not blocked between client and container
- Proxmox firewall: add rules to allow these ports inbound on the container
- Check that the container is in the same VLAN/subnet as the client, or that inter-VLAN routing is configured
### Menu loads but OS download fails or is slow
- Expected — OS files come from the internet, not your container
- Client needs internet access (direct or via NAT through Proxmox)
- For air-gapped networks, you need to mirror OS images locally (advanced, see netboot.xyz docs)
### Machine boots to local disk instead of PXE
- Check boot order in BIOS/UEFI — network boot must come first, or select it manually via F11/F12
- Some UEFI systems require Secure Boot to be disabled for iPXE
### UEFI machine ignores the boot filename
- Some DHCP servers send the same `filename` option to both BIOS and UEFI clients
- Use vendor class matching in your DHCP config to send `.efi` only to UEFI clients
- OPNsense/pfSense handle this automatically when you set both BIOS and UEFI filenames separately
### `netboot.xyz.kpxe` works but `netboot.xyz.efi` doesn't (or vice versa)
- BIOS systems → use `netboot.xyz.kpxe` or `netboot.xyz-undionly.kpxe`
- UEFI systems → use `netboot.xyz.efi` or `netboot.xyz-snp.efi`

View File

@@ -1,15 +1,25 @@
# Misc Documentation
This directory contains comprehensive documentation for all function libraries and components of the Proxmox Community Scripts project. Each section is organized as a dedicated subdirectory with detailed references, examples, and integration guides.
This directory documents the shared Bash function libraries under `misc/`.
The important implementation detail is that these libraries are **not independent islands**:
- `build.func` orchestrates host-side CT creation.
- `api.func` is the canonical source of telemetry and exit-code explanations.
- `error_handler.func` wraps trap handling and falls back to `explain_exit_code()` if `api.func` was not loaded yet.
- `install.func` runs inside the container and bootstraps `core.func` + `error_handler.func` first, then downloads `tools.func` after the OS update stage.
- `tools.func` is the large Debian/Ubuntu helper toolbox for repository management, retries, releases, services, language runtimes, databases, GPU helpers, and update workflows.
---
## 🏗️ **Core Function Libraries**
### 📁 [build.func/](./build.func/)
**Core LXC Container Orchestration** - Main orchestrator for Proxmox LXC container creation
**Contents:**
- BUILD_FUNC_FLOWCHART.md - Visual execution flows and decision trees
- BUILD_FUNC_ARCHITECTURE.md - System architecture and design
- BUILD_FUNC_ENVIRONMENT_VARIABLES.md - Complete environment variable reference
@@ -23,9 +33,11 @@ This directory contains comprehensive documentation for all function libraries a
---
### 📁 [core.func/](./core.func/)
**System Utilities & Foundation** - Essential utility functions and system checks
**System Utilities & Foundation** - Shared runtime foundation for logging, prompts, validation, and execution control
**Contents:**
- CORE_FLOWCHART.md - Visual execution flows
- CORE_FUNCTIONS_REFERENCE.md - Complete function reference
- CORE_INTEGRATION.md - Integration points
@@ -37,9 +49,11 @@ This directory contains comprehensive documentation for all function libraries a
---
### 📁 [error_handler.func/](./error_handler.func/)
**Error Handling & Signal Management** - Comprehensive error handling and signal trapping
**Error Handling & Signal Management** - Trap orchestration, cleanup, and abort telemetry
**Contents:**
- ERROR_HANDLER_FLOWCHART.md - Visual error handling flows
- ERROR_HANDLER_FUNCTIONS_REFERENCE.md - Function reference
- ERROR_HANDLER_INTEGRATION.md - Integration with other components
@@ -51,39 +65,45 @@ This directory contains comprehensive documentation for all function libraries a
---
### 📁 [api.func/](./api.func/)
**Proxmox API Integration** - API communication and diagnostic reporting
**Telemetry & Diagnostics Runtime** - Anonymous telemetry reporting, progress tracking, and canonical exit-code mapping
**Contents:**
- API_FLOWCHART.md - API communication flows
- API_FUNCTIONS_REFERENCE.md - Function reference
- API_INTEGRATION.md - Integration points
- API_USAGE_EXAMPLES.md - Practical examples
- README.md - Overview and quick reference
**Key Functions**: `post_to_api()`, `post_update_to_api()`, `get_error_description()`
**Key Functions**: `post_to_api()`, `post_to_api_vm()`, `post_progress_to_api()`, `post_update_to_api()`, `explain_exit_code()`
---
## 📦 **Installation & Setup Function Libraries**
### 📁 [install.func/](./install.func/)
**Container Installation Workflow** - Installation orchestration for container-internal setup
**Container Installation Workflow** - Container bootstrap inside the LXC
**Contents:**
- INSTALL_FUNC_FLOWCHART.md - Installation workflow diagrams
- INSTALL_FUNC_FUNCTIONS_REFERENCE.md - Complete function reference
- INSTALL_FUNC_INTEGRATION.md - Integration with build and tools
- INSTALL_FUNC_USAGE_EXAMPLES.md - Practical examples
- README.md - Overview and quick reference
**Key Functions**: `setting_up_container()`, `network_check()`, `update_os()`, `motd_ssh()`, `cleanup_lxc()`
**Key Functions**: `setting_up_container()`, `network_check()`, `update_os()`, `motd_ssh()`, `customize()`
---
### 📁 [tools.func/](./tools.func/)
**Package & Tool Installation** - Robust package management and 30+ tool installation functions
**Package & Tool Installation** - Repository, package, release, runtime, and service toolbox
**Contents:**
- TOOLS_FUNC_FLOWCHART.md - Package management flows
- TOOLS_FUNC_FUNCTIONS_REFERENCE.md - 30+ function reference
- TOOLS_FUNC_INTEGRATION.md - Integration with install workflows
@@ -91,14 +111,16 @@ This directory contains comprehensive documentation for all function libraries a
- TOOLS_FUNC_ENVIRONMENT_VARIABLES.md - Configuration reference
- README.md - Overview and quick reference
**Key Functions**: `setup_nodejs()`, `setup_php()`, `setup_mariadb()`, `setup_docker()`, `setup_deb822_repo()`, `pkg_install()`, `pkg_update()`
**Key Functions**: `curl_with_retry()`, `setup_deb822_repo()`, `install_packages_with_retry()`, `setup_mariadb()`, `setup_postgresql()`, `get_latest_github_release()`
---
### 📁 [alpine-install.func/](./alpine-install.func/)
**Alpine Container Setup** - Alpine Linux-specific installation functions
**Contents:**
- ALPINE_INSTALL_FUNC_FLOWCHART.md - Alpine setup flows
- ALPINE_INSTALL_FUNC_FUNCTIONS_REFERENCE.md - Function reference
- ALPINE_INSTALL_FUNC_INTEGRATION.md - Integration points
@@ -110,9 +132,11 @@ This directory contains comprehensive documentation for all function libraries a
---
### 📁 [alpine-tools.func/](./alpine-tools.func/)
**Alpine Tool Installation** - Alpine-specific package and tool installation
**Contents:**
- ALPINE_TOOLS_FUNC_FLOWCHART.md - Alpine package flows
- ALPINE_TOOLS_FUNC_FUNCTIONS_REFERENCE.md - Function reference
- ALPINE_TOOLS_FUNC_INTEGRATION.md - Integration with Alpine workflows
@@ -124,9 +148,11 @@ This directory contains comprehensive documentation for all function libraries a
---
### 📁 [cloud-init.func/](./cloud-init.func/)
**VM Cloud-Init Configuration** - Cloud-init and VM provisioning functions
**Contents:**
- CLOUD_INIT_FUNC_FLOWCHART.md - Cloud-init flows
- CLOUD_INIT_FUNC_FUNCTIONS_REFERENCE.md - Function reference
- CLOUD_INIT_FUNC_INTEGRATION.md - Integration points
@@ -145,18 +171,24 @@ This directory contains comprehensive documentation for all function libraries a
├─────────────────────────────────────────────┤
│ │
│ ct/AppName.sh │
│ ↓ (sources)
│ ↓ sources
│ build.func │
│ ├─ variables()
│ ├─ build_container()
advanced_settings()
↓ (calls pct create with)
│ ├─ sources api.func
│ ├─ sources core.func
sources error_handler.func
├─ loads variables/settings/prompts
│ └─ creates container + launch phase │
│ ↓ pct exec / lxc-attach │
│ install/appname-install.sh │
│ ↓ (sources)
│ ├─ core.func (colors, messaging)
│ ├─ error_handler.func (error trapping)
│ ├─ install.func (setup/network)
tools.func (packages/tools)
│ ↓ sources install.func
│ ├─ sources core.func
│ ├─ sources error_handler.func
│ ├─ load_functions()
catch_errors()
│ ├─ network_check() │
│ ├─ update_os() │
│ │ └─ downloads + sources tools.func │
│ └─ app install uses tools.func │
│ │
└─────────────────────────────────────────────┘
@@ -191,17 +223,17 @@ This directory contains comprehensive documentation for all function libraries a
## 📊 **Documentation Quick Stats**
| Library | Files | Functions | Status |
|---------|:---:|:---:|:---:|
| build.func | 7 | 50+ | ✅ Complete |
| core.func | 5 | 20+ | ✅ Complete |
| error_handler.func | 5 | 10+ | ✅ Complete |
| api.func | 5 | 5+ | ✅ Complete |
| install.func | 5 | 8+ | ✅ Complete |
| tools.func | 6 | 30+ | ✅ Complete |
| alpine-install.func | 5 | 6+ | ✅ Complete |
| alpine-tools.func | 5 | 15+ | ✅ Complete |
| cloud-init.func | 5 | 12+ | ✅ Complete |
| Library | Files | Functions | Status |
| ------------------- | :---: | :-------: | :---------: |
| build.func | 7 | 50+ | ✅ Complete |
| core.func | 5 | 20+ | ✅ Complete |
| error_handler.func | 5 | 10+ | ✅ Complete |
| api.func | 5 | 5+ | ✅ Complete |
| install.func | 5 | 8+ | ✅ Complete |
| tools.func | 6 | 30+ | ✅ Complete |
| alpine-install.func | 5 | 6+ | ✅ Complete |
| alpine-tools.func | 5 | 15+ | ✅ Complete |
| cloud-init.func | 5 | 12+ | ✅ Complete |
**Total**: 9 function libraries, 48 documentation files, 150+ functions
@@ -210,16 +242,20 @@ This directory contains comprehensive documentation for all function libraries a
## 🚀 **Getting Started**
### For Container Creation Scripts
Start with: **[build.func/](./build.func/)** → **[tools.func/](./tools.func/)** → **[install.func/](./install.func/)**
Start with: **[build.func/](./build.func/)** → **[core.func/](./core.func/)** → **[error_handler.func/](./error_handler.func/)** → **[api.func/](./api.func/)** → **[install.func/](./install.func/)** → **[tools.func/](./tools.func/)**
### For Alpine Containers
Start with: **[alpine-install.func/](./alpine-install.func/)** → **[alpine-tools.func/](./alpine-tools.func/)**
### For VM Provisioning
Start with: **[cloud-init.func/](./cloud-init.func/)**
### For Troubleshooting
Start with: **[error_handler.func/](./error_handler.func/)** → **[EXIT_CODES.md](../EXIT_CODES.md)**
Start with: **[error_handler.func/](./error_handler.func/)** → **[api.func/](./api.func/)**
---
@@ -251,6 +287,7 @@ function-library/
```
**Advantages**:
- ✅ Consistent navigation across all libraries
- ✅ Quick reference sections in each README
- ✅ Visual flowcharts for understanding
@@ -273,11 +310,12 @@ All documentation follows these standards:
---
## ✅ **Last Updated**: December 2025
## ✅ **Last Updated**: Based on live `misc/*` code verification
**Maintainers**: community-scripts team
**License**: MIT
**Status**: All 9 libraries fully documented and standardized
**Status**: Canonical overviews aligned to live code; deeper generated subpages may still require occasional drift cleanup
---
*This directory contains specialized documentation for specific components of the Proxmox Community Scripts project.*
_When documentation conflicts with the live shell implementation, prefer the files under `ProxmoxVE` / `ProxmoxVED` `misc/`._

65
docs/pocketbase-bot.md Normal file
View File

@@ -0,0 +1,65 @@
## 🤖 PocketBase Bot — Command Reference
> Available to **org members only** (Contributors team).
> Trigger by posting a comment on any Issue or PR.
---
### 🔧 Field Updates
Simple key=value pairs. Multiple in one line.
```
/pocketbase <slug> field=value [field=value ...]
```
**Boolean fields** (`true`/`false`): `updateable` `privileged` `has_arm` `is_dev` `is_disabled` `is_deleted`
**Text fields**: `name` `description` `logo` `documentation` `website` `project_url` `github` `config_path` `disable_message` `deleted_message`
**Number**: `port`
**Nullable**: `default_user` `default_passwd` *(empty value = null: `default_passwd=`)*
**Examples:**
```
/pocketbase homeassistant is_disabled=true disable_message="Broken upstream"
/pocketbase homeassistant documentation=https://www.home-assistant.io/docs
/pocketbase homeassistant is_dev=false
/pocketbase homeassistant default_passwd=
```
---
### 📝 set — HTML / Multiline / Special Characters
Use a code block for values that contain HTML, links, quotes or newlines.
````
/pocketbase <slug> set <field>
```
Your content here — HTML tags, links, quotes, all fine
```
````
**Allowed fields:** `name` `description` `logo` `documentation` `website` `project_url` `github` `config_path` `disable_message` `deleted_message`
---
### 🗒️ Notes
```
/pocketbase <slug> note list
/pocketbase <slug> note add <type> "<text>"
/pocketbase <slug> note edit <type> "<old text>" "<new text>"
/pocketbase <slug> note remove <type> "<text>"
```
Note types come from `z_ref_note_types` in PocketBase (e.g. `info`, `warning`).
If text doesn't match exactly, the bot lists all current notes automatically.
---
### ⚙️ Install Method Resources
```
/pocketbase <slug> method list
/pocketbase <slug> method <type> hdd=10
/pocketbase <slug> method <type> cpu=4 ram=2048 hdd=20
```
`<type>` matches the install method type name (e.g. `default`, `alpine`). Use `method list` to see available types and current values. `ram` = MB, `hdd` = GB.
---
### 💡 Tips
- The bot reacts with 👀 when it picks up the command, ✅ on success, 👎 on error
- On any error, a comment explains what went wrong
- `note edit` / `note remove` show the current note list if the text doesn't match

158
docs/vm/APP_DEPLOYER_VM.md Normal file
View File

@@ -0,0 +1,158 @@
# App Deployer VM
Deploy LXC applications inside a full Virtual Machine instead of an LXC container.
## Overview
The App Deployer VM bridges the gap between CT install scripts (`install/*.sh`) and VM infrastructure. It leverages the existing install scripts — originally designed for LXC containers — and runs them **live during image build** via `virt-customize --run`.
### Supported Operating Systems
| OS | Version | Codename | Cloud-Init |
| ------ | --------- | -------- | ---------- |
| Debian | 13 | Trixie | Optional |
| Debian | 12 | Bookworm | Optional |
| Ubuntu | 24.04 LTS | Noble | Required |
| Ubuntu | 22.04 LTS | Jammy | Required |
## Usage
### Create a new App VM (interactive)
```bash
bash -c "$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/vm/app-deployer-vm.sh)"
```
### Pre-select application
```bash
APP_SELECT=yamtrack bash -c "$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/vm/app-deployer-vm.sh)"
```
### Update the application later (inside the VM)
```bash
bash -c "$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/ct/<app>.sh)"
```
For example, to update Yamtrack:
```bash
bash -c "$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/ct/yamtrack.sh)"
```
## How It Works
### Installation Flow
```
┌─────────────────────────────────────┐
│ Proxmox Host │
│ │
│ 1. Select app (e.g. Yamtrack) │
│ 2. Select OS (e.g. Debian 13) │
│ 3. Configure VM resources │
│ 4. Download cloud image │
│ 5. virt-customize: │
│ - Install base packages │
│ - Inject install.func │
│ - Inject tools.func │
│ - Run install script LIVE │
│ (virt-customize --run) │
│ - Configure hostname & SSH │
│ 6. Create VM (qm create) │
│ 7. Import customized disk │
│ 8. Start VM │
│ │
│ → Application pre-installed! │
└─────────────────────────────────────┘
```
### Update Flow
```
┌─────────────────────────────────────┐
│ Inside the VM (SSH or console) │
│ │
│ bash -c "$(curl -fsSL │
│ $COMMUNITY_SCRIPTS_URL/ │
│ ct/<app>.sh)" │
│ │
│ → start() detects no pveversion │
│ → Shows update/settings menu │
│ → Runs update_script() │
└─────────────────────────────────────┘
```
The update mechanism reuses the existing CT script logic. Since `pveversion` is not available inside the VM, the `start()` function automatically enters the update/settings mode — exactly the same as running updates in LXC containers.
## Architecture
### Files
| File | Purpose |
| ----------------------- | ------------------------------------------- |
| `vm/app-deployer-vm.sh` | Main user-facing script |
| `misc/vm-app.func` | Core library for VM app deployment |
| `misc/vm-core.func` | Shared VM functions (colors, spinner, etc.) |
| `misc/cloud-init.func` | Cloud-Init configuration (optional) |
### Key Design Decisions
1. **Install scripts run unmodified** — The same `install/*.sh` scripts that work in LXC containers work inside VMs. The environment (`FUNCTIONS_FILE_PATH`, exports) is replicated identically.
2. **Image customization via `virt-customize`** — All dependencies are installed and the app install script runs live inside the qcow2 image during build. No SSH or guest agent required during setup.
3. **Live installation** — The install script runs during image build (not on first boot), so the application is ready immediately when the VM starts.
4. **Update via CT script URL** — Run the same `bash -c "$(curl ...ct/<app>.sh)"` command inside the VM, just like in an LXC container.
### Environment Variables (set during image build)
| Variable | Description |
| ----------------------- | ---------------------------------- |
| `FUNCTIONS_FILE_PATH` | Full contents of `install.func` |
| `APPLICATION` | App display name (e.g. "Yamtrack") |
| `app` | App identifier (e.g. "yamtrack") |
| `VERBOSE` | "no" (silent mode) |
| `SSH_ROOT` | "yes" |
| `PCT_OSTYPE` | OS type (debian/ubuntu) |
| `PCT_OSVERSION` | OS version (12/13/22.04/24.04) |
| `COMMUNITY_SCRIPTS_URL` | Repository base URL |
| `DEPLOY_TARGET` | "vm" (distinguishes from LXC) |
### VM Directory Structure
```
/opt/community-scripts/
├── install.func # Function library
└── tools.func # Helper functions
```
## Limitations
- **Alpine-based apps**: Currently only Debian/Ubuntu VMs are supported. Alpine install scripts are not compatible.
- **LXC-specific features**: Some CT features (FUSE, TUN, GPU passthrough) are configured differently in VMs.
- **`cleanup_lxc`**: This function works fine in VMs (it only cleans package caches), but the name is LXC-centric.
## Troubleshooting
### Check build log
If the installation fails during image build, check the log on the Proxmox host:
```bash
cat /tmp/vm-app-install.log
```
### Re-run installation
Re-build the VM from scratch — since the app is installed during image build, there is no in-VM reinstall mechanism. Simply delete the VM and run the deployer again.
### Verify installation worked
After the VM boots, SSH in and check if the application service is running:
```bash
systemctl status <app-service-name>
```

View File

@@ -1,5 +0,0 @@
{
"extends": ["next/core-web-vitals"],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"]
}

39
frontend/.gitignore vendored
View File

@@ -1,39 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# wrangler
.worker-next
.wrangler
# testing
/coverage
# next.js
/.next/
out
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# # local env files
# .env*.local
# .env
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -1,5 +0,0 @@
dist
node_modules
.next
build
.contentlayer

View File

@@ -1,3 +0,0 @@
{
"plugins": ["prettier-plugin-tailwindcss", "prettier-plugin-organize-imports"]
}

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2024 Bram Suurd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,17 +0,0 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "@/styles/globals.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}

View File

@@ -1,25 +0,0 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack: (config) => {
config.resolve.alias.canvas = false;
return config;
},
images: {
remotePatterns: [
{
protocol: "https",
hostname: "**",
},
],
},
env: {
BASE_PATH: "ProxmoxVED",
},
output: "export",
basePath: `/ProxmoxVED`,
};
export default nextConfig;

10816
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

93
frontend/package.json generated
View File

@@ -1,93 +0,0 @@
{
"name": "proxmox-helper-scripts-website",
"version": "1.0.0",
"license": "MIT",
"private": true,
"author": {
"name": "Bram Suurd",
"url": "https://github.com/community-scripts"
},
"type": "module",
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint",
"test": "vitest",
"deploy": "next build && touch out/.nojekyll && git add out/ && git commit -m \"Deploy\" && git subtree push --prefix out origin gh-pages",
"format:write": "prettier --write \"**/*.{ts,tsx,mdx}\" --cache",
"format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@radix-ui/react-accordion": "^1.2.3",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.6",
"@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-navigation-menu": "^1.2.5",
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-switch": "^1.1.3",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-tooltip": "^1.1.8",
"@tanstack/react-query": "^5.71.1",
"chart.js": "^4.4.8",
"chartjs-plugin-datalabels": "^2.2.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"date-fns": "^4.1.0",
"framer-motion": "^11.18.2",
"fuse.js": "^7.1.0",
"lucide-react": "^0.453.0",
"mini-svg-data-uri": "^1.4.4",
"next": "15.5.7",
"next-themes": "^0.3.0",
"nuqs": "^2.4.1",
"pocketbase": "^0.21.5",
"prettier-plugin-organize-imports": "^4.1.0",
"react": "19.0.0",
"react-chartjs-2": "^5.3.0",
"react-code-blocks": "^0.1.6",
"react-datepicker": "^7.6.0",
"react-day-picker": "8.10.1",
"react-dom": "19.0.0",
"react-icons": "^5.5.0",
"react-simple-typewriter": "^5.0.1",
"sharp": "^0.33.5",
"simple-icons": "^13.21.0",
"sonner": "^1.7.4",
"tailwind-merge": "^2.6.0",
"zod": "^3.24.2"
},
"devDependencies": {
"@tanstack/eslint-plugin-query": "^5.68.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.2.0",
"@types/node": "^22.13.16",
"@types/react": "npm:types-react@19.0.0-rc.1",
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
"@typescript-eslint/eslint-plugin": "^8.29.0",
"@typescript-eslint/parser": "^8.29.0",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.23.0",
"eslint-config-next": "15.0.2",
"jsdom": "^25.0.1",
"postcss": "^8.5.3",
"prettier": "^3.5.3",
"prettier-plugin-tailwindcss": "^0.6.11",
"tailwindcss": "^3.4.17",
"tailwindcss-animate": "^1.0.7",
"tailwindcss-animated": "^1.1.2",
"typescript": "^5.8.2",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.1.1"
},
"overrides": {
"@types/react": "npm:types-react@19.0.0-rc.1",
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1"
}
}

View File

@@ -1,8 +0,0 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
},
};
export default config;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

View File

@@ -1,35 +0,0 @@
{
"name": "CronMaster",
"slug": "cronmaster",
"categories": [
1
],
"date_created": "2026-02-17",
"type": "pve",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://github.com/fccview/cronmaster",
"website": "https://github.com/fccview/cronmaster",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/cr-nmaster.webp",
"config_path": "/opt/cronmaster/.env",
"description": "Self-hosted cron job scheduler with web UI, live logs, auth and prebuilt binaries provided upstream.",
"install_methods": [
{
"type": "default",
"script": "tools/addon/cronmaster.sh",
"resources": {
"cpu": null,
"ram": null,
"hdd": null,
"os": null,
"version": null
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -1,44 +0,0 @@
{
"name": "ddclient",
"slug": "ddclient",
"categories": [
4
],
"date_created": "2026-01-31",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": null,
"documentation": "https://ddclient.net/",
"website": "https://ddclient.net/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/ddclient.webp",
"config_path": "/etc/ddclient.conf",
"description": "ddclient is a Perl client used to update dynamic DNS entries for accounts on a wide range of dynamic DNS service providers. It supports multiple protocols and providers, allowing automatic IP address updates for your domain names.",
"install_methods": [
{
"type": "default",
"script": "ct/ddclient.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 2,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"type": "info",
"text": "After installation, edit `/etc/ddclient.conf` with your dynamic DNS provider credentials"
},
{
"type": "info",
"text": "Sample configuration is created for Namecheap but can be modified for other providers"
}
]
}

View File

@@ -1,35 +0,0 @@
{
"name": "Frigate",
"slug": "frigate",
"categories": [
15
],
"date_created": "2025-07-02",
"type": "ct",
"updateable": true,
"privileged": false,
"config_path": "/config/config.yml",
"interface_port": 5000,
"documentation": "https://docs.frigate.video/",
"website": "https://frigate.video/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/frigate-light.webp",
"description": "Frigate is an open-source NVR built around real-time AI object detection for IP cameras.",
"install_methods": [
{
"type": "default",
"script": "ct/frigate.sh",
"resources": {
"cpu": 4,
"ram": 4096,
"hdd": 20,
"os": "Debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -1,40 +0,0 @@
{
"name": "ImmichFrame",
"slug": "immichframe",
"categories": [
13
],
"date_created": "2026-02-26",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8080,
"documentation": null,
"config_path": "/opt/immichframe/Config/Settings.yml",
"website": null,
"logo": "https://github.com/selfhst/icons/blob/main/webp/immich-frame.webp",
"description": "ImmichFrame is a digital photo frame web application that connects to your Immich server and displays your photos as a fullscreen slideshow.",
"install_methods": [
{
"type": "default",
"script": "ct/immichframe.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 8,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "After installation, edit `/opt/immichframe/Config/Settings.yml` and set ImmichServerUrl and ApiKey. Then restart the service with `systemctl restart immichframe`.",
"type": "info"
}
]
}

View File

@@ -1,44 +0,0 @@
{
"name": "iSponsorBlockTV",
"slug": "isponsorblocktv",
"categories": [
13
],
"date_created": "2026-01-25",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": null,
"documentation": "https://github.com/dmunozv04/iSponsorBlockTV/wiki",
"website": "https://github.com/dmunozv04/iSponsorBlockTV",
"logo": "https://raw.githubusercontent.com/ajayyy/SponsorBlock/master/public/icons/IconSponsorBlocker512px.png",
"config_path": "/var/lib/isponsorblocktv/config.json",
"description": "iSponsorBlockTV connects to YouTube TV clients and automatically skips SponsorBlock segments, mutes ads, and presses the Skip Ad button when available.",
"install_methods": [
{
"type": "default",
"script": "ct/isponsorblocktv.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "No web UI; run `iSponsorBlockTV setup` inside the container to configure.",
"type": "info"
},
{
"text": "SSDP auto-discovery requires multicast on your bridge; manual pairing works without it.",
"type": "info"
}
]
}

View File

@@ -1,50 +0,0 @@
{
"name": "NetBird",
"slug": "netbird",
"categories": [4],
"date_created": "2025-12-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": null,
"documentation": "https://docs.netbird.io/",
"website": "https://netbird.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/netbird.webp",
"config_path": "/etc/netbird/config.json",
"description": "NetBird is an open source VPN management platform that creates secure peer-to-peer networks using WireGuard. It enables secure connectivity between devices anywhere in the world without complex firewall configurations or port forwarding. NetBird offers features like zero-configuration networking, SSO integration, access control policies, and a centralized management dashboard. It's designed to be simple to deploy and manage, making it ideal for connecting remote teams, securing IoT devices, or building secure infrastructure networks.",
"install_methods": [
{
"type": "default",
"script": "ct/netbird.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 4,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "The NetBird client (agent) allows a peer to join a pre-existing NetBird deployment. If a NetBird deployment is not yet available, there are both managed and self-hosted options available.",
"type": "info"
},
{
"text": "After installation, enter the container and run `netbird` to view the commands.",
"type": "info"
},
{
"text": "Use a Setup Key from your NetBird dashboard or SSO login to authenticate during setup or in the container.",
"type": "info"
},
{
"text": "Check connection status with `netbird status`.",
"type": "info"
}
]
}

View File

@@ -1,56 +0,0 @@
{
"name": "Papra",
"slug": "papra",
"categories": [
12
],
"date_created": "2025-12-30",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 1221,
"documentation": "https://github.com/CorentinTh/papra",
"website": "https://github.com/CorentinTh/papra",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/papra.webp",
"config_path": "/opt/papra/.env",
"description": "Papra is a modern, self-hosted document management system with full-text search, OCR support, and automatic document processing. Built with Node.js and featuring a clean web interface for organizing and managing your documents.",
"install_methods": [
{
"type": "default",
"script": "ct/papra.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 10,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "First visit will prompt you to create an account",
"type": "info"
},
{
"text": "Tesseract OCR is pre-installed for all languages",
"type": "info"
},
{
"text": "Documents are stored in /opt/papra/app-data/documents",
"type": "info"
},
{
"text": "Ingestion folder available at /opt/papra/ingestion for automatic document import",
"type": "info"
},
{
"text": "Email functionality runs in dry-run mode by default",
"type": "warning"
}
]
}

View File

@@ -1,48 +0,0 @@
{
"name": "SeaweedFS",
"slug": "seaweedfs",
"categories": [
11
],
"date_created": "2026-02-22",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 9333,
"documentation": "https://github.com/seaweedfs/seaweedfs/wiki",
"website": "https://seaweedfs.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/seaweedfs.webp",
"config_path": "",
"description": "SeaweedFS is a fast distributed storage system for blobs, objects, files, and data lakes, with O(1) disk seek, S3 API, FUSE mount, WebDAV, and cloud tiering support.",
"install_methods": [
{
"type": "default",
"script": "ct/seaweedfs.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 16,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Master UI available at port 9333, Filer UI at port 8888, S3 API at port 8333.",
"type": "info"
},
{
"text": "Data is stored in /opt/seaweedfs-data.",
"type": "info"
},
{
"text": "FUSE mounting requires fuse3 (pre-installed).",
"type": "info"
}
]
}

View File

@@ -1,44 +0,0 @@
{
"name": "Split Pro",
"slug": "split-pro",
"categories": [
12
],
"date_created": "2026-02-12",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://github.com/oss-apps/split-pro/blob/main/docker/README.md",
"website": "https://github.com/oss-apps/split-pro",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/splitpro.webp",
"config_path": "/opt/split-pro/.env",
"description": "SplitPro is a self-hosted, open source way to share expenses with friends. It is designed as a replacement for Splitwise.",
"install_methods": [
{
"type": "default",
"script": "ct/split-pro.sh",
"resources": {
"cpu": 2,
"ram": 4096,
"hdd": 6,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Before first use you must configure email credentials or authentication (OAuth/OIDC) provider in `/opt/split-pro/.env` and restart the service `systemctl restart split-pro`.",
"type": "warning"
},
{
"text": "Receipt uploads are stored in `/opt/split-pro_data/uploads`",
"type": "info"
}
]
}

View File

@@ -1,44 +0,0 @@
{
"name": "Yamtrack",
"slug": "yamtrack",
"categories": [
13
],
"date_created": "2026-02-22",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8000,
"documentation": "https://github.com/FuzzyGrim/Yamtrack/wiki",
"website": "https://github.com/FuzzyGrim/Yamtrack",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/yamtrack.webp",
"config_path": "/opt/yamtrack/src/.env",
"description": "Yamtrack is a self-hosted media tracker for movies, TV shows, anime, manga, video games, books, comics, and board games with multi-user support and Celery-powered background tasks.",
"install_methods": [
{
"type": "default",
"script": "ct/yamtrack.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Set API keys (TMDB_API, MAL_API, IGDB_ID, IGDB_SECRET) in /opt/yamtrack/src/.env to enable media search from external providers.",
"type": "info"
},
{
"text": "If using a reverse proxy, set the URLS variable in .env to your external URL (e.g., URLS=https://yamtrack.example.com).",
"type": "warning"
}
]
}

Some files were not shown because too many files have changed in this diff Show More