pbox
Linux development environments on Proxmox. Create a box from a container image, install tools with Ansible recipes, and open a shell or desktop.
Quick start · Configuration · Relay setup · Recipes · Help
Quick start
Run the commands below on the Linux machine where you want to use pbox. A box is a Linux container running on Proxmox VE (PVE).
1. Check the requirements
| Component | Needed for |
|---|---|
| Proxmox VE | Running boxes on a standalone node or cluster |
| Proxmox API token | Giving pbox access to the nodes, containers and storage it manages |
| Network bridge | Connecting boxes to a network with addressing, DNS and access to package repositories |
| Storage | Container disks (rootdir) and uploaded templates (vztmpl); these can use different storage pools |
| Podman and Git | Preparing images locally and downloading recipes |
| Ansible | Applying recipes; ansible-playbook must be available locally |
| TigerVNC viewer | Opening a desktop; optional for shell-only use |
The default box network uses DHCP. A bridge alone does not supply DHCP or DNS. See network configuration for static addresses and direct or relay access.
2. Install
Install the CLI and guest agent with cargo-binstall:
Prebuilt binaries are available for x86-64 Linux and work with glibc or musl. Alternatively, compile the CLI and agent with Rust and a C toolchain:
Cargo builds for the current machine. The agent must also match the guest's CPU architecture and libc; use the prebuilt agent for Alpine, or see agent builds.
Install Rust and a C toolchain, then:
Keep ~/.cargo/bin on your PATH. Both binaries are needed.
Pbox copies pbox-agent into boxes automatically.
It looks beside the CLI binary, or uses an explicit path:
3. Connect to Proxmox
Create an API token, then run:
The wizard asks for credentials and discovers nodes, storage and bridges.
| Value | Expected format | Example |
|---|---|---|
| API URL | HTTPS address of the PVE API | https://pve.example.com:8006 |
| Token ID | USER@REALM!TOKEN_NAME |
pbox@pve!cli |
| Token secret | The separate value shown when creating the token | Paste into the hidden prompt |
| Node | A PVE node name, or auto |
Select from the wizard |
| Rootfs storage | Storage supporting container disks | Select from the wizard |
| Template storage | Storage supporting container templates | May differ from rootfs storage |
| Bridge | The network to attach new boxes to | Select the bridge for your setup |
Expected result: Configuration saved and PVE connection verified.
This checks API access; creating a box also needs allocation and storage
permissions. Permissions and configuration details.
4. Choose the connection path
| Your setup | Connection |
|---|---|
| Pbox can reach guest addresses on a LAN, routed network or VPN | Direct. Guest SSH is used during initial setup; later sessions use the agent. |
| Pbox cannot reach guest addresses, but both pbox and the boxes can reach a relay | Relay. Follow relay setup before creating a box. |
| Boxes have no outbound route or working DNS | Configure the guest network first; a relay still needs to be reachable. |
[!IMPORTANT] Reaching the Proxmox web interface does not imply that pbox can reach a box. A relay provides guest access; pbox still connects to the Proxmox API separately.
For an existing relay, obtain its URL and key file from whoever operates it:
For a new relay, generate a key and deploy the service, then run the check. Generating a key alone does not start a relay.
5. Create a box and open a shell
Pbox waits for the guest agent before completing creation. Press Ctrl-] to
detach and keep your shell running. Reconnect with the same command. Type exit
to end the shell; the box keeps running.
current selects the only box. With several boxes, use a pbx_ ID or unique
name from pbox list. Shell access uses pbox's agent; you do not need to
configure a separate SSH login.
Illustrative output; IDs, addresses and installed tools will differ.
$ pbox list
ID STATE PING NODE IPV4 NAME IMAGE
pbx_d7ky95gz running ok pve 172.30.0.134 pbox-d7ky95gz docker.io/library/debian:13
$ pbox ssh current
> Connected to pbx_d7ky95gz · main
Ctrl-] detaches. Type exit to end this shell.
[pbox@pbox-d7ky95gz ~]$
6. Install tools
Recipes run in the order given. Browse pbox-recipes for languages, browsers, IDEs and coding agents. Recipe logs and recovery.
For a desktop, install a desktop recipe and open the viewer:
This opens a local TigerVNC window. Closing it leaves applications running. Desktop requirements and sessions.
Everyday commands
Replace BOX with an ID, unique name or current.
| Task | Command |
|---|---|
| List boxes | pbox list |
| Inspect a box, including CPU, memory and disk allocation | pbox info BOX |
| Open or resume your shell | pbox ssh BOX |
| Run a command | pbox exec BOX -- uname -a |
| Copy a file into a box | pbox scp ./file.txt BOX:/tmp/file.txt |
| Reach an app on port 3000 | pbox forward BOX 3000 |
| Stop / start / restart | pbox stop BOX / pbox start BOX / pbox restart BOX |
| Delete | pbox rm BOX |
| Find images | pbox image search debian |
| List image tags | pbox image tags debian |
pbox list uses a background inventory cache; changes can take a refresh to
appear. Use pbox COMMAND --help for options and --json for structured
results where supported.
Terminal sessions
pbox ssh BOX opens your main shell. If the connection drops, run it again
and carry on where you left off. Ctrl-] detaches; exit ends the shell.
The connection message and terminal title identify the session.
The application gets the full terminal, including its normal scrolling, text selection, clickable links, mouse input and cursor settings. pbox does not draw a bar over interactive sessions, capture the wheel, add scroll shortcuts or enter its own alternate screen. Native scrollback stays in the same terminal when you detach.
Use --read-only to watch without sending input, resizing the guest, or taking
over another connection. Ctrl+C exits the viewer and leaves the session running.
The read-only viewer shows CPU, RAM and disk usage in its bottom row.
| Task | Command |
|---|---|
| Open a separate terminal | pbox ssh BOX:build |
| Watch without taking control | pbox attach BOX:build --read-only |
| Update the guest agent | pbox agent update BOX |
| List terminals and foreground programs across all boxes | pbox session list |
| List terminals in one box | pbox session list BOX |
| Read the screen and retained history | pbox session read BOX:build --history |
| End a terminal and its processes | pbox session close BOX:build |
The list shows the current directory and foreground process chain, such as
codex [1234] · bash. pbox --json session list also includes process IDs and
parent IDs. Older terminal supervisors show only the original command until they
can update without ending existing sessions.
A separate terminal supervisor keeps shells and programs running during agent
updates; tmux is not required. Reconnect with pbox attach BOX:build after an
interrupted connection. Attaching moves the session from its previous connection.
Stopping the box or its terminal supervisor ends the sessions.
[!NOTE] Update survival works with systemd and pbox’s minimal guest init. Sessions created by older agents still defer their first update until you close them. Other init setups also defer updates while sessions are running.
SSH and session control commands check for agent updates before connecting.
pbox agent update BOX performs the same update without opening a shell; use
--json for a result a script can inspect. Updates use the local pbox-agent
binary. Session listing and read-only viewing never update the guest.
[!WARNING] To end legacy terminals blocking an update, run
pbox agent update BOX --kill-sessions. It lists the affected sessions and asks for confirmation. Add--yesfor non-interactive use. This stops their running programs and may lose unsaved work; normal updates preserve sessions.
pbox ssh BOX -- COMMAND still runs a one-off command. Add --session NAME
to keep that command in a named terminal. Working directory, user and environment
options apply when a session is created; reconnecting keeps its existing shell.
BOX:NAME works with session start, read, send and close. The separate BOX NAME form and
SSH’s --session NAME option also work. Closing shows the box, session, command,
user and starting directory before asking for confirmation.
Control a session from a script or agent
These commands work with pipes and TERM=dumb. No local terminal emulator is needed.
| Command | Result |
|---|---|
start BOX NAME -- COMMAND |
Creates a detached terminal; an existing name is an error |
read BOX NAME |
Prints the current screen as plain text |
send BOX NAME --text TEXT |
Types or pastes text; does not add Enter |
send BOX NAME --key KEY |
Presses a key, such as Enter, Escape, Up or Ctrl+C |
send BOX NAME --stdin |
Reads text from a pipe, up to 64 KiB |
Repeat --key for a sequence. When combined, text is sent before keys.
Reads and sends leave any SSH attachment in place. read shows the current
screen, not a full output log; its JSON includes dimensions and a zero-based
cursor position. send acknowledges input accepted by the agent; read again
to see the application's response. If a send loses its connection, check the
screen before repeating it to avoid sending the same input twice.
The agent handles terminal queries while detached. You can still attach at any
time with pbox ssh BOX --session NAME.
Save an environment
| Snapshot | Checkpoint | |
|---|---|---|
| Purpose | Create new boxes from a saved environment | Roll back the same box |
| Lifetime | Independent of the source box | Deleted with the box |
| Storage | Full copy in Proxmox | Requires native snapshot support |
Snapshot capture stops the source while copying; save work first. Capture, restore and recovery.
Shell completion
For Zsh, add to ~/.zshrc:
For Bash, add to ~/.bashrc:
For Fish, run once:
Updates
pbox update installs the latest published CLI through cargo-binstall or Cargo.
Pbox checks for published updates before selected commands and caches successful
checks for a day. Network failures are silent. Set PBOX_NO_UPDATE_CHECK=1 to
disable checks. The CLI update does not update the local agent binary or relay;
pbox ssh compares the guest agent with the local binary before connecting.
It defers agent updates while terminal sessions are running. End those sessions
first to allow the update on your next connection.
Troubleshooting
| Problem | Next step |
|---|---|
pbox-agent binary was not found |
Install the agent or set agent.binary; see installation. |
| PVE rejects credentials or permissions | Check the full token ID, secret and user/token permissions. |
| Box has no address | Check bridge, DHCP or static addressing in networking. |
| Creation stops while waiting for the agent | Inspect the box in PVE, correct the reported problem, then run pbox repair BOX. |
| Relay check fails | Check the URL, running service and matching key using the relay guide. |
| Recipe fails | Read the saved log path or rerun with --verbose; see recipes. |
| Desktop will not start | Check local viewer and guest session requirements in desktop help. |
Report an issue with the command, pbox version or source commit, guest image and relevant error output. Remove credentials from logs before sharing them.