Search for a command to run...
Install Consul 2.0, run a client-server cluster with ACLs and TLS, register services with health checks, and set up service discovery and the service mesh.
Consul is a service networking platform. It provides service discovery, distributed configuration, health checking and — with Connect — mutual TLS between every service in your mesh.
Consul 2.0.4 (2.1 is in release candidate) · client/server cluster with
Integrated Storage · ACLs with a default_policy of deny · service-intentions
config entries · transparent proxy now uses nftables instead of iptables
The transparent proxy no longer manages iptables/ip6tables rules — it uses
nftables and needs the nft binary plus a kernel with stateful NAT support in the
inet family (Linux 5.2+, or a distribution that backports it). There is no
fallback to iptables, and the old iptables rules are not cleaned up
automatically. When upgrading an existing host, remove the old Consul-managed
iptables rules first, or traffic will be redirected twice.
# Add the HashiCorp signing key
wget -O - https://apt.releases.hashicorp.com/gpg \
| sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
# Add the repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(grep -oP '(?<=UBUNTU_CODENAME=).*' /etc/os-release || lsb_release -cs) main" \
| sudo tee /etc/apt/sources.list.d/hashicorp.list
# Install
sudo apt update
sudo apt install -y consul
consul versionCreate /etc/consul.d/server.hcl:
datacenter = "dc1"
data_dir = "/opt/consul"
node_name = "consul-server-1"
server = true
bootstrap_expect = 3
bind_addr = "{{GetPrivateIP}}"
client_addr = "0.0.0.0"
advertise_addr = "{{GetInterfaceIP \"ens5\"}}"
retry_join = [
"10.0.0.11",
"10.0.0.12",
"10.0.0.13",
]
ui_config {
enabled = true
}
# Deny by default — every service needs an explicit intention
acl {
enabled = true
default_policy = "deny"
enable_token_persistence = true
}Create /etc/consul.d/client.hcl:
datacenter = "dc1"
data_dir = "/opt/consul"
node_name = "app-server-1"
server = false
bind_addr = "{{GetPrivateIP}}"
retry_join = [
"10.0.0.11",
"10.0.0.12",
"10.0.0.13",
]# Prepare the data directory
sudo mkdir -p /opt/consul
sudo chown -R consul:consul /opt/consul
sudo chmod 750 /opt/consul
# Start the service
sudo systemctl enable --now consul
sudo systemctl status consul# Start a single agent with everything enabled
consul agent -dev
# The UI is on http://localhost:8500
consul members
consul services# Generate a CA and a server certificate
consul tls ca create
consul tls cert create -server -dc=dc1verify_incoming = true
verify_outgoing = true
verify_server_hostname = true
ca_file = "consul-agent-ca.pem"
cert_file = "dc1-server-consul-0.pem"
key_file = "dc1-server-consul-0-key.pem"# Bootstrap the ACL system — this prints the initial management token
consul acl bootstrap
# Store the token so the agent can use it
echo "CONSUL_HTTP_TOKEN=..." | sudo tee /etc/consul.d/consul.env
# Create a policy for a service
consul acl policy create -name "web-policy" -rules @web-policy.hcl# web-policy.hcl
service_prefix "web" {
policy = "write"
}
node_prefix "" {
policy = "read"
}# Create a token for the service
consul acl token create -description "web service" -policy-name web-policyAttaching Envoy extensions (builtin/lua, builtin/wasm) or the
envoy_*_json escape-hatch overrides to a service now requires mesh:write in
addition to service:write. Grant it only to operators who really need it.
Create /etc/consul.d/web-service.hcl:
service {
name = "web"
port = 8080
tags = ["prod", "http"]
check {
http = "http://localhost:8080/health"
interval = "10s"
timeout = "2s"
}
}# Reload the agent configuration
consul reload
# Check that the service is registered and healthy
consul services
consul health checks service webService intentions define who may talk to whom. They are the heart of the mesh security model:
# /etc/consul.d/intentions.hcl
Kind = "service-intentions"
Name = "web"
Sources = [
{
Name = "api"
Action = "allow"
},
{
Name = "*"
Action = "deny"
}
]# Write the config entry
consul config write /etc/consul.d/intentions.hcl
# List the intentions
consul config list -kind service-intentions# Enable Connect on a service
consul config write -kind service-defaults -name web <<EOF
{
"Protocol": "http",
"Kind": "service-defaults",
"Name": "web"
}
EOF
# Start a sidecar proxy for a service instance
consul connect proxy -sidecar-for web
# Check the proxy status
consul connect proxy-statusOn Consul 2.x, consul connect redirect-traffic uses nftables. Install the nft
package, make sure the kernel supports stateful NAT in the inet family, and remove
any Consul-managed iptables rules left over from Consul 1.x before you start the new
version.
# 1. Back up the data directory
sudo systemctl stop consul
sudo tar -czf /var/backups/consul-$(date +%F).tar.gz -C /opt/consul data
sudo systemctl start consul
# 2. Upgrade the package
sudo apt update && sudo apt install --only-upgrade consul
# 3. Restart one server at a time and check the cluster
sudo systemctl restart consul
consul members
consul leaderNever upgrade all servers at the same time. Upgrade the followers first, check the leader and the Raft health, and only then upgrade the leader.
default_policy = "deny" and issue scoped tokens per service.service-intentions config entries, not the deprecated legacy intention API.consul members in between.Install Vault 2.2, initialise and unseal the server, enable the KV v2 and AWS secrets engines, configure AppRole authentication, audit logging and automatic unsealing.
Install Vagrant 2.4.9, add boxes, manage VirtualBox, VMware, Hyper-V and libvirt providers, share folders and provision machines with Ansible or shell scripts.