Single-file utility that reads structured credentials from Proxmox VM notes and (re)creates matching RDP / VNC / SSH connections in Apache Guacamole. Includes IP discovery, grouping, optional password encryption, Wake‑on‑LAN and powerful bulk operations.
git clone https://github.com/SpotlightForBugs/Proxmox-Guacamole-Sync.git
cd Proxmox-Guacamole-Sync
cp config_example.py config.py # Edit credentials
uv sync # Or: uv pip install -r requirements.txt
uv run python guac_vm_manager.py test-auth
uv run python guac_vm_manager.py autoAdd to a VM's Notes in Proxmox (example):
user:"admin" pass:"MyPassword" protos:"rdp,ssh";
Run auto again – connections appear in Guacamole.
Tip: Use --raw flag for plain text output without colors/animations (perfect for scripts and logs):
uv run python guac_vm_manager.py --raw auto > sync.log- Zero-daemon, single script (
guac_vm_manager.py) - No DB migrations or schema coupling – talks directly to both APIs
- Works even when guest agent IP is missing (ARP + ping fallback)
- Safe idempotent sync – updates instead of duplicating
- Optional transparent password encryption (Fernet) in VM notes
- Built for bulk ops (regex filters, partial arguments, auto-discovery)
| Protocol | Default Port | Adjustable Via Note Key |
|---|---|---|
| RDP | 3389 | rdp_port:"3390" |
| VNC | 5900 | vnc_port:"5901" |
| SSH | 22 | ssh_port:"2222" |
VNC extra settings via vnc_settings:"key=value,..." (e.g. color-depth=32,encoding=tight,read-only=false).
Each credential block ends with a semicolon ;. Keys are order‑independent.
user:"admin" pass:"pw" protos:"rdp,vnc" confName:"{vmname}-{user}-{proto}";
user:"viewer" pass:"readonly" protos:"vnc" vnc_settings:"read-only=true,color-depth=16";
user:"ops" encrypted_password:"<FERNET_BLOB>" protos:"ssh";
Supported keys (aliases in parentheses):
user(username)pass/password/encrypted_passwordprotos(proto,protocols) – comma separatedconfName(connection_name) – templated name- Protocol ports:
rdp_port,vnc_port,ssh_port - Protocol settings:
vnc_settings wol_disabled:"true"to suppress Wake-on-LAN for that credential
Template variables inside confName:
{vmname}, {user}, {proto}, {port}, {vmid}, {node}, {ip}, {hostname}
Generate key:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"Set ENCRYPTION_KEY in config.py.
If a note line uses pass:"cleartext" it is auto‑converted in-place (non‑destructive) to encrypted_password:"..." on first processing.
Minimal required fields:
class Config:
GUAC_BASE_URL = "https://guacamole.example.com"
GUAC_USERNAME = "admin"
GUAC_PASSWORD = "admin_password"
GUAC_DATA_SOURCE = "mysql" # or postgresql/sqlserver
PROXMOX_HOST = "192.168.1.100"
PROXMOX_TOKEN_ID = "root@pam!mytoken"
PROXMOX_SECRET = "<token_secret>"
ENCRYPTION_KEY = "<optional_fernet_key>"First run discovers/locks working Guacamole API base path & data source variants automatically.
uv run python guac_vm_manager.py test-auth # Validate both APIs & encryption key
uv run python guac_vm_manager.py auto # Process all VMs with credential notes
uv run python guac_vm_manager.py add # Interactive VM picker
uv run python guac_vm_manager.py add-external # Non-Proxmox host
uv run python guac_vm_manager.py list # List + status flags
uv run python guac_vm_manager.py edit # Bulk edit by pattern
uv run python guac_vm_manager.py delete # Interactive / pattern delete
uv run python guac_vm_manager.py autogroup # Group connections intelligently
uv run python guac_vm_manager.py test-network <MAC> # Test network scanning for MAC
uv run python guac_vm_manager.py test-connectivity # Test protocol authentication
uv run python guac_vm_manager.py test-connectivity --no-test-auth # Quick socket test
# Use --raw flag for plain text (no colors/animations) - great for automation
uv run python guac_vm_manager.py --raw auto # Plain text sync output
uv run python guac_vm_manager.py --raw list # Plain text connection list
# Also supports GUAC_RAW_MODE=1 environment variableNo subcommand = interactive menu.
Applies to: list, edit, delete.
- Regex allowed:
--connection ".*-admin-.*" - Multiple comma-separated expressions:
--connection "web-.*,db-.*" - Wildcards (
*) auto-translated to regex.* - Missing required CLI options trigger prompts (partial option mode)
Examples:
uv run python guac_vm_manager.py list --protocol rdp --connection "*-admin-*"
uv run python guac_vm_manager.py edit --connection "vm-.*-rdp" --username newuser --password newpass
uv run python guac_vm_manager.py delete --connection "temp-.*" --forceEnabled by default per connection unless wol_disabled:"true" in that credential line.
If target MAC + broadcast path resolvable, WoL packet is sent before connection creation when the VM was off (then original state restored afterwards).
Order of attempts:
- Proxmox guest agent reported IPv4
- Cached previous IP (if still alive)
- ARP table parse (platform aware: Windows
arp -a, Unixarp -anfallback toarp -a) - Optional subnet scan + ping sweep (boot VM temporarily if powered off and allowed)
All IPv6 addresses are ignored deliberately (Guacamole connection stability & simplicity).
vnc_settings:"key=value,..."
| Key | Values | Notes |
|---|---|---|
| color-depth | 8,16,24,32 | Quality vs bandwidth |
| encoding | raw,rre,corre,hextile,zlib,tight,ultra | tight = good balance |
| cursor | local,remote | |
| read-only | true,false | Viewer mode |
| disable-copy | true,false | Clipboard restrict |
| disable-paste | true,false | |
| enable-sftp | true,false | If supported |
| swap-red-blue | true,false | Color channel fix |
| autoretry | integer | Retry attempts |
Default if none supplied: <vmname>-<user>-<proto>.
Custom: confName:"{vmname}-{user}-{proto}-{vmid}".
Variables are resolved after IP discovery so {ip} becomes the final resolved address.
Each connection line may include flags:
- OK – In sync
- PORT – Port mismatch vs note definition
- CREDS – Username or password changed
- PROTO – Protocol set differs
- MISSING – Exists in notes but missing in Guacamole (will be created on auto)
Use --json or --csv <file> for export.
Example list output with status flags:
- Unix: arrow / tab navigation (termios)
- Windows:
msvcrtsingle-key navigation with TAB + arrows - Always accepts direct numeric entry or
qto quit Screens:
| Aspect | Approach |
|---|---|
| Credential storage | Proxmox VM notes only |
| At-rest password | Optional Fernet encryption inline |
| Transit | HTTPS (cert validation disabled by default for self‑signed) |
| Key validation | Encryption key sanity-checked at startup |
| Token scope | Proxmox token requires VM read (+ optional start/stop for discovery) |
Important: SSL certificate verification is intentionally disabled for self-signed certificates (common in internal infrastructure). See SECURITY.md for full security policy, threat model, and vulnerability reporting procedures.
Security Scanner Notes: This tool will trigger expected warnings from static analysis tools:
- SSL verification disabled (B501) - Intentional for self-signed certs
- SSRF warnings - False positives (tool connects to user-configured endpoints)
- Network operations - Required for IP discovery
All security considerations are documented in detail in SECURITY.md.
| Problem | Check |
|---|---|
| Auth fails | URLs, token scope, Guac user/pass |
| No IP | Guest agent stopped? Network segment mismatch? ARP permission? |
| Wrong password | Re-run auto after updating note; ensure encryption key unchanged |
| Duplicates | Ensure unique confName template and no manual conflicting creations |
| Slow scan | Large /24 subnet + ping sweep; restrict with patterns or supply known IP |
Useful commands:
uv run python guac_vm_manager.py test-auth
uv run python guac_vm_manager.py debug-vms
uv run python guac_vm_manager.py test-network "AA:BB:CC:DD:EE:FF"
uv run python guac_vm_manager.py test-connectivity --protocol rdp
uv run python guac_vm_manager.py test-connectivity --connection ".*prod.*" --verbose
uv run python guac_vm_manager.py test-connectivity --no-test-auth # Fast socket-only testThe test-connectivity command performs protocol-level authentication testing to verify that your Guacamole connections can actually reach and authenticate to their target hosts. Unlike simple port scanning, this validates actual protocol handshakes and credential authentication.
Key Features:
- Protocol-Level Authentication Testing: Validates SSH, RDP (via WinRM), and VNC connections with actual credentials
- Fallback Socket Testing: Tests port connectivity when protocol libraries unavailable or
--no-test-authspecified - Interactive TUI Mode: Guided interface with filtering options and detailed results
- CLI Mode: Full command-line control with regex filtering and protocol selection
- Configurable timeout for responsive testing
- Reports connection latency and authentication status for each test
- Provides detailed error diagnostics for failures
- Exits with error code 1 if any tests fail (perfect for CI/CD)
Usage Examples:
# Interactive mode (guided TUI with filtering)
uv run python guac_vm_manager.py interactive
# Then select option 3: "Test connection connectivity"
# CLI: Test all connections with protocol authentication
uv run python guac_vm_manager.py test-connectivity
# Test only RDP connections with authentication
uv run python guac_vm_manager.py test-connectivity --protocol rdp
# Test specific connection pattern with custom timeout
uv run python guac_vm_manager.py test-connectivity --connection "prod-.*" --timeout 10.0
# Socket-only test (no authentication, faster)
uv run python guac_vm_manager.py test-connectivity --no-test-auth
# Verbose output for failed connections
uv run python guac_vm_manager.py test-connectivity --verbose
# Combine all options
uv run python guac_vm_manager.py test-connectivity --connection "web-.*" --protocol ssh --timeout 5.0 --verboseOutput:
- Summary table showing connection name, protocol, endpoint, status (✓/✗), authentication result, and latency
- Success/failure counts with authentication status breakdown
- Optional detailed error diagnostics with
--verbose
Authentication Results:
Auth OK- Protocol authentication successful with provided credentialsAuth Failed- Credentials rejected by target servicePort Open- Socket connected but authentication not testedPort Closed- Cannot connect to target portTimeout- Connection attempt exceeded timeout periodDNS Error- Hostname resolution failedConfig Error- Missing required connection parameters
Protocol-Specific Testing:
- SSH: Uses paramiko to test actual SSH authentication (install with:
uv pip install paramiko) - RDP: Tests WinRM authentication as proxy for RDP credentials (install with:
uv pip install pywinrm) - VNC: Validates VNC protocol handshake and security negotiation
- Other Protocols: Falls back to socket connectivity test
Note: Protocol authentication testing validates that credentials work at the protocol level. This is more thorough than port scanning and catches authentication issues before users attempt connections through Guacamole.
Component summary (all in one file):
| Component | Responsibility |
|---|---|
| GuacamoleAPI | Auth, endpoint probing, CRUD for connections/groups |
| ProxmoxAPI | VM enumeration, note retrieval, power state handling |
| Credential Parser | Regex + tokenization of flexible note syntax |
| NetworkScanner | ARP parsing, ping probing, MAC→IP resolution |
| WakeOnLan | UDP broadcast magic packet generation |
| Grouping Engine | Pattern heuristics to form logical groups |
| CLI Layer | Typer commands + interactive menu rendering |
| ConnectivityTest | Protocol-level authentication testing (SSH/RDP/VNC) + socket fallback |
Design principles:
- Stateless between runs (except cached working Guac path)
- Fail-soft: degrade rather than abort on partial errors
- No external daemons; all transient operations
uv sync
uv run python guac_vm_manager.py --debug-vms
uv run python guac_vm_manager.py test-network "<mac>"
uv run python guac_vm_manager.py test-connectivity
pytest # If you add testsCoding guidelines:
- Keep single-file structure
- Avoid adding heavyweight deps
- Preserve credential parsing semantics
- Do not commit real credentials;
config.pyis git-ignored
Where to hook:
- Add new protocol: extend parser (port + settings), adjust GuacamoleAPI create/update mapping
- Add export format: extend list command output branch
- Enhance grouping: modify heuristic scorer in grouping section
Minimal compose (host networking for WoL broadcast):
version: "3"
services:
guacamole:
image: abesnier/guacamole
network_mode: host
restart: unless-stopped
volumes:
- guacdata:/config
volumes:
guacdata: {}Use Cloudflare Tunnel or reverse proxy for external exposure if needed.
Auto process (force recreate):
MIT – see LICENSE.
SECURITY.md- Comprehensive security policy including threat model, vulnerability reporting, and security scanner warnings.deepsource.yml- Static analysis configuration with documented exceptions for intentional patternsREADME.md- This file - complete usage guideconfig_example.py- Template configuration file (copy toconfig.py)
Notes line: user:"admin" pass:"pw" protos:"rdp,ssh";
Encrypt key: python -c "from cryptography.fernet import Fernet;print(Fernet.generate_key().decode())"
Sync all: uv run python guac_vm_manager.py auto
Test auth: uv run python guac_vm_manager.py test-auth
Test connect:uv run python guac_vm_manager.py test-connectivity
Test RDP: uv run python guac_vm_manager.py test-connectivity --protocol rdp
Quick test: uv run python guac_vm_manager.py test-connectivity --no-test-auth
Find MAC: uv run python guac_vm_manager.py test-network "AA:BB:CC:DD:EE:FF"
List RDP: uv run python guac_vm_manager.py list --protocol rdp
Bulk edit: uv run python guac_vm_manager.py edit --connection "web-.*" --username ops
Delete temp: uv run python guac_vm_manager.py delete --connection "temp-.*" --force
Raw mode: uv run python guac_vm_manager.py --raw auto # Plain text output
- Hexagon Icons: Visual indicators for operation types
- ⬢ (green) - Guacamole operations (view/edit connections)
- ⬢ (orange) - Proxmox operations (VM configuration)
- ⬢→⬢ (animated) - Sync operations (Proxmox → Guacamole)
- Sync Animations: Real-time animated feedback during bulk operations
- Raw Mode: Use
--rawflag orGUAC_RAW_MODE=1for plain text output- Perfect for automation, logging, CI/CD, and screen readers
- Disables colors, animations, and Rich formatting
- All features work identically in both modes
End of README.
