Skip to content

Comparing the tools

A Janus node does everything through one API: gRPC over mutual TLS, on port 9505. janusctl, its live dashboard janusctl tui, the Controller and the Terraform provider each cover part of that API, and add what a single node can’t do: many nodes at once, accounts, virtual machines. This page shows, call by call, which tool does what.

janusctljanusctl tuiControllerTerraform
What it isA command line: one command per call, plain text to scriptA live dashboard in the terminal, for one node or a whole fleetThe web UI of a fleet: accounts and roles, the virtual machines it createsThe janus provider for Terraform and OpenTofu: nodes as code
How it reaches a nodeDirectly, port 9505, with a certificate from the Controller, the fleet, or the node’s own CALike janusctl: the same contexts and certificatesDirectly, with its fleet certificate (or the credential a node was added with), acting for the account signed inThrough the Controller’s API, with an API token - never the node itself
Without a ControllerYes: a node’s own certificate, or a fleet without a ControllerYes-No: it drives a Controller
CoversNearly every callWatching, and a few actionsNearly every callThe node’s VM, network, release and haproxy.cfg
MoreUsing janusctl, referenceThe dashboardThe ControllerTerraform / OpenTofu

Whatever the tool, the node checks the caller’s role (os:reader, os:operator, os:admin) on every call and logs who changed what: a tool offering an action doesn’t mean you may take it. The Controller and the TUI offer only the actions your role allows. Calling the API yourself, from your own code or grpcurl: driving nodes; every call and its role: the node API reference.

In the tables below, the tool does it where a cell names janusctl’s command (shown without janusctl) or the Controller’s page (in a node’s sidebar), or shows ✅ - in the TUI, a panel shows it or its action menu makes the call. ⚙️ means the tool makes the call by itself, for a feature of its own; - that it doesn’t. Terraform’s janus_node drives a node’s network and its release, janus_haproxy_config its haproxy.cfg; its ⚙️ are calls the Controller makes for a janus_node.

CalljanusctlTUIControllerTerraform
Version - release, kernel, slots, imageversion, system info✅Overview, Update⚙️
Hostname - the node’s hostnamesystem hostname✅Overview-
Reboot - soft-stop HAProxy, reboot: firmware, power cycle or kexecsystem reboot✅Power-
Shutdown - soft-stop HAProxy, power offsystem shutdown-Power; ⚙️ resizing or deleting a VM⚙️
Restart - restart janusd, HAProxy keeps servingsystem restart✅Power-
Reset - wipe STATE, reboot with a new CAsystem reset-Power-
Events - the node’s event log, livesystem events✅Events-
Dmesg - the kernel’s messagessystem dmesg-Kernel-
Logs - a service’s outputsystem logs✅Service logs-
Stats - each service’s CPU and memorysystem stats✅Metrics-
SystemStat, Memory, CPUInfo, LoadAvg - CPU, memory, loadsystem info, systemstat✅Overview, Metrics-
DiskStats - each disk’s counterssystem info-Storage-
DiskUsage - a path’s disk usagesystem du-Storage-
NetworkDeviceStats - each interface’s counterssystem netdev✅Network-
Netstat - TCP and UDP socketssystem netstat-Network-
Mounts - mounted filesystemssystem mounts-Storage-
Processes - every processsystem ps✅Processes-
ServiceList - the services and their healthsystem services✅Services-
ServiceStart, ServiceStop, ServiceRestartsystem service-Services-
List, Read, Copy - the node’s files, never its secretssystem ls, cat, cp-Files-
PacketCapture - a live capture, as pcapsystem pcap-Packet capture-
Probe - DNS, TCP, TLS, HTTP, ping, traceroute from the nodesystem probe-Connectivity test-
GenerateClientConfiguration - a certificate of the node’s own CApki generate-client-config-Access; ⚙️ adding a node-
MetricsConfigGet, MetricsConfigSet - the Janus exportersystem metrics-Janus exporter-
NodeExporterConfigGet, NodeExporterConfigSet - prometheus-node-exportersystem node-exporter-Node exporter-
SysctlList - kernel parameters, suggestions, the CIS benchmarksystem sysctl list, get, observed✅Sysctl; ⚙️ auto-scaling-
SysctlApply - parameters on trialsystem sysctl set, reset-Sysctl; ⚙️ auto-scaling⚙️
SysctlConfirm - keep the values on trialsystem sysctl confirm✅Sysctl; ⚙️ auto-scaling⚙️
SysctlCancel - the previous values back, nowsystem sysctl cancel-Sysctl-
SysctlHistory - who changed what, whensystem sysctl history-Sysctl; ⚙️ auto-scaling-
ApplyConfiguration, MetaWrite, MetaDelete - not implemented----

Terraform’s ⚙️: a janus_node’s version read back, a clean shutdown before a resize or a destroy, its kernel parameters following its size with autoscaling.sysctl. ApplyConfiguration and the Meta* calls answer “unimplemented”: Janus has no declarative machine configuration and no META partition.

CalljanusctlTUIControllerTerraform
GetConfig - the running haproxy.cfghaproxy get-config⚙️HAProxy › Configuration✅
ApplyConfig - check, write, reload without dropping connectionshaproxy apply-config-HAProxy › Configuration✅
ConfigHistory, ConfigVersion - the configurations applied before; ApplyConfig of one, going backhaproxy config-history, get-config -version, config-revert-HAProxy › Configuration › History-
ValidateConfig - check only--HAProxy › Configuration-
Reload - a seamless reloadhaproxy reload✅HAProxy-
Stats - show stathaproxy stats✅HAProxy › Status-
ShowInfo - version, uptime, connectionshaproxy show-info✅HAProxy › Status-
BackendList - backends, servers, stateshaproxy backends-HAProxy › Backends-
ServerSetState - ready, drain, maintenancehaproxy server-state✅HAProxy › Backends-
MapList, MapGet - the maps and their entrieshaproxy map-list, map-get⚙️HAProxy › Maps & ACLs-
MapUpdate - set or delete an entry, livehaproxy map-set, map-delete-HAProxy › Maps & ACLs-
ACLUpdate - add or delete a pattern, livehaproxy acl-add, acl-delete-HAProxy › Maps & ACLs-
MapLookup, ACLLookup - the entry or pattern a value matcheshaproxy map-lookup, acl-lookup-HAProxy › Maps & ACLs-
TableList, TableShow, TableClear - stick tableshaproxy tables, table, table-clear-HAProxy › Stick tables-
SessionList, SessionShutdown - the sessions in progresshaproxy sessions, session-kill-HAProxy › Sessions-
ErrorsShow - the last refused requests and responseshaproxy errors-HAProxy › Errors-
CertificateList, CertificateUpload, CertificateDeletehaproxy cert-list, cert-upload, cert-delete-HAProxy › Certificates-
FileList, FileGet, FilePut, FileDelete - error pages, CAs…haproxy files, file-get, file-put, file-delete-HAProxy › Files-
ACMEStatus, ACMEGetConfig, ACMEApplyConfig, ACMERenew - Let’s Encrypthaproxy acme-Let’s Encrypt-

The TUI’s ⚙️: its traffic flow (f) reads the configuration and its maps - the Controller’s Traffic flow page too. apply-config and janus_haproxy_config have the node check the configuration before applying it; checking alone is the Controller’s.

CalljanusctlTUIControllerTerraform
NetworkStatus - interfaces, addresses, routes, DNS, clocknetwork status✅Network⚙️
NeighborList - the neighbour table (ARP, NDP)network neighbors-System › Network-
NetworkConfigGet - the saved configurationnetwork get-System › Network✅
NetworkConfigApply - a configuration on trialnetwork apply-System › Network✅
NetworkConfigConfirm - keep itnetwork confirm✅System › Network✅
FirewallList - saved, on trial, livenetwork firewall status✅Firewall-
FirewallGetRuleset, FirewallApplyRulesetnetwork firewall get, check, apply-Firewall-
FirewallConfirm - keep the ruleset on trialnetwork firewall confirm✅Firewall-
FirewallSets, FirewallSetUpdate - the live named setsnetwork firewall sets, set-add, set-del-Firewall-
VRRPStatus - instances, virtual IPsnetwork vrrp status✅VRRP-
VRRPGetConfig, VRRPApplyConfig - keepalived.confnetwork vrrp get, check, apply-VRRP-
BGPStatus - protocols, sessions, routesnetwork bgp status✅BGP-
BGPGetConfig, BGPApplyConfig - bird.confnetwork bgp get, check, apply-BGP-
ConsulStatus - the agent, its clusternetwork consul status✅Consul-
ConsulGetConfig, ConsulApplyConfig - its configurationnetwork consul get, check, apply-Consul-

janusctl network apply and janus_node confirm the trial by themselves (interfaces, dns, ntp). janusctl network modules, the Controller’s sidebar and the TUI’s panels tell which optional modules the image has, from the *Status calls.

CalljanusctlTUIControllerTerraform
Install - partition a blank disk, write a releaselifecycle install---
Upgrade - the other slot, reverted unless healthylifecycle upgrade-Update; ⚙️ a VM’s release✅
UploadReleaseFile - a bundle streamed to the nodelifecycle upload-release-Update-
Rollback - boot the other slotlifecycle rollback---

lifecycle upgrade takes a directory on the node or a URL; the Controller’s Update page a version, a URL or a bundle it relays; janus_node its version, extensions, haproxy and kernel (update_reboot_mode: firmware or kexec). The Controller installs nothing: it creates VMs from images.

CalljanusctlTUIControllerTerraform
TrustGet - the fleet’s root and bundle, the node’s CAaccess trust; ⚙️ fleet-Access; ⚙️ its fleet-
TrustSet - pin the root, apply a newer bundleaccess trust-set; ⚙️ fleet-⚙️ its fleet-
TrustReset - forget the fleetaccess trust-reset---
LocalCARotate - a new CA for the nodeaccess rotate-ca-Access-

janusctl fleet adopt and fleet sync set the trust by themselves; the Controller sets its fleet’s on each node every 10 minutes. TrustReset takes a certificate of the node’s own CA.

What a tool adds on top of the calls above - the fleet, accounts, virtual machines:

janusctlTUIControllerTerraform
Several nodes at once-n a,b, -all✅✅✅
Signing inSSH key, browser, tokenjanusctl’spassword, passkey, TOTPAPI token
Accounts, roles, label scopes, API tokens--✅-
The fleet’s trust: root, bundle, issuing CAsfleet-✅-
Nodes registering themselves, enrollment tokens--✅-
A disk image provisioned offlineimage-⚙️ its VMs-
VMs on libvirt/KVM or Proxmox VE: create, resize, delete--✅✅
Auto-scaling: vCPUs and memory hot-plugged--✅✅
A VM’s serial console--✅-
Node labels--✅✅
Images with other extensions, HAProxy branch or kernel--✅✅
Update and security notices--✅-
Live graphs-✅✅-
Traffic flow: frontends to servers-✅✅-
Encrypted backups, to S3 too--✅-
Audit log--✅-
Drift: changes made elsewhere--✅✅
Locking a node’s page---✅
Shell completion, pickers, plain output✅---

Without a Controller, janusctl keeps a fleet itself and upgrades a node to any image given its URL. The Controller says when an update is available, 🔒 when it fixes a vulnerability. Each node logs who changed what; the Controller’s audit log has every change made through it, its backups each node’s configuration. Terraform declares hypervisors (janus_hypervisor, janus_proxmox_hypervisor) and VMs (janus_node: size, autoscaling, labels, lock_ui, release, network); terraform plan shows what changed elsewhere, and the Controller’s record of a VM follows the machine.

  • One node, a terminal, a script: janusctl - nearly the whole API, plain output, with a Controller or without.
  • Watching a fleet, acting fast: janusctl tui - drain a server, reload HAProxy, reboot, confirm a trial, without leaving the terminal.
  • A team, a fleet, its VMs: the Controller - accounts and roles, the nodes’ pages, updates, backups, the VMs it creates and grows.
  • Nodes as code: Terraform - the VM, its network, its release and its haproxy.cfg in a plan; a token narrowed to HAProxy is enough for janus_haproxy_config.
  • Something none of them does: the node’s API itself, from your own code (your own orchestrator).

Only janusctl installs onto a blank disk (lifecycle install), rolls back (lifecycle rollback) and forgets a fleet (access trust-reset). Only the Controller checks a haproxy.cfg without applying it.