Agent Enrollment
Agent cannot enroll
Symptom
A new Agent does not appear online after start. Typical observations:
POST /api/v1/agents/registerreturns 4xx/403/429zwallctl list-agentsdoes not show the host- Agent journal shows bootstrap/TLS/profile errors
- Hosting Agent refuses to start because a pre-token was left in YAML
Production example config keeps agents.auto_register: false. Admission is pre-register or admin create, then one-time bootstrap, then register.
Likely verified causes
- No pre-registration / create, and
auto_registeris false. - Missing or consumed one-time bootstrap token (
AGENT_PRE_TOKEN/AGENT_TOKEN; Hosting must not storeserver.pre_tokenin YAML). - Hostname /
expected_ipmismatch with the actual registration source IP (403IP or identity mismatch). - Invalid
security_level(must bestandardormaximum). - Invalid Hosting vs Virtualization profile identity (
400 Invalid Agent profile identity). - Community already has 3 registered Agents (
403 COMMUNITY_AGENT_LIMIT_REACHED). - Enterprise license gate rejects Agent count (
403LicenseErrorResponse). RegisterRateLimiteronPOST /api/v1/agents/register(429 / temporary ban).- TLS verification failure (
verify_tls: true;allow_insecure_remote_tls: false). - Operator copied the stale start-agent path
/etc/zwall/agent.yml. Real unit paths: Virtualization/etc/zcs/agent.yml; Hosting/etc/zwall-hosting/agent.yml. - Wrong binary/unit: Hosting vs
zwall-agent.service.
Diagnostic commands/endpoints
Manager must be ready first (Manager Unavailable).
zwallctl login --manager-url https://manager.example.com:8443 --username admin
zwallctl list-agentsAdmin pre-register (requires hostname and expected_ip):
POST /api/v1/agents/pre-register
Authorization: Bearer <admin JWT>{
"hostname": "host-01",
"expected_ip": "203.0.113.10",
"security_level": "standard"
}Optional Hosting identity fields: profile_type, profile_platform (JSON tag), profile_version, observation_only. Empty profile + observation_only: false is the Virtualization/default identity.
Agent register (Agent runtime, not a browser):
POST /api/v1/agents/registerEnterprise wraps ResolveRegistrationClientIP() plus RegisterRateLimiter(). Bootstrap token is required (PreToken). Response on success includes token, agent_id, security_level, token_expires_at.
On the node:
# Virtualization
sudo systemctl status zwall-agent
sudo journalctl -u zwall-agent -n 200 --no-pager
# Hosting (Enterprise)
sudo systemctl status zwall-hosting-agent
sudo journalctl -u zwall-hosting-agent -n 200 --no-pagerConfirm the config path in the unit ExecStart=, not folklore.
What each result means
Scroll sideways to see the full table. Use the arrow keys when focused.
| Result | Meaning |
|---|---|
400 Invalid request format on pre-register | JSON missing required hostname or expected_ip, or bind failure. |
400 Invalid security_level: must be 'standard' or 'maximum' | security_level set to something else. Empty defaults to standard. maximum is mTLS. |
400 Invalid Agent profile identity | Profile is not (all empty + not observation-only) and not Hosting hosting + plesk + hosting-plesk-observe-v1 or v2 with observation_only: true. |
400 Invalid Hosting release identity | Hosting v2 register payload failed release identity checks. |
400 Invalid hostname / Hostname cannot be an IP address | Validator or IP-as-hostname. |
400 Invalid public IP address | expected_ip unspecified, multicast, or loopback. |
400 expiry_hours must not exceed 24 | Pre-register expiry cap. Default when omitted/≤0 is 1 hour. |
400 Invalid pre-token | Bootstrap token failed format validation. |
401 Bootstrap token is required for agent registration | PreToken empty. |
401 Invalid bootstrap token | Unknown, stale, or unparsable token (ErrStaleToken / ErrPreRegistrationNotFound). |
403 Agent registration denied: IP address mismatch | Reported IP ≠ verified registration source, or pre-register expected IP mismatch. |
403 Agent registration denied: identity mismatch | Duplicate or conflicting identity. |
403 Existing Agent recovery requires an explicit agent_id | Hostname already registered; recovery must name agent_id. |
403 Community body code/error COMMUNITY_AGENT_LIMIT_REACHED, limit: 3 | Fourth registration-style enroll. Already-registered Agents may still heartbeat. |
403 LicenseErrorResponse (success: false, code, message, license) | Enterprise license gate on pre-register or register (OperationAgentPreRegister / OperationAgentRegister, LimitAgents). |
403 Agent registration source could not be verified | Client-IP resolver failed. |
429 Registration temporarily banned | RegisterRateLimiter (3 attempts / 10 minute window; ban path returns retry_after_seconds). |
503 Agent registration is unavailable | Registration repo / IP resolver / rate-limit identity not configured. |
Hosting start error server.pre_token must not be stored in YAML | Product-enforced Hosting validation. Use AGENT_PRE_TOKEN once, then unset. |
| TLS / x509 in Agent journal | verify_tls: true rejected the Manager certificate. |
Unit ExecStart /etc/zcs/agent.yml vs copied /etc/zwall/agent.yml | stale path string in zwallctl start message. Follow the unit. |
Valid Hosting registration identity (from validRegistrationProfile): profile_type=hosting, platform=plesk, profile_version v1 or v2, observation_only=true. Virtualization uses empty profile fields and observation_only=false.
Safe remediation
- Confirm Manager
/health/readyis 200. - Pre-register or create the Agent as admin. Keep
agents.auto_register: false. - Place the one-time token in the Agent environment (
AGENT_PRE_TOKEN/AGENT_TOKEN), not as a long-lived YAML JWT. Hosting unsets leftoverAGENT_TOKEN/AGENT_PRE_TOKENafter config load. - Match
hostnameandexpected_ipto the address the Manager will see. Loopback is rejected as a public expected IP. - Start the correct unit:
- Virtualization:
sudo systemctl start zwall-agentwith/etc/zcs/agent.yml - Hosting: loader first, then Hosting Agent with
/etc/zwall-hosting/agent.yml
- Virtualization:
- Confirm
GET /api/v1/agents/zwallctl list-agents. - Community: stay at 3 Agents or move to Enterprise. Do not “raise the limit” in Community config.
- Enterprise 403 license: inspect
GET /api/v1/license/statusandlimits(not a public SKU list). - Rate limit 429: wait for
retry_after_seconds; do not script register in a tight loop. - TLS: install a Manager certificate the Agent trusts. Do not flip
allow_insecure_remote_tlsexcept break-glass.
Do-not-do warnings
- Do not leave
AGENT_PRE_TOKENin Hosting YAML or in a Hosting unitEnvironment=line. Tests forbid permanent bootstrap in the Hosting unit. - Do not copy
sudo /usr/local/bin/zwall-agent --config /etc/zwall/agent.ymlfromzwallctl startas procedure. - Do not enable
agents.auto_registerto bypass pre-register in production. Example config is false; Manager warns if it is true. - Do not mix Hosting observation identity onto a Virtualization unit, or firewall programs onto a Hosting node.
- Do not put bootstrap tokens in tickets, git, or
psargv. - Do not treat Community 3-Agent rejection as a Manager outage.
- Do not publish default no-license entitlement numbers as a price list.
Escalation condition
Escalate when:
- pre-register succeeds, token is unused, source IP matches
expected_ip, TLS verifies, and register still returns identity mismatch - Hosting v2 returns
Invalid Hosting release identityon an admitted Hosting bundle - Enterprise license gate denies enroll despite a license that should include Agents (license APIs vs commercial SKU is a known discrepancy)
- Path prefix in the admitted release unit does not match any documented family
Related documentation
- Agent enrollment
- Agent / Manager trust
- Agent-facing register/heartbeat HTTP details are provided separately to Enterprise customers.
- Agent disconnected
- Manager authentication
- Least privilege
Edition
SHARED registration API. Community hard limit 3 Agents. Enterprise license gate and Hosting profile identity are ENTERPRISE_ONLY.
Status
SUPPORTED for pre-register → env token → register. NOT_SUPPORTED: leaving auto-register on as a production admission design.