The Proxmox VE helper scripts are the one-line installers that turn a fresh Proxmox host into a Home Assistant box, a Jellyfin server or a Docker VM in a few minutes. Most guides stop at “copy the command, paste it into the shell”. This one reads the code first: what a script changes on your host, how to pin it so the same code runs every time, and which scripts belong on a server you depend on.
Short answer
Proxmox helper scripts at a glance (read 2 November 2026)
- Repository
- github.com/community-scripts/ProxmoxVE
- Website with every command
- community-scripts.org
- Engine (since August 2026)
- github.com/community-scripts/core
- Supported Proxmox VE
- 8.0 to 8.4 and 9.0 to 9.2 (README)
- Runs as
- root on the Proxmox host
- Scripts in the repo
- 649 container, 20 VM, 35 host tools
- License
- MIT
- Original author
- tteck (repo tteck/Proxmox, archived November 2024)
What the Proxmox helper scripts are, and who maintains them
The collection began in August 2021 as tteck’s personal repository, tteck/Proxmox. When he could no longer maintain it, the project moved to the community-scripts organization on 1 November 2024, with the full history carried over (18,582 commits on the day we checked). The old repository is archived. The README now credits tteck “in memory”, and a core team of volunteers reviews changes. New scripts are tested in a separate DevScripts repository before they reach the main one.
That history matters when you copy a command from an old forum post or video. A URL that contains tteck/Proxmox still downloads, but it runs code frozen in November 2024, and its version check only accepts pve-manager/8.1 to 8.3. On Proxmox VE 9 it stops with “This version of Proxmox Virtual Environment is not supported”. Always start from the current repository or community-scripts.org.
| Folder | What is in it | Where it runs |
|---|---|---|
ct/ | The script you paste: the app's name, default resources and update function | Proxmox host |
install/ | What gets installed inside the new container | Inside the container |
vm/ | Full virtual machines: Debian, Ubuntu, Home Assistant OS, OPNsense, TrueNAS, a Docker VM and others | Proxmox host |
tools/pve/ | Host tools: post-install, microcode, kernel clean and pin, container updates | Proxmox host |
tools/addon/ | Add-ons installed into an existing container, such as Tailscale or Portainer | Host or container |
Since August 2026 the shared engine (the code that asks the questions, creates the container and handles errors) lives in a second repository, community-scripts/core. The scripts in ct/ are now short: the Debian one is 45 lines, and its third line loads the engine from core at run time. Keep that in mind for the pinning section below, because a pin on one repository no longer pins the other. The README also notes that the same scripts run unchanged on an Incus host, through the project’s separate Incus repository.
The most-installed helper scripts
If you came for a specific script, these were the ten most installed in the last 30 days according to the counter on community-scripts.org (read 2 November 2026). Each runs with the same command as the Debian example below; only the path at the end of the URL changes.
| Script | Type | Installs (30 days) | Path in the command URL |
|---|---|---|---|
| Docker | Container | 5,897 | ct/docker.sh |
| Debian | Container | 4,638 | ct/debian.sh |
| Immich | Container | 4,278 | ct/immich.sh |
| Jellyfin Media Server | Container | 3,956 | ct/jellyfin.sh |
| AdGuard Home | Container | 3,874 | ct/adguard.sh |
| Home Assistant OS | VM | 3,483 | vm/haos-vm.sh |
| Pi-hole | Container | 3,477 | ct/pihole.sh |
| Nginx Proxy Manager | Container | 3,385 | ct/nginxproxymanager.sh |
| Tailscale | Add-on for an existing container | 3,308 | tools/addon/add-tailscale-lxc.sh |
| Frigate | Container | 2,688 | ct/frigate.sh |
What happens when you run a helper script
Every script page on the website gives one command in the same form. For the plain Debian container it is:
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/debian.sh)"curl -fsSL downloads the script quietly and fails on an HTTP error, the $(...) turns the file into a string, and bash -c runs that string. Nothing is saved to disk, so there is nothing left to read afterwards. main in the URL means “whatever is on the main branch right now”. We traced what a run does from the source, at the commits listed in the test box at the end:
- 1Load the engine from the second repository
Line 3 of
ct/debian.shsourcescore/build.funcfromcommunity-scripts/core, branchmain, unless you point it elsewhere. The engine then fetches around 20 more function files the same way. - 2Check the host
It stops unless it runs as root, in bash, on amd64 or arm64, on a Proxmox node with a supported version. Over SSH from outside the node’s network it warns and recommends the Proxmox web shell instead; sessions from the node itself or the same /24 get no warning.
- 3Ask about diagnostics, once
On the first run a dialog asks “Send Diagnostics of LXC Installation?”. Your answer is stored in
/usr/local/community-scripts/diagnostics. WithDIAGNOSTICS=yes, each install reports the app, the container’s resources, CPU, GPU and RAM facts and, when it fails, the failing command and its log lines totelemetry.community-scripts.org. Answer no, or setDIAGNOSTICS=noin that file, to send nothing. - 4Default or Advanced
Default asks only what it must, such as the storage when there is more than one. Advanced shows every setting below before anything is created.
- 5Download a template and create the container
It updates the template list with
pveam, downloads the OS template if it is not cached, and callspct createwith the next free ID. - 6Run the install half inside the container
It fetches
install/debian-install.shand runs it throughlxc-attach: update the OS, set up the message of the day, configure console login, clean up. For an app such as Uptime Kuma, this is where the app itself is downloaded. - 7Leave an update command behind
It writes
/usr/bin/updateinto the container. Typingupdatein the container console downloads the samect/script again, from the same branch, and runs its update function.
What Default mode gives you
Read these before you accept the defaults on a server rather than a home lab. They come from the engine’s built-in values and the Debian script’s own header; other apps set their own CPU, RAM and disk.
| Setting | Default | What to check |
|---|---|---|
| Container type | Unprivileged | Keep it. Some apps ask for privileged; read why first. |
| Debian resources | 1 vCPU, 512 MB RAM, 2 GB disk, Debian 13 | Each app script sets its own; Advanced changes them. |
| Network | vmbr0, IPv4 by DHCP, IPv6 off | Without a DHCP server on that bridge the container gets no address. Set a static IP in Advanced. |
| Features | nesting=1, plus keyctl=1 when unprivileged | Needed for Docker inside the container; also a wider surface. |
| SSH | Off | If you enable root SSH access, the engine sets PermitRootLogin yes. |
| Root password | Empty: root logs in on the console automatically | Set one in Advanced if anyone else can open the console. |
| Tags | community-script | Handy for finding them later in the web UI. |
How to read a helper script before you run it
The project’s own README says it plainly: the commands run as root on your host, so read the script before you paste it. Because the work is split into three parts, reading only the file in the URL is not enough. Download all three and page through them:
APP=debian
mkdir -p ~/cs-review && cd ~/cs-review
curl -fsSLO https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/$APP.sh
curl -fsSLO https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/$APP-install.sh
less $APP.sh $APP-install.sh
# every place the code downloads or runs something else
grep -nE 'curl|wget|source|bash -c|eval' $APP.sh $APP-install.shWhat to look for in the two files:
- The
var_lines at the top of thect/script: CPU, RAM, disk, OS version andvar_unprivileged. A0there means a privileged container. - Every URL. App installs often call
fetch_and_deploy_gh_release, which downloads the app’s latest GitHub release. Check that the repository it names is the app’s official one. - Anything that writes outside the container in the
ct/half:pct set, bind mounts, device passthrough, edits under/etc/pve. - The engine is the larger part:
core/build.funcand the files it loads come to several thousand lines. You do not have to read it every time, but read it once, and read its changes when you move your pin.
Pin a helper script to a commit
A URL with main in it can run different code tomorrow than it ran today. Pinning means replacing main with a full commit hash, so the code you read is the code you run. The common advice is to pin the script’s URL. Since the engine moved out, that pins only the 45-line script, while the engine still comes from core/main. Pin both repositories:
git ls-remote https://github.com/community-scripts/ProxmoxVE refs/heads/main
git ls-remote https://github.com/community-scripts/core refs/heads/mainS=7774a1a28d6e637c47a7476de3e9167fbe337d25 # ProxmoxVE commit you read
E=09fac1952f6050395aae8e6ecc9d4900c5c180d2 # core (engine) commit you read
COMMUNITY_SCRIPTS_URL=https://raw.githubusercontent.com/community-scripts/ProxmoxVE/$S \
COMMUNITY_SCRIPTS_CORE_URL=https://raw.githubusercontent.com/community-scripts/core/$E \
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/$S/ct/debian.sh)"Both variables are the ones the project documents for testing a fork or branch: COMMUNITY_SCRIPTS_URL decides where the install/ half comes from, COMMUNITY_SCRIPTS_CORE_URL where the engine comes from. The two hashes above are the heads of both branches on 2 November 2026; both URLs answered 200, and the pinned file’s SHA-256 matched our clone. Use the commits you actually read, not ours.
The stricter way: run from a local checkout
If you want to read diffs instead of URLs, clone both repositories next to each other and check out the commits you reviewed. The ct/ script looks for the engine at ../../core relative to itself and the engine finds install/ next to ct/. Everything still comes from the commits you checked out, but not all of it from disk: the half that runs inside the container downloads the engine files from GitHub, and in checkout mode the engine points that download at community-scripts/core at the short hash of your checkout. That detection needs git on the node, which a fresh install may not have:
apt install -y git
mkdir -p /root/cs && cd /root/cs
git clone https://github.com/community-scripts/ProxmoxVE.git
git clone https://github.com/community-scripts/core.git
git -C ProxmoxVE checkout 7774a1a28d6e637c47a7476de3e9167fbe337d25
git -C core checkout 09fac1952f6050395aae8e6ecc9d4900c5c180d2
bash /root/cs/ProxmoxVE/ct/debian.sh
# next time: see exactly what changed before you move the pin
git -C ProxmoxVE fetch && git -C ProxmoxVE log --oneline HEAD..origin/main -- ct/debian.sh install/debian-install.sh
git -C core fetch && git -C core diff --stat HEAD origin/mainTwo limits apply to every pin:
- A pin fixes the installer, not the app. 449 of the 635 files in
install/call the release helper, and its default version islatest. Two installs a month apart can get two app versions. - The
updatecommand inside the container reuses the scripts URL from the install and loads the engine fromcore/mainunless you set the variable again:COMMUNITY_SCRIPTS_CORE_URL=https://raw.githubusercontent.com/community-scripts/core/$E update.
The Proxmox post-install script: what it changes
The most-run host tool is post-pve-install.sh, usually the first thing people run on a new node. It asks before every change, but the prompts are short, so here is what each yes does on Proxmox VE 9. The first two rows only appear on a node that has no .sources file in /etc/apt/sources.list.d yet, such as an old 8.x layout upgraded by hand or a provider image. A fresh 9.x install, or a node upgraded with the official 8 to 9 guide, already has .sources files: the script shows “Deb822 sources detected”, leaves the source format alone and goes straight to the enterprise repository.
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/post-pve-install.sh)"| Prompt | What yes does | Watch out |
|---|---|---|
| Disable legacy sources? (only without .sources files) | Renames every *.list file in /etc/apt/sources.list.d to *.list.bak, copies sources.list to sources.list.bak and comments out its deb lines | Reversible: rename the .bak files back. Repositories you need must exist as .sources files afterwards. |
| Migrate to deb822 sources format? (only without .sources files) | Deletes any *.list file still in /etc/apt/sources.list.d and writes a new debian.sources for trixie | If you answered no to the previous prompt, repositories a provider or you added as .list files are gone without a backup. The new file lists main contrib only, without non-free-firmware, where Debian ships CPU microcode. |
| pve-enterprise | Keep, disable (Enabled: false) or delete the enterprise repository file | Disable rather than delete if you may buy a subscription later. |
| pve-no-subscription | Adds proxmox.sources with the free repository | The same change the Proxmox docs describe for hosts without a subscription. |
| Ceph repositories | Disables Ceph enterprise and adds Ceph no-subscription | Harmless if you do not use Ceph. |
| pve-test | Adds the test repository, disabled | Leave it disabled on a production node. |
| Subscription nag | Patches proxmoxlib.js and adds an APT hook that re-applies the patch after every package run | Vendor code changed on every update; a UI bug after an update may come from the patch. |
| Disable high availability | Stops and disables pve-ha-lrm and pve-ha-crm; a second prompt can disable corosync | Only on a single node. Never in a cluster. |
| Update Proxmox VE now? | Runs apt -y dist-upgrade with output hidden | You do not see what is upgraded; run it yourself if you want to read the list. |
| Reboot | Reboots the node | Every VM and container on it stops. |
Before you run it, keep a copy of what it edits. On a ZFS install a root snapshot is the cleanest undo; on the default ext4 or XFS layout copy the files:
cp -a /etc/apt /root/apt-before-post-install
# ZFS root only: check the dataset name first, then snapshot it
zfs list -o name | grep ROOT
zfs snapshot rpool/ROOT/pve-1@before-post-installOnly if the script wrote a new debian.sources (the migrate prompt above): add non-free-firmware back to its Components: lines and install intel-microcode or amd64-microcode with apt, so microcode keeps receiving updates. On a fresh Proxmox VE 9 install the file is untouched, and the Proxmox documentation lists non-free-firmware there by default.
Useful helper scripts for a server node
Most of the 649 container scripts are apps. The host tools in tools/pve/ are the ones that touch the node itself. We read each of these; this is what it does and whether we would run it on a production host:
| Script | What it does on the host | On a production node | Without the script |
|---|---|---|---|
post-pve-install | Repositories, nag patch, HA services, upgrade, reboot (table above) | Once, on a fresh node, reading each prompt | Edit the .sources files by hand |
microcode | Installs iucode-tool, lists every intel-microcode .deb in Debian’s pool, lets you pick one and installs it with dpkg -i (AMD branch the same with amd64-microcode) | Prefer the apt package, which gets updates | apt install intel-microcode |
kernel-clean | Lists old proxmox-kernel packages, purges the ones you select, runs autoremove | Fine; keep the running kernel and one older | apt purge proxmox-kernel-X.Y.Z-N-pve-signed |
kernel-pin | Wraps proxmox-boot-tool kernel pin in a menu | Fine, but the command is one line | proxmox-boot-tool kernel pin VERSION |
update-lxcs | Runs the package upgrade in every container via pct exec, lets you skip some. In Debian and Ubuntu containers that is apt-get update, dist-upgrade, autoremove, autoclean, and then rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED: it silently removes the PEP 668 marker that stops pip from installing into the system Python | After a backup, with a list of skips; check Python apps afterwards | pct exec ID -- sh -c 'apt-get update && apt-get -y dist-upgrade' |
cron-update-lxcs | Installs /usr/local/bin/update-lxcs.sh and a root crontab entry for unattended upgrades of all containers | No: unattended upgrades with no snapshot first | A backup job, then upgrades you watch |
fstrim | Runs pct fstrim per container, logs to /var/log/fstrim.log | Fine on thin storage | pct fstrim ID |
clean-lxcs | Deletes every file under /var/log and /tmp in each selected container. Debian/Ubuntu: also /var/cache and the APT lists, then autoremove. CentOS/RHEL family: yum clean all, then yum upgrade -y, so it also upgrades those containers | No: it wipes logs you may still need | pct exec ID -- apt-get clean |
host-backup | A tar.gz of directories you tick under /etc | A quick copy, not a backup strategy | vzdump plus a copy of /etc/pve |
scaling-governor | Sets the CPU frequency governor and adds a crontab line to keep it after reboots | Only if you measured a reason | Leave the default |
For the guests themselves, the VM scripts (debian-vm, ubuntu-vm, docker-vm, opnsense-vm) save the fiddly parts of building a cloud image VM, and they have no updater: you patch the guest like any other machine. If you are weighing a single Docker VM against many containers, installing Docker on Debian by hand takes about as long as the script and leaves nothing you have not read.
Production node or home lab?
Why people run them
- Minutes instead of an evening per app, with sane container defaults
- Readable bash under the MIT license, with every change in public git history
- Each container gets an
updatecommand, so updates are not forgotten - Active maintenance: commits land daily and new scripts are tested before they merge
What you take on
- Code from
mainruns as root on the hypervisor that holds every other guest - Three moving parts per run: script, engine and the app's latest release
- A failed step ends the run and removes the broken container by default: Enter or 60 seconds without an answer both remove it, only choosing keep (n, or option 2 in the recovery menu) saves it for debugging, so read the error first
- Diagnostics are on if you answered yes once, and stay on for every later run
Our rule of thumb: in a home lab, run them from the website and enjoy the time saved. On a node that carries customer or business workloads, pin both repositories, read the diff when you move the pin, avoid the nag patch and unattended updates, and test new scripts on a spare node first. If you are still choosing a hypervisor for that node, Hyper-V vs VMware covers the main commercial options, and what is Hyper-V the Windows one.
Snapshot and roll back
Undoing a helper script means undoing what it created, which is usually one container. Before an update or any change inside it, take a snapshot from the host:
pct snapshot 105 before-update
pct listsnapshot 105
# the update went wrong
pct rollback 105 before-update
# it worked: drop the snapshot again
pct delsnapshot 105 before-updateContainer snapshots need storage that supports them. local-lvm (LVM-thin) and local-zfs, the two layouts the Proxmox installer creates, both do; a container on plain Directory storage does not, so back it up instead with vzdump 105 --mode stop --storage local. Snapshot mode is no way around that: the vzdump documentation says it needs every backed up volume on storage that supports snapshots. Stop mode shuts the container down for a consistent copy and starts it again; --mode suspend keeps the downtime shorter. A new container is only in your backup job if that job covers all guests; a job with a fixed list of IDs needs it added.
pct stop 105
pct destroy 105 --purge # --purge also removes it from backup, replication and HA jobsTo undo the post-install script, put back the copy of /etc/apt (or roll back the ZFS snapshot), then run apt update. To drop the nag patch, delete /etc/apt/apt.conf.d/no-nag-script and /usr/local/bin/pve-remove-nag.sh and reinstall the original file with apt --reinstall install proxmox-widget-toolkit, plus apt --reinstall install pve-yew-mobile-gui if that package is installed, because the hook patches the mobile UI too. If you disabled HA by mistake, systemctl enable --now pve-ha-lrm pve-ha-crm corosync turns it back on.
Rolling back rpool/ROOT/pve-1 resets more than APT: the cluster configuration database /var/lib/pve-cluster/config.db lives on that dataset, so every VM and container config created after the snapshot disappears from the node. Plan a reboot straight after the rollback.
Common helper script errors
Symptom, cause, fix
Symptom: This version of Proxmox VE is not yet supported.
- Cause
- Your Proxmox VE is newer than the engine's check allows (on 2 November 2026 the newest accepted release was 9.2).
- Fix
- Wait for the project to raise the check, or upgrade from a supported minor release. Editing the check out of a script you then run as root defeats the point of reading it.
Symptom: curl: (22) The requested URL returned error: 404, then header_info: command not found
- Cause
- A command pinned to a commit from before the script moved to the core engine (late August to early October 2026, depending on the script) loads the engine from
misc/build.func, which no longer exists. - Fix
- Take the current command from the website, or pin both repositories as shown in the pinning section.
Symptom: This version of Proxmox Virtual Environment is not supported
- Cause
- The command points at the archived
tteck/Proxmoxrepository, which only accepts 8.1 to 8.3. - Fix
- Replace
tteck/Proxmoxwithcommunity-scripts/ProxmoxVEand use the current script name from the website.
Symptom: Debian must be run on the Proxmox VE host. (the app name comes first)
- Cause
- You pasted the command into a container, a VM or another Linux machine.
- Fix
- Open the shell of the node itself: in the web UI, click the node, then Shell.
Symptom: Please run this script as root.
- Cause
- You are logged in as a normal user with sudo.
- Fix
- Use
sudo -ifirst, then paste the command. The check also fails when the parent process issudo, sosudo bash -cdoes not work either.
Symptom: The container starts but has no IP address
- Cause
- Default mode uses DHCP on vmbr0, and nothing on that bridge hands out addresses.
- Fix
- Set a static address:
pct set 105 -net0 name=eth0,bridge=vmbr0,ip=192.0.2.50/24,gw=192.0.2.1, or rerun the script in Advanced mode.
How we tested
- OS image
- Debian 12, not a Proxmox node (no script was executed)
- Versions
- community-scripts/ProxmoxVE 7774a1acommunity-scripts/core 09fac19git 2.39.5curl 7.88.1
- Tested on
- Method
- Both repositories cloned at the heads of main and read: ct/debian.sh, install/debian-install.sh, the engine's defaults, container creation, telemetry and version checks, post-pve-install.sh and the host tools in the table. Checked that pinned raw URLs answer 200 and match the clone by SHA-256, that the old misc/build.func URL answers 404, and what an old pinned command prints because of it.
- Not tested
- Running a script on a Proxmox VE node. The run sequence and defaults above are read from the code, not observed on a host.
A helper script saves you from building the container, not from running the app. If all you need is one of these apps online and you do not need a hypervisor of your own, a Standard KVM VPS runs it directly, with snapshots and a browser VNC console in the panel for the day an update goes wrong.
Frequently asked
Are Proxmox helper scripts safe?
They are open source and actively reviewed, but every one runs as root on your Proxmox host and pulls more code from GitHub while it runs. Read the script and its install half first, pin both the ProxmoxVE and the core (engine) repository to a commit, and take a snapshot or backup before you run anything that changes the host.
What happened to tteck's Proxmox helper scripts?
tteck started the collection in 2021. When he could no longer maintain it, the project moved to the community-scripts organization on GitHub in November 2024, with its full history, and his tteck/Proxmox repository was archived. Old commands that point at tteck/Proxmox run frozen 2024 code that does not accept Proxmox VE 9.
What does the Proxmox post install script do?
On Proxmox VE 9 it asks before each step. Only on a node without any .sources file yet (an old 8.x layout or a provider image) does it first offer to rename legacy .list files to .list.bak and to write a new debian.sources; a fresh 9.x install or a node upgraded with the official guide skips that. Then it can keep, disable or delete the enterprise repositories, add the no-subscription and Ceph repositories, patch out the subscription nag, disable high availability on a single node, run a full upgrade and reboot. Each step only happens if you answer yes.
How do I update an LXC container created by a helper script?
Open the container's console and type update. The command downloads the app's script again and runs its update function. Take a snapshot first with pct snapshot ID before-update on the host, so pct rollback can undo a bad update. VM scripts have no updater; patch those guests with their own package manager.
Do the Proxmox helper scripts work on Proxmox VE 9?
Yes. On 2 November 2026 the project README listed Proxmox VE 8.0 to 8.4 and 9.0 to 9.2, and the engine refuses newer minor releases with 'This version of Proxmox VE is not yet supported.' until the project raises the check.