Install and configure Consul for service discovery with clustering and security

Intermediate 45 min Apr 01, 2026 18 views
Ubuntu 24.04 Ubuntu 22.04 Debian 12 AlmaLinux 9 Rocky Linux 9 Fedora 41

Set up HashiCorp Consul for distributed service discovery with a secure three-node cluster, ACL authentication, and encrypted communication for production microservices environments.

Prerequisites

  • Root or sudo access
  • At least 3 servers for clustering
  • Static IP addresses for cluster nodes
  • Basic understanding of networking and DNS

What this solves

Consul provides service discovery, health checking, and configuration management for distributed applications and microservices. This tutorial sets up a production-ready Consul cluster with encryption, ACLs, and monitoring capabilities to handle service registration and discovery across multiple nodes.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you have the latest security patches and dependencies.

sudo apt update && sudo apt upgrade -y
sudo apt install -y wget unzip curl
sudo dnf update -y
sudo dnf install -y wget unzip curl

Create Consul system user

Create a dedicated system user for Consul with minimal privileges and no shell access.

sudo useradd --system --home /etc/consul.d --shell /bin/false consul
sudo mkdir -p /opt/consul /etc/consul.d /opt/consul/data
sudo chown consul:consul /opt/consul /etc/consul.d /opt/consul/data

Download and install Consul binary

Download the latest Consul binary from HashiCorp's releases and install it to /usr/local/bin.

CONSUL_VERSION="1.17.1"
wget https://releases.hashicorp.com/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_amd64.zip
unzip consul_${CONSUL_VERSION}_linux_amd64.zip
sudo mv consul /usr/local/bin/
sudo chmod +x /usr/local/bin/consul
consul version

Generate encryption key and certificates

Create the encryption key for gossip protocol and generate CA certificates for TLS communication between nodes.

consul keygen > /tmp/consul_encrypt.key
cd /etc/consul.d
sudo consul tls ca create
sudo consul tls cert create -server -dc dc1
sudo chown consul:consul .pem .key

Configure Consul server

Create the main configuration file for the Consul server with clustering, encryption, and ACL settings.

datacenter = "dc1"
data_dir = "/opt/consul/data"
log_level = "INFO"
node_name = "consul-server-1"
bind_addr = "203.0.113.10"
client_addr = "0.0.0.0"

server = true
bootstrap_expect = 3

retry_join = ["203.0.113.10", "203.0.113.11", "203.0.113.12"]

ui_config {
  enabled = true
}

connect {
  enabled = true
}

ports {
  grpc = 8502
  https = 8501
}

encrypt = "REPLACE_WITH_YOUR_ENCRYPT_KEY"

acl = {
  enabled = true
  default_policy = "deny"
  enable_token_persistence = true
}

tls {
  defaults {
    ca_file = "/etc/consul.d/consul-agent-ca.pem"
    cert_file = "/etc/consul.d/dc1-server-consul-0.pem"
    key_file = "/etc/consul.d/dc1-server-consul-0-key.pem"
    verify_incoming = true
    verify_outgoing = true
  }
  internal_rpc {
    verify_server_hostname = true
  }
}
Note: Replace the bind_addr with your actual server IP and update the encrypt key with the generated value from the previous step.

Set proper file permissions

Secure the configuration files and certificates with appropriate permissions for the consul user.

sudo chown -R consul:consul /etc/consul.d
sudo chmod 640 /etc/consul.d/consul.hcl
sudo chmod 600 /etc/consul.d/.pem /etc/consul.d/-key.pem
Never use chmod 777. It gives every user on the system full access to your files. Instead, fix ownership with chown and use minimal permissions.

Create systemd service file

Configure Consul as a systemd service with proper security restrictions and resource limits.

[Unit]
Description=Consul Service Discovery Agent
Documentation=https://www.consul.io/
Requires=network-online.target
After=network-online.target
ConditionFileNotEmpty=/etc/consul.d/consul.hcl

[Service]
Type=notify
User=consul
Group=consul
ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul.d/
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
LimitNOFILE=65536

Security settings

NoNewPrivileges=yes PrivateTmp=yes ProtectHome=yes ProtectSystem=strict ReadWritePaths=/opt/consul/data [Install] WantedBy=multi-user.target

Configure firewall rules

Open the necessary ports for Consul cluster communication, UI access, and client connections.

sudo ufw allow 8300/tcp comment 'Consul server RPC'
sudo ufw allow 8301/tcp comment 'Consul serf LAN'
sudo ufw allow 8301/udp comment 'Consul serf LAN'
sudo ufw allow 8302/tcp comment 'Consul serf WAN'
sudo ufw allow 8302/udp comment 'Consul serf WAN'
sudo ufw allow 8500/tcp comment 'Consul HTTP API'
sudo ufw allow 8501/tcp comment 'Consul HTTPS API'
sudo ufw allow 8502/tcp comment 'Consul gRPC'
sudo ufw reload
sudo firewall-cmd --permanent --add-port=8300/tcp --add-port=8301/tcp --add-port=8301/udp
sudo firewall-cmd --permanent --add-port=8302/tcp --add-port=8302/udp
sudo firewall-cmd --permanent --add-port=8500/tcp --add-port=8501/tcp --add-port=8502/tcp
sudo firewall-cmd --reload

Start and enable Consul service

Enable Consul to start automatically on boot and start the service for the first time.

sudo systemctl daemon-reload
sudo systemctl enable consul
sudo systemctl start consul
sudo systemctl status consul

Bootstrap ACL system

Initialize the ACL system and create the bootstrap token for administrative access.

sleep 10
consul acl bootstrap
Note: Save the SecretID from this command as your master token. You'll need it for all administrative operations.

Create ACL policies and tokens

Set up specific ACL policies for different service types and create corresponding tokens.

node_prefix "" {
  policy = "write"
}
service_prefix "" {
  policy = "read"
}
key_prefix "" {
  policy = "read"
}
export CONSUL_HTTP_TOKEN="YOUR_BOOTSTRAP_TOKEN_HERE"
consul acl policy create -name "node-policy" -description "Node registration policy" -rules @/tmp/node-policy.hcl
consul acl token create -description "Node token" -policy-name "node-policy"

Configure service registration

Create a sample service definition to test service discovery functionality.

{
  "service": {
    "name": "web",
    "tags": ["nginx", "frontend"],
    "port": 80,
    "check": {
      "http": "http://localhost:80/health",
      "interval": "10s",
      "timeout": "3s"
    }
  }
}
sudo chown consul:consul /etc/consul.d/web-service.json
sudo systemctl reload consul

Verify your setup

Check that Consul is running correctly and the cluster is healthy.

consul members
consul info
consul catalog services
curl -H "X-Consul-Token: YOUR_TOKEN" http://localhost:8500/v1/status/leader
consul acl token list

Access the Consul UI at https://your-server-ip:8501 using your bootstrap token. You should see your services, nodes, and health checks.

Configure health checks and monitoring

Set up comprehensive health monitoring

Configure Consul to monitor system resources and service health with custom check intervals.

{
  "checks": [
    {
      "id": "disk-usage",
      "name": "Disk Usage Check",
      "script": "df -h | grep -E '9[0-9]%|100%'",
      "interval": "30s",
      "status": "passing"
    },
    {
      "id": "memory-usage",
      "name": "Memory Usage Check",
      "script": "free | awk 'FNR==2{printf \"%.2f%%\\n\", $3/$2*100}'",
      "interval": "60s"
    }
  ]
}

For comprehensive monitoring integration, consider setting up Grafana with Prometheus to visualize Consul metrics and cluster health.

Set up Consul agents on client nodes

Configure Consul client agents

Install Consul on client nodes that need to register services or perform service discovery.

datacenter = "dc1"
data_dir = "/opt/consul/data"
log_level = "INFO"
node_name = "client-node-1"
bind_addr = "203.0.113.20"

server = false

retry_join = ["203.0.113.10", "203.0.113.11", "203.0.113.12"]

encrypt = "SAME_ENCRYPT_KEY_AS_SERVERS"

acl = {
  enabled = true
  default_policy = "deny"
  tokens = {
    default = "CLIENT_TOKEN_HERE"
  }
}

tls {
  defaults {
    ca_file = "/etc/consul.d/consul-agent-ca.pem"
    verify_incoming = false
    verify_outgoing = true
  }
}

This setup integrates well with Traefik reverse proxy for automatic service discovery and load balancing in containerized environments.

Common issues

SymptomCauseFix
Consul won't startConfiguration syntax errorconsul validate /etc/consul.d/consul.hcl
Nodes can't join clusterFirewall blocking portsCheck ports 8300-8302 are open between nodes
ACL token denied errorsInsufficient token permissionsCreate policy with required permissions and attach to token
TLS certificate errorsMismatched certificates or hostnameRegenerate certificates with correct hostnames
UI not accessibleHTTPS redirect or token missingUse https://ip:8501 and provide valid ACL token
Service discovery failsService not registered or unhealthyconsul catalog services and check health status

Next steps

Automated install script

Run this to automate the entire setup

#consul #service-discovery #consul-cluster #hashicorp-consul #microservices

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer