Files
Proxmox-Coolify-Manager/agent/TOOLS.md
T

5.3 KiB

Tooling — Proxmox host

All commands assume PowerShell from the project root.

Canonical catalog: docs/TOOL-INDEX.md — verified signatures, env requirements, and read-only/mutating classification for every script in the repo. This file holds the host-level usage patterns.

Environment

. .\.env.local.ps1

Without a private env file, SSH still works from the hardcoded defaults in scripts/ProxmoxAgent.ps1. API calls require token env vars.

Status of .env.local.ps1 (2026-08-29): PROXMOX_API_TOKEN_ID (root@pam!openclaw, verified 200 against /version and /cluster/resources), PROXMOX_API_TOKEN_SECRET, COOLIFY_EMAIL, COOLIFY_PASSWORD (probable — unverified) and a working GITHUB_TOKEN (extracted from Windows Credential Manager after the old PAT expired) are all loaded. The Proxmox REST API, the Coolify API and GitHub work. Only CLOUDFLARE_API_TOKEN is still missing — tunnel changes go through the Cloudflare dashboard.

Smoke test and inventory

.\scripts\Test-ProxmoxConnection.ps1     # config + SSH + Docker sample + API auth; exits 1 on FAIL
.\scripts\Get-ProxmoxInventory.ps1       # host, LXC, QEMU, Docker in LXC 102

SSH wrapper

.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct list"
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "qm list"
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker ps -a"

⚠️ Nested quotes get mangled — use base64

Invoke-ProxmoxSshCommand passes $Command as a single argument to ssh, and PowerShell 5.1 destroys embedded quotes when calling a native executable. A command with two levels of quoting arrives corrupted (bash: line 1: -c: command not found). Encode it instead:

$remote = @'
pct exec 102 -- docker exec -i <db-container> bash -lc 'PGPASSWORD="$POSTGRES_PASSWORD" psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -At -c "SELECT 1"'
'@
$b64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($remote))
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "echo $b64 | base64 -d | bash 2>&1"

The single-quoted here-string @'...'@ is required so PowerShell does not expand $POSTGRES_PASSWORD on the Windows side. Single-level quoting (docker ps --format '{{.Names}}') works through the plain wrapper.

Safe read-only commands

.\scripts\Invoke-ProxmoxSsh.ps1 -Command "hostname && pveversion && uname -r && uptime"
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct list && qm list"
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "df -h / && free -h"
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pvesh get /cluster/resources"
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "systemctl --failed"
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'"
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker stats --no-stream"

Resolving a container name

Coolify names containers <service>-<uuid> plus an optional build suffix, so they are not guessable and change when a redeploy recreates the container:

.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker ps --format '{{.Names}}' | grep -i <app>"

Proxmox REST API from a PowerShell session

Requires PROXMOX_API_TOKEN_ID + PROXMOX_API_TOKEN_SECRET; throws without them.

. .\scripts\ProxmoxAgent.ps1
Invoke-ProxmoxApi -Path "/version"
Invoke-ProxmoxApi -Path "/nodes"
Invoke-ProxmoxApi -Path "/cluster/resources"

Cloudflare API — tunnel and DNS

Requires CLOUDFLARE_API_TOKEN. GET is read-only; everything else mutates. -Raw returns objects, the default returns a JSON string.

.\scripts\Invoke-CloudflareApi.ps1 -Path "/user/tokens/verify"

The tunnel is dashboard-managed — fix routes there or via this API, never by editing files on the host. See docs/runbooks/cloudflare-tunnel.md.

Host automation

# Power-outage auto-start of LXC 102 + tunnel. Audit without touching anything:
.\scripts\Install-CoolifyAutostart.ps1 -VerifyOnly

Installed on the host: coolify-autostart.service (systemd, enabled) and the Chatwoot guard at /root/scripts/chatwoot-enterprise-guard.sh, scheduled by /etc/cron.d/chatwoot-enterprise-guard every 5 minutes.

Chatwoot enterprise licence

.\scripts\Get-ChatwootLicenseStatus.ps1 -Deep                              # read-only diagnosis
.\scripts\Apply-ChatwootEnterprisePatch.ps1 -DryRun -ReenableAccountFeatures  # preview the repair

Full context: docs/runbooks/chatwoot-update.md.

Per-app deploy helpers

scripts/apps/ holds app-specific one-off deploy scripts with hardcoded uuids and domains — e.g. Deploy-SoloLeveling.ps1, which builds the image on the server to work around a private GHCR without read:packages. Read the header before running one; they are mutating and tied to a specific resource.

Commands that require confirmation

  • pct start|shutdown|reboot|stop|destroy
  • qm start|shutdown|reboot|stop|destroy
  • docker restart|stop|rm|compose up|compose down
  • Package updates, firewall edits, network edits, storage edits
  • Any Cloudflare write (POST/PUT/PATCH/DELETE)
  • Install-CoolifyAutostart.ps1 without -VerifyOnly
  • Apply-ChatwootEnterprisePatch.ps1 without -DryRun