The Consul UI at http://91.99.105.61:8500/ui was not accessible from the public internet.
The Hetzner Cloud firewall for the bastion host was configured to only allow access to port 8500 from:
- Private network:
172.16.0.0/16 - WireGuard VPN network:
192.168.100.0/24
This blocked public internet access to the Consul UI.
Updated the firewall rule in main.tf to allow public access to port 8500:
# Before
rule {
direction = "in"
protocol = "tcp"
port = "8500"
source_ips = [var.network_cidr, "192.168.100.0/24"]
}
# After
rule {
direction = "in"
protocol = "tcp"
port = "8500"
source_ips = ["0.0.0.0/0", "::/0"]
}$ curl -s -o /dev/null -w "%{http_code}" http://91.99.105.61:8500/ui/
200✅ Status: Fixed - Consul UI is now accessible at http://91.99.105.61:8500/ui
Current Configuration: The Consul UI is now publicly accessible without authentication.
Enable access control lists to require authentication:
# SSH to bastion
ssh -i ./id_ed25519_hetzner_cloud_k3s admin@91.99.105.61
# Edit Consul config
sudo nano /etc/consul.d/server.hcl
# Change ACL settings
acl {
enabled = true
default_policy = "deny"
enable_token_persistence = true
}
# Restart Consul
sudo systemctl restart consul
# Bootstrap ACL system
consul acl bootstrapLimit access to your IP address only:
variable "allowed_consul_ui_ips" {
description = "List of IPs allowed to access Consul UI"
type = list(string)
default = ["YOUR_IP/32"] # Replace with your public IP
}
# In firewall rule
rule {
direction = "in"
protocol = "tcp"
port = "8500"
source_ips = var.allowed_consul_ui_ips
}Access Consul UI only through the VPN:
# Setup WireGuard client
./setup-vpn-client.sh
# Access through VPN
http://172.16.0.10:8500/uiConfigure Consul with TLS certificates:
- Use Let's Encrypt or your own certificates
- Configure reverse proxy (nginx/traefik) with HTTPS
Add nginx as a reverse proxy with IP restrictions:
location /consul/ {
allow YOUR_IP;
deny all;
proxy_pass http://localhost:8500/;
}| Aspect | Current | Recommended for Production |
|---|---|---|
| Authentication | ❌ None | ✅ ACL enabled with tokens |
| Network Access | ✅ VPN or specific IPs only | |
| Encryption | ✅ HTTPS with valid certificates | |
| Monitoring | ❌ None | ✅ Access logging enabled |
- Enable ACLs immediately:
ssh -i ./id_ed25519_hetzner_cloud_k3s admin@91.99.105.61 << 'EOF'
sudo sed -i 's/enabled = false/enabled = true/' /etc/consul.d/server.hcl
sudo sed -i 's/default_policy = "allow"/default_policy = "deny"/' /etc/consul.d/server.hcl
sudo systemctl restart consul
sleep 5
consul acl bootstrap
EOF- Restrict firewall to your IP:
# Get your public IP
MY_IP=$(curl -s ifconfig.me)
# Update terraform.tfvars
echo "allowed_consul_ui_ips = [\"${MY_IP}/32\"]" >> terraform.tfvars
# Apply changes
terraform apply- Access: Direct public internet
- Auth: None
- Use case: Development/testing only
- Access: IP whitelist + HTTPS
- Auth: Basic auth or ACLs
- Use case: Small teams, internal use
- Access: VPN only
- Auth: ACL tokens required
- Encryption: TLS enabled
- Monitoring: Audit logs enabled
- Use case: Production environments
- ✅ Consul UI is now accessible - Test at http://91.99.105.61:8500/ui
⚠️ Implement security measures - Choose appropriate security level- 📝 Document access procedures - Share with team
- 🔍 Monitor access logs - Watch for unauthorized attempts
To revert to VPN-only access:
rule {
direction = "in"
protocol = "tcp"
port = "8500"
source_ips = ["172.16.0.0/16", "192.168.100.0/24"]
}Then run:
terraform applyFixed on: November 8, 2025
Status: ✅ Working
Security Level:
Recommended Action: Implement ACLs or IP restrictions for production use