Consul Connection Refused: Complete Troubleshooting Guide
Fix 'consul connection refused' errors fast. Covers agent down, wrong ports, firewall rules, TLS mismatches, and ACL token issues with real commands.
- Root cause 1: Consul agent is not running or crashed — verify with systemctl status consul and check logs in /var/log/consul/
- Root cause 2: Incorrect bind address or port — Consul defaults to 127.0.0.1:8500 for HTTP; if the agent binds to a different interface, clients connecting to localhost will be refused
- Root cause 3: Firewall or security-group rules blocking TCP 8500 (HTTP), 8501 (HTTPS), 8300 (RPC), or 8600 (DNS)
- Root cause 4: TLS/ACL misconfiguration — HTTPS-only clusters refuse plain HTTP connections with a TCP RST that manifests as connection refused
- Quick fix: Run consul agent -dev on a workstation to isolate whether the issue is config vs. network, then apply the targeted fix from the comparison table below
| Method | When to Use | Time | Risk |
|---|---|---|---|
| Restart consul systemd service | Agent is stopped or crashed; logs show exit code | < 1 min | Low — service restart only |
| Fix bind_addr / client_addr in consul.hcl | Agent starts but only listens on 0.0.0.0 or 127.0.0.1 while clients need a LAN IP | 5 min + reload | Low — requires config reload |
| Open firewall ports (iptables / nftables / AWS SG) | Agent is running but remote hosts can't reach port 8500/8301 | 5–15 min | Medium — exposes port; scope rules tightly |
| Switch CONSUL_HTTP_ADDR to HTTPS + cert trust | Cluster enforces TLS; plain HTTP connections are refused | 15–30 min | Low if certs already exist |
| Generate and export ACL bootstrap token | HTTP returns 200 but RPC calls return 'permission denied'; agent refuses connections after ACL enforcement | 10 min | Medium — token material is sensitive |
| Roll back to previous Consul version | Connection refused started after an upgrade; no config changed | 20–40 min | High — reverting may affect data |
Understanding the "Connection Refused" Error in Consul
When you see a message like:
Get "http://127.0.0.1:8500/v1/status/leader": dial tcp 127.0.0.1:8500: connect: connection refused
or from the CLI:
Error querying agent: Get "http://127.0.0.1:8500/v1/agent/self": dial tcp 127.0.0.1:8500: connect: connection refused
your TCP SYN to Consul's HTTP port received a RST/ACK — meaning nothing is listening on that socket. This is distinct from a timeout (firewall drop) or a 403 Forbidden (ACL). Connection refused means the OS actively rejected the connection.
Step 1: Confirm Whether the Consul Agent Is Running
# systemd-managed systems
systemctl status consul
# Or for non-systemd
pgrep -a consul
ps aux | grep consul
If systemctl status consul shows Active: inactive (dead) or failed, start it:
systemctl start consul
journalctl -u consul -n 100 --no-pager # inspect why it died
Common crash reasons found in journals:
Error parsing config: ...— invalid HCL/JSON in/etc/consul.d/Failed to start Raft: ...— corrupted data dir; may needconsul data-dircleanupAddress already in use— another process on port 8500; find it withss -tlnp | grep 8500
Step 2: Verify the Listening Address and Port
Even when the agent is running, it may not be listening where your client expects:
# Show all sockets Consul is bound to
ss -tlnp | grep consul
# Or with lsof
lsof -i -P -n | grep consul
Expected output for a default dev-mode agent:
TCP 127.0.0.1:8500 LISTEN (consul)
TCP 127.0.0.1:8600 LISTEN (consul)
If the agent binds only to 127.0.0.1 but your application runs in a container or on a different host, you will get connection refused on the LAN IP. Fix by editing /etc/consul.d/consul.hcl:
# /etc/consul.d/consul.hcl
client_addr = "0.0.0.0" # listen on all interfaces for HTTP/DNS
bind_addr = "{{ GetPrivateIP }}" # bind RPC/gossip to the primary LAN IP
Then reload:
consul reload # or: kill -HUP $(pgrep consul)
systemctl reload consul
Step 3: Check Firewall and Network Path
Consul uses several ports. All must be reachable between the relevant nodes:
| Port | Protocol | Purpose |
|---|---|---|
| 8500 | TCP | HTTP API & UI |
| 8501 | TCP | HTTPS API (if TLS enabled) |
| 8502 | TCP | gRPC (Consul Connect) |
| 8300 | TCP | Server RPC |
| 8301 | TCP+UDP | LAN Serf gossip |
| 8302 | TCP+UDP | WAN Serf gossip |
| 8600 | TCP+UDP | DNS |
# From the client machine, test reachability
nc -zv <consul-server-ip> 8500
traceroute -T -p 8500 <consul-server-ip>
# On the server: check iptables
iptables -L INPUT -n --line-numbers | grep -E '8500|8301|8300'
# Quick allow rule (scope this to your CIDR in production)
iptables -A INPUT -p tcp --dport 8500 -s 10.0.0.0/8 -j ACCEPT
For AWS, GCP, or Azure security groups, add an inbound rule for TCP 8500 scoped to your VPC CIDR — never 0.0.0.0/0 unless behind a VPN.
Step 4: Rule Out TLS/HTTPS Misconfiguration
If your cluster has verify_incoming = true or https_port = 8501 in config but your client is pointing at http://..., the TLS handshake never completes and the kernel closes the connection — appearing as "connection refused" to application-layer code.
# Does the server speak TLS on 8501?
openssl s_client -connect <consul-ip>:8501 -CAfile /etc/consul.d/consul-ca.pem
# Export env vars to switch the CLI to HTTPS
export CONSUL_HTTP_ADDR="https://<consul-ip>:8501"
export CONSUL_CACERT="/etc/consul.d/consul-ca.pem"
export CONSUL_CLIENT_CERT="/etc/consul.d/client-cert.pem"
export CONSUL_CLIENT_KEY="/etc/consul.d/client-key.pem"
consul members # should succeed now
Step 5: Validate ACL Bootstrap State
If ACLs are enabled but no bootstrap token exists, the agent enters a degraded mode where API connections may be actively refused or return 403. Check:
consul acl bootstrap
# If you see: "The ACL system is already bootstrapped."
# you need an operator token. Retrieve from a peer server's log or Vault.
# Export token and test
export CONSUL_HTTP_TOKEN="<your-management-token>"
consul members
Step 6: Consul in Kubernetes
For Helm-deployed Consul, connection refused commonly means the service endpoint isn't exposed or the pod isn't ready:
# Check pod status
kubectl get pods -n consul
# Describe a crashing pod
kubectl describe pod consul-server-0 -n consul
# Port-forward to test locally
kubectl port-forward svc/consul-ui 8500:80 -n consul
curl http://127.0.0.1:8500/v1/status/leader
# Check service endpoints
kubectl get endpoints consul-server -n consul
Missing endpoints means the readiness probe is failing — usually a bad TLS secret or wrong datacenter name in the Helm values.
Step 7: Confirm the Fix
curl -s http://127.0.0.1:8500/v1/status/leader
# Expected: "10.0.1.5:8300" (the leader's address as a JSON string)
consul members
# Should list all agents with Status=alive
consul monitor -log-level=debug
# Watch live logs; Ctrl-C to exit
Frequently Asked Questions
#!/usr/bin/env bash
# consul-diagnose.sh — Run on the host where connection refused occurs
# Usage: bash consul-diagnose.sh [consul-target-ip] [consul-http-port]
TARGET_IP="${1:-127.0.0.1}"
HTTP_PORT="${2:-8500}"
echo "===== Consul Connection Refused Diagnostic ====="
echo "Target: ${TARGET_IP}:${HTTP_PORT}"
echo ""
# 1. Is the consul process running?
echo "[1] Consul process check:"
pgrep -a consul && echo " -> Process found" || echo " -> NO consul process running"
echo ""
# 2. What is the consul agent listening on?
echo "[2] Open sockets for consul:"
ss -tlnp 2>/dev/null | grep consul || echo " -> No consul sockets found (ss)"
lsof -i -P -n 2>/dev/null | grep consul || true
echo ""
# 3. Is anything on the target port at all?
echo "[3] Port ${HTTP_PORT} listener check:"
ss -tlnp | grep ":${HTTP_PORT}" || echo " -> Nothing listening on ${HTTP_PORT}"
echo ""
# 4. Network reachability
echo "[4] TCP reachability test (nc):"
nc -zv -w 3 "${TARGET_IP}" "${HTTP_PORT}" 2>&1 && echo " -> Port OPEN" || echo " -> Port REFUSED or TIMEOUT"
echo ""
# 5. Firewall rules that might block the port
echo "[5] iptables rules touching port ${HTTP_PORT}:"
iptables -L INPUT -n --line-numbers 2>/dev/null | grep "${HTTP_PORT}" || echo " -> No explicit iptables rule found (default policy applies)"
echo ""
# 6. Attempt HTTP API call
echo "[6] HTTP API call to /v1/status/leader:"
curl -sf --max-time 5 \
"http://${TARGET_IP}:${HTTP_PORT}/v1/status/leader" \
&& echo "" || echo " -> curl failed (see error above)"
echo ""
# 7. Attempt HTTPS API call (if TLS might be enabled)
echo "[7] HTTPS API call to /v1/status/leader (ignoring cert for diagnosis):"
curl -sk --max-time 5 \
"https://${TARGET_IP}:8501/v1/status/leader" \
&& echo "" || echo " -> HTTPS also failed"
echo ""
# 8. Recent consul service logs
echo "[8] Last 20 consul journal lines:"
journalctl -u consul -n 20 --no-pager 2>/dev/null || echo " -> journalctl not available or consul unit not found"
echo ""
# 9. consul.hcl bind config snippet
echo "[9] Consul config bind/client addresses:"
grep -r -E '(bind_addr|client_addr|ports|http|https)' /etc/consul.d/ 2>/dev/null || echo " -> /etc/consul.d/ not found or no matching config"
echo ""
echo "===== Diagnostic complete ====="
echo "Next steps:"
echo " If [1] shows no process: systemctl start consul"
echo " If [3] shows wrong IP: fix client_addr in /etc/consul.d/consul.hcl"
echo " If [4] shows TIMEOUT (not refused): open firewall port ${HTTP_PORT}"
echo " If [7] succeeds but [6] fails: switch to HTTPS with CONSUL_HTTP_ADDR=https://...:8501"
Error Medic Editorial
Error Medic Editorial is a team of senior DevOps and SRE engineers with combined experience across HashiCorp tooling, Kubernetes, and large-scale distributed systems. We write production-tested troubleshooting guides based on real incident post-mortems and community issue trackers.
Sources
- https://developer.hashicorp.com/consul/docs/install/ports
- https://developer.hashicorp.com/consul/docs/agent/config/config-files
- https://developer.hashicorp.com/consul/docs/security/acl/acl-system
- https://github.com/hashicorp/consul/issues/5090
- https://stackoverflow.com/questions/46451786/consul-connection-refused-on-port-8500
- https://developer.hashicorp.com/consul/docs/k8s/helm