* docker-vm, pve-privilege-converter: source from GitHub raw instead of gitea mirror
* docker-vm, pve-privilege-converter, vm-core.func: source from GitHub raw instead of gitea mirror
* Post the command that tests a ct/ or install/ change
Reviewing a script change meant working out the URL yourself, and the
obvious guess is wrong: curling the branch URL alone gives you the ct/
script from the PR and the install/ script from main, because each script
pins _CS_DEFAULT_URL to main and that pin is what fills
COMMUNITY_SCRIPTS_URL when it is unset. Frequently the install script is
the only thing that changed.
So the comment spells out both lines, per changed app.
Only for scripts already on the core bootstrap. The older one-liner
resolves everything from ProxmoxVE/main and ignores the variable, so a
command built for it would install main and look like it passed -- worse
than no comment. Those are named instead, with what to do about them.
pull_request_target for fork PRs, and nothing from the PR is checked out
or executed: the file list and the bootstrap line come from the API, and
a branch name that is not [A-Za-z0-9._/-]+ stops the run rather than
reaching a fenced code block.
* Update .github/workflows/pr-test-command.yml
Co-authored-by: Sam Heinz <sam@samheinz.com>
---------
Co-authored-by: Sam Heinz <sam@samheinz.com>
* calibre-web: point cps at explicit db path, src-layout package has no default anymore
* calibre-web: fix empty-library bootstrap, migrate pre-existing library on update
* Teach the PocketBase bot every field
The bot covered most of script_scripts but not categories, has_arm,
execute_in or app_vars, so those had to be edited by hand in the admin UI.
categories is a relation, so names are resolved against script_categories
and ids are accepted too - a copy out of the PocketBase UI works either way.
app_vars is a JSON column and rides the code-block 'set' path with its
content parsed rather than stored verbatim, so readers get an object.
cpu/ram/hdd/os/version live inside install_methods, and '/pocketbase immich
hdd=25' is how people ask for them. They now route to the default (non-Alpine)
method instead of being rejected as unknown fields, the reply names which
method was touched, and the value syncs into ct/<slug>.sh like the 'method'
path already does.
* Add screenshots and type to the bot
Two gaps were left. type is a relation to z_ref_script_types, so it needs the
same name-to-id resolution as categories - people write "ct", not a
fifteen-character id. Screenshots had no command at all.
The screenshot subcommand hands the URLs to the frontend's /api/screenshots
rather than fetching images inside a workflow. That endpoint already checks
the content type and size and attaches the file to PocketBase; doing it a
second time here would be a second set of bugs. It needs
SCREENSHOT_IMPORT_SECRET, and says so plainly when it is missing instead of
failing halfway.
slug stays deliberately out of reach. It is the URL, the JSON filename and the
ct/<slug>.sh path at once, so renaming it is a migration rather than an edit,
and the help text now says that instead of leaving people to wonder.
* Move the top 25 scripts onto the core engine
The engine work of the last few days reaches 30 of 561 ct scripts, about 5% of
ProxmoxVE traffic: retry on engine downloads, exit 227 instead of a misfiled
dpkg error, the umask fix that stops a hardened host producing containers apt
cannot resolve in, the TMPDIR guard, the toolchain restore. All of it has been
sitting where almost nobody runs it.
All eighteen at once rather than in waves. A slow rollout does not exercise the
paths only some scripts take, and broad exposure is what surfaces bugs -- a
deliberate call about release risk.
Checked before touching anything, because "migrate" meant far more than a line
swap last time:
- None of the eighteen has an alpine-* variant, so there is no merge to do.
- No script references misc/ outside its bootstrap line.
- Of the 61 functions that exist only in misc/, none is called by any of them.
So it is one line per script, and every head is now byte-identical to the ones
migrated earlier. With these, ProxmoxVE goes from 30 scripts on the core engine
to 48 -- and from roughly 5% of traffic to the majority, since these are the
ones people actually install.
Two to watch: immich sits at 44.7% success and vaultwarden at 42.1% before
this. If their numbers move, the engine is one of two changed variables rather
than the only one.
* Move update-apps onto the core engine
Entry 11 of the list and the only one that is not a ct script, so it was left
out of the previous commit. It is a host tool: it never used build.func at all,
it sources misc/core.func and misc/api.func directly.
The swap is therefore two lines rather than one, and worth checking rather than
assuming. It uses exactly five engine functions -- header_info,
init_tool_telemetry, msg_info, msg_ok, msg_error -- all present in the core, and
both files load standalone, which they had not had to do before: everywhere else
they arrive through build.func.
That completes the list. All 25 now run on the core engine.
Fixing this one matters beyond the migration: update-apps is what drives
unattended updates across every container on a host, and it is the path where
PHS_SILENT was being ignored (#16593). It now gets the engine that honours it.
* netbox: serve on plain HTTP too, port 80 forced HTTPS redirect broke reverse proxies
* Update netbox-install.sh for Apache configuration
Modify Apache configuration to serve NetBox on port 80.
* Set default ProxmoxVE raw URL in UPS script
Define `_CS_DEFAULT_URL` at the top of `ct/pve-ups.sh` and remove the outdated bootstrap comments, aligning the script with the newer URL-default pattern used for script sourcing.
* Branch var_cpu by OS where the two variants actually differ
The merged scripts branch var_ram, var_disk and var_version on var_os but
left var_cpu above the branch, so both variants inherited the Debian value.
On Vaultwarden that meant an Alpine container was told it wanted four cores
for an update that runs apk and restarts a service.
Only seven scripts are affected. Comparing each merged script against the
alpine-* script it replaced, 22 of the 29 already had the same CPU count on
both sides, so moving the line there would be churn with no behaviour change.
These seven did not:
docker, forgejo, ironclaw, syncthing, transmission, zigbee2mqtt 2 -> 1
vaultwarden 4 -> 1
The Alpine values are the ones those scripts carried before the merge, read
back out of the deleted alpine-* files rather than picked. The Debian arm
keeps what it has now.
Needs the matching core change: until build.func derives var_os inside a
container, an update never reaches the Alpine arm at all.
* fix: source url
* Update script to source build functions from URLs
---------
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
DocuSeal switched to its own PDFium fork (upstream commit "adjust pdfium",
2026-08-15) and now attaches functions that only exist in that build, e.g.
FPDFPage_GetAnnotCountRaw from the added fpdf_annots_raw.h. The generic
bblanchon/pdfium-binaries library the script installed does not export them,
so lib/pdfium.rb raises FFI::NotFoundError while Rails eager-loads and both
docuseal.service and docuseal-sidekiq.service fail to start:
Unable to load application: FFI::NotFoundError: Function
'FPDFPage_GetAnnotCountRaw' not found in [libpdfium.so]
Install the library from docusealco/pdfium-binaries instead, matching the
upstream Dockerfile. It is only published as a musl build (DocuSeal's image is
Alpine based), so the musl runtime is installed and its library directory is
added to the loader search path - the shared object needs "libc.so" (musl) at
dlopen time. Verified on glibc: the library loads, resolves the raw annotation
functions and renders pages correctly.
The update path now refreshes PDFium too, so existing containers are repaired
by running "update" even when DocuSeal itself is already up to date.
* Skip mount points during backup and clean install
Prevent accidental deletion or backup of mount points:
- In create_backup(), skip paths that are mount points with a warning
- In _deploy_source_tarball(), _deploy_unpacked_archive(), and fetch_and_deploy_from_url(), use find with mountpoint pruning to avoid deleting mount point directories during CLEAN_INSTALL
* change comments for new variant
Update `_deploy_source_tarball` and related helper comments to note that CLEAN_INSTALL wipes target contents including dotfiles while preserving mount points. This improves guidance around backup/restore of config dotfiles during source deployments.
* networkoptimizer: mitigate dotnet publish hang in LXC
* Optimize networkoptimizer.sh by removing duplicate restore
Removed redundant restore_backup call after deployment.
* Clean up comments in networkoptimizer-install.sh
Removed comments about MSBuild issues in the installation script.
* Let docker-install.sh take its three answers up front
The script asked three questions with no way to answer them in advance,
so a Docker container could not be deployed unattended: Portainer, the
Portainer Agent, and whether to expose the TCP socket.
Each now reads a variable and prompts only when it is unset, the same
shape install/forgejo-runner-install.sh already uses:
var_portainer yes | no
var_portainer_agent yes | no
var_docker_socket n | l (127.0.0.1) | a (0.0.0.0)
Interactive behaviour is unchanged — with nothing set, all three still
ask exactly as before.
The matching declaration for the script's PocketBase record, which the
website generator reads to offer these as form fields:
"app_vars": [
{"name":"var_portainer","label":"Install Portainer","type":"boolean","default":"no"},
{"name":"var_portainer_agent","label":"Install Portainer Agent","type":"boolean","default":"no",
"help":"Only used when Portainer itself is not installed"},
{"name":"var_docker_socket","label":"Expose Docker TCP socket","type":"select",
"options":["n","l","a"],"default":"n",
"help":"l = 127.0.0.1 only, a = all interfaces (insecure)"}
]
CONTRIBUTING.md documents the convention so the next script follows it.
* Let docker-install.sh take its three answers up front
The script asked three questions with no way to answer them in advance,
so a Docker container could not be deployed unattended: Portainer, the
Portainer Agent, and whether to expose the TCP socket.
Each now reads a variable and prompts only when it is unset, the same
shape install/forgejo-runner-install.sh already uses:
var_portainer yes | no
var_portainer_agent yes | no
var_docker_socket n | l (127.0.0.1) | a (0.0.0.0)
Interactive behaviour is unchanged — with nothing set, all three still
ask exactly as before.
The matching declaration for the script's PocketBase record, which the
website generator reads to offer these as form fields:
"app_vars": [
{"name":"var_portainer","label":"Install Portainer","type":"boolean","default":"no"},
{"name":"var_portainer_agent","label":"Install Portainer Agent","type":"boolean","default":"no",
"help":"Only used when Portainer itself is not installed"},
{"name":"var_docker_socket","label":"Expose Docker TCP socket","type":"select",
"options":["n","l","a"],"default":"n",
"help":"l = 127.0.0.1 only, a = all interfaces (insecure)"}
]
CONTRIBUTING.md documents the convention so the next script follows it.
* Let forgejo-runner and pangolin take their answers up front
forgejo-runner already exported two of the three values its install
script requires, but not var_forgejo_runner_uuid — so an unattended
install passed the ct-level guard and then stopped at a prompt inside
the container, which is the one place nobody can answer it. The guard
missed it for the same reason.
pangolin asked for its URL and email with no way to supply them. Both
sides are needed: the read in install/ now only fires when the variable
is unset, and ct/ exports it, because lxc-attach carries the caller's
environment but only what was exported.
Reverts the docker change from the previous commit; it is superseded by
work on another branch.
* Teach the PocketBase workflows the capability fields
All three wrote fields the site no longer reads. The slash bot and the
AI bot accepted has_arm=true and github=owner/repo; push-json mapped
has_arm into the payload. After the schema change those writes would
have gone to columns that are not there.
architectures and platforms are multi-selects over a closed set, so
both bots reject an unknown value instead of storing it — the same
guarantee the field type gives in the admin UI.
push-json still reads has_arm when architectures is absent, because
ProxmoxVED's json files carry the old key until they are converted.
* Drop the docker change again
It came back through the merge in 35735dae: the branch was pushed
before the revert, so merging the remote copy restored it. Removing it
forward rather than rewriting history that is already published.