The Proxmox helper scripts are community-scripts/ProxmoxVE, the MIT-licensed continuation of tteck’s project. You copy a one-line command from community-scripts.org into the Proxmox host shell, choose Default or Advanced, and it builds an LXC container or VM as root, fetching more code from GitHub while it runs. Back up the host first.
Contents
If you run a Proxmox homelab, you have seen the one-liners. A forum post or a YouTube comment says “just paste this,” you copy a bash -c "$(curl ...)" command into your Proxmox shell, and a few minutes later you have a configured LXC container running Jellyfin, AdGuard or Home Assistant. They are the community-scripts ProxmoxVE helper scripts, the project formerly known as tteck’s Proxmox scripts. On September 28, 2026 the repository had 29,691 stars on GitHub.
The question people type into a search bar before pasting that command is the right one: is this safe?
The answer is “mostly, with conditions”. I read the current source to write this, and the part that changes the calculus is that the script you paste is not the only code that runs. Here is how they are used, what they do as root, where the real risk lives, and a practical way to use them without gambling your node.
The short answer
- These are legitimate, community-maintained scripts under the MIT license, built on tteck’s original work. They are not malware.
- They run as root on your Proxmox host, and they download more code from two GitHub repositories while they run. Reviewing the one file the command points at does not show you everything.
- The code is now written by a community team, not by tteck. That is a reason to re-examine your assumptions, not to panic.
- On a test node the risk is low. On a host you cannot afford to lose, read the script and back up first.
How to run a helper script
The project’s README gives the route, and it is short:
- Go to community-scripts.org and search for the service, for example “Home Assistant”, “Nginx Proxy Manager” or “Jellyfin”.
- Copy the one-line install command from the script’s page.
- Open the shell on the Proxmox host itself and paste it.
- Choose Default or Advanced and follow the prompts.
Default picks the CPU, RAM and storage for you and asks only the questions it must. The README says most of those installs finish in under five minutes. Advanced gives you control over the container settings, networking, storage backend and the application’s own configuration before anything is installed. I would use Advanced on any host that matters, because it is where you see what the script is about to set.
The README lists what you need: Proxmox VE 8.4, 9.0, 9.1 or 9.2, root shell access on the host, and an internet connection during the install. After the install, each container ships with a post-install helper reached from the Proxmox shell. It applies updates to the installed service, changes its settings without hand-editing config files, and gives basic troubleshooting and log access. The engine’s update notes say every container it builds gets /usr/bin/update, and that running it pulls the app’s script from the repository again. An update runs live code the same way an install does.
New scripts do not land in the main repository first. The README says they go to a separate repository, ProxmoxVED, where they are tested before they move over, and the project publishes a security policy for reporting vulnerabilities.
For a worked example, my AdGuard Home on Proxmox guide walks through one script’s defaults and the two jobs it leaves to you.
What the helper scripts are
The project lives at community-scripts/ProxmoxVE and covers hundreds of services, from media servers and home automation to databases, networking tools and monitoring. The README’s requirements table lists “Root shell access on the Proxmox host.”
The provenance matters. The scripts began as tteck’s personal project, tteck/Proxmox. A community team carries them now as community-scripts/ProxmoxVE, licensed MIT and footnoted “In memory of tteck.” tteck’s repository was archived on November 2, 2024; its README points to the new home and still tells readers to “thoroughly evaluate scripts and automation tasks obtained from external sources.” That handover is a good outcome for an orphaned project — and the crux of the safety question, which is a trust question.
What runs as root
When you paste a helper-script one-liner, it fetches a script from GitHub and executes it as root. That much is obvious. Less obvious is what that script does next.
The script is mostly a loader. Its opening lines, here from ct/jellyfin.sh, name where the app scripts come from and pull in a shared engine:
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
If there is no core checkout beside the script’s own repository checkout (or one named in COMMUNITY_SCRIPTS_CORE_DIR), and there is none when you paste a one-liner, it downloads core/build.func from the main branch of a second repository, community-scripts/core, and runs it in your shell. That repository describes itself as “the shared Bash libraries that every community script runs on: the whiptail wizard, container and VM creation, the in-container installer, error handling, telemetry and the helper library.” The AdGuard Home script starts the same way.
The engine then fetches the rest of itself. Its loading guide says it pulls every file on its engine list concurrently into memory for that run, and core/build.func sources anything else it needs with source <(_cs_download ...). The app’s own installer comes from the ProxmoxVE repository (the _CS_DEFAULT_URL line above) and runs inside the new container. Both come from main.
So a single “review the script” step is misleading. The file you read is a loader that, at runtime, pulls an engine from one repository and an installer from another. The engine runs as root on your host; the installer runs as root inside the container it builds. You are trusting the current state of two repositories at the moment you run it — not the static text you skimmed.
The engine does what a capable installer does, and it is a lot. Its Advanced wizard (ui/advanced.func) and its Proxmox backend (pve/backend.func) between them:
- Create an LXC container with the CPU, RAM and disk you choose.
- Configure its networking: DHCP or static IP, IPv6, VLAN tags, MTU, bridge selection.
- Ask which storage pool to use for the container and its template, in Default and Advanced mode alike.
- Set security-relevant options: SSH keys, the root password, GPU passthrough, container nesting, FUSE and TUN.
- Apply container settings: timezone, hostname, DNS, APT caching, tags, protection.
None of that is malicious. But every one of those actions happens with full root authority on your hypervisor, driven by code fetched live from the internet.
So where is the real risk?
It is not “the maintainers are bad actors.” The repo is public, popular, MIT-licensed and reviewable. The risk is structural, and it is the same risk as any curl-to-bash-as-root workflow:
- You are trusting a moving target. The one-liner pulls from
mainin two repositories. Code that was clean last week is not guaranteed to be the code you run today. There is no review step on your side between “a commit lands” and “it executes as root on your box.” - The trust handover is real. The people writing the code today are not the person who wrote it first. “I trust this project” is a decision to make on purpose, not one to inherit.
- Supply-chain compromise happens. In 2024 NVD recorded CVE-2024-3094: “Malicious code was discovered in the upstream tarballs of xz, starting with version 5.6.0.” Widely trusted open-source tooling was compromised at the source. A popular script repository whose code runs as root on hypervisors is the kind of target that history says to treat carefully.
- The blast radius is your whole node. Running as root, a bad or buggy script can wipe data, misconfigure the host, or install something unintended. One guide puts the worst case as “malware, a wiped drive, or a compromised Proxmox node.”
None of this says the maintainers are doing anything wrong. The point is that “it has been fine so far” and “it is safe to run blind on my production host” are two different statements.
How to vet a helper script (the workflow I’d use)
You do not have to choose between “paste blindly” and “never use them.” A few habits turn a gamble into a calculated, reversible decision:
- Read it before you run it. Open the raw GitHub URL the one-liner points at and read it. It loads the engine from
community-scripts/core, so skim the engine’score/build.funcand its loading guide once to understand what the shared code does. You are not auditing every line forever; you are confirming it does what it claims and noting where it fetches code from. - Back up what it can touch first. A Proxmox VE backup covers guests: the backup chapter describes backups as “always full backups - containing the VM/CT configuration and all data.” Back up the VMs and containers you care about before running anything new. The host itself is a different job: Proxmox Backup Server’s client can archive the host’s files (
proxmox-backup-client backup root.pxar:/, pointed at your server as the repository). That is a file archive, and I would not count it as a quick way back for a host a script has broken. - Test on a non-critical node. If you run more than one box, try new scripts on the one you would not cry over. If you run one node, that is more reason to do steps 1 and 2.
- Run from local checkouts to run what you reviewed. Saving the one-liner’s script to a file and running that does not freeze anything: the engine and the installer are still fetched from
main. The engine’s loading guide says a local checkout is “used when found.” Clonecommunity-scripts/coreandcommunity-scripts/ProxmoxVEside by side, check each out at the commit you read (a detached HEAD, not a branch), and run the script from the checkout (cd ProxmoxVE && bash ct/<app>.sh). The host side then runs from your files. The container still downloads its share of the engine from GitHub, because it “has its own filesystem, so the host’s copy cannot help it”; with a detached HEAD the engine points that download at your commit (host/source-origin.func), and with a branch checked out it follows the branch. - Treat an update like an install.
updateinside a container pulls the app’s script from the repository again, so back up that container before you run it. - Keep the service in an unprivileged LXC where the app supports it, and do not turn on nesting, FUSE or passthrough unless the workload needs them. Least privilege limits what a future problem can reach.
If that sounds like more friction than “paste this,” that is the trade. The scripts buy you speed. These habits buy back the safety you skipped. On a test node, steps 1 and 2 are plenty. On a host running things you care about, do all six.
When to use them, and when not to
| Situation | Verdict |
|---|---|
| Spinning up a throwaway service on a test node | Fine: read it, run it, move on |
| Learning Proxmox and what a clean LXC setup looks like | Good, if you read the script so you learn what it did |
| Installing on your main node with data you care about | Only after a guest backup and a read-through |
| Production, or anything you cannot restore quickly | Do the install yourself, or run reviewed local checkouts |
| You cannot or will not read a bash script at all | Reconsider; that is the user these workflows are riskiest for |
There is also a long-term argument worth taking seriously: the scripts are a fast accelerator and a poor teacher. A user quoted by mrplanb put it this way: “They are good for learning short term, but when you find yourself getting serious on a project, you’re better off learning to do it without the scripts.” Knowing how to create and configure an LXC container yourself, or set up a node from scratch, means you never depend on a third party’s root access to your hypervisor.
The verdict
The Proxmox helper scripts are not a scam and not malware. They are a well-run, MIT-licensed, community-maintained project doing a useful thing. But “is it safe?” is the wrong shape of question. The accurate version is: “am I comfortable letting code fetched live from GitHub run as root on this specific host, and could I recover if it went wrong?”
On a test node, the answer is almost always yes. Use them, and read them to learn. On a host you cannot afford to lose, make it a yes on purpose: read the script, understand that it pulls more code at runtime, back up your guests first, and keep your containers least-privileged. Then take the few-minute install without betting the homelab on it.
Sources
- community-scripts/ProxmoxVE repository and README (MIT license, “In memory of tteck,” requirements, Default and Advanced modes, post-install helper, ProxmoxVED testing)
- community-scripts/core, the shared engine (README)
- community-scripts/core, “How loading works” (two roots, local checkout first,
mainby default, the prefetch) - community-scripts/core, “update: what happens inside a container”
ct/jellyfin.sh, the engine bootstrap lines- Proxmox VE documentation, Backup and Restore
- Proxmox Backup Server documentation, Backup Client Usage (host file archives)
- tteck/Proxmox, the original repository (archived November 2, 2024)
- NVD, CVE-2024-3094 (xz upstream tarballs)
- “Proxmox Helper Scripts: Handy Shortcut or Hidden Security Risk?”, mrplanb.com (2025)
- Proxmox forum: “How safe are the Updatable PVE Helper-Scripts”
Frequently asked questions
What are the Proxmox helper scripts?
How do I run a Proxmox helper script?
How do I update an app installed by a helper script?
Are the community-scripts (tteck) Proxmox helper scripts safe to run?
Who maintains the Proxmox helper scripts now that tteck passed away?
Does reading the install one-liner’s script tell me everything it will do?
What is the safest way to run a Proxmox helper script?
Can a Proxmox helper script break or compromise my whole node?
Sources and corrections
- Last updated
- Methodology
- See our methodology for research and review standards.
- Update log
- 2026-08-14 — Refreshed the build.func evidence block, which had gone stale. The article quoted three verbatim
source <(curl -fsSL ...)/source <(wget -qO- ...)lines as the framework’s remote-code bootstrap. Re-read against the live source (misc/build.funcshared installer framework, 7,312 lines, fetched 2026-08-14) and those lines no longer exist: upstream refactored to a_bootstrap_sourcehelper that captures the download, aborts on an empty fetch, and verifies an expected function was defined (exit 115 on failure) - with an in-source comment stating the old process-substitution form hid the download exit code. The page now quotes the current loader and credits the hardening. The underlying claim is unchanged and re-verified: api.func, core.func and error_handler.func are still fetched from themainbranch at runtime and sourced as root, as are tools.func, install.func and the per-app installer under install/. - 2026-08-15 — Correction to the 2026-08-14 build.func refresh. That update credited the new
_bootstrap_sourceloader and concluded “the current code fails closed instead”, which overstated the hardening. I re-read it against the same live source (7,312 lines, re-fetched 2026-08-15): the fail-closed loader covers only the three bootstrap files (api.func, core.func, error_handler.func) at lines 117-120. The entry pointstart()at line 4113 still runssource <(curl -fsSL .../misc/tools.func), and the dev-mode MOTD path at line 5519 still sources install.func the same way, the exact process-substitution form the project’s own in-source comment at line 91 says “hides the download exit code.” The paragraph now states the hardening is partial and names where the old form survives. - 2026-09-28 — Retitled around the safety question and added how to run and update a script from the project’s README. The scripts no longer load
misc/build.func: thect/scripts checked (Jellyfin, AdGuard Home) now load the engine from a separate repository,community-scripts/core, so the section on what runs as root describes that engine, and the vetting steps follow the engine’s own code and documents (loading,host/source-origin.funcfor commit pinning, updates) and the Proxmox VE backup chapter. Removed a wizard step count, an install count and a hypervisor count that no source gave, and a user quotation that neither cited page carries. The xz example now follows the NVD record.
- 2026-08-14 — Refreshed the build.func evidence block, which had gone stale. The article quoted three verbatim
- Corrections
- Spotted an error or a stale number? Email contact@techfuelhq.com. Confirmed corrections are recorded here with the date and change.