OpenStack Horizon Troubleshoot

Troubleshooting OpenStack Horizon (Kolla-Ansible 2024.2)

Problem

After a successful Kolla-Ansible deployment, Horizon could not be reached using the expected URL:

http://192.168.1.50:8080/openstack-horizon/

Instead the browser either failed to connect or was redirected to cAdvisor.


Step 1 — Verify the Horizon container

First confirm Horizon is running.

docker ps --format "table {{.Names}}\t{{.Status}}" | grep horizon

Expected

horizon   Up (healthy)

Result

horizon   Up 2 hours (healthy)

Conclusion

  • Horizon container is healthy.
  • The problem is not Horizon crashing.

Step 2 — Verify HAProxy

docker ps | grep haproxy

Expected

haproxy   Up (healthy)

Result

haproxy   Up 2 hours (healthy)

Conclusion

HAProxy is running correctly.


Step 3 — Determine which port is actually listening

Instead of assuming Horizon is exposed on 8080, inspect listening sockets.

ss -tlnp | grep -E "80|8080|18080"

Result

*:18080 LISTEN

No service was listening on

*:8080

Conclusion

Port 8080 was never serving Horizon.


Step 4 — Test the advertised URL

curl -I http://localhost:8080

Result

curl: (7) Couldn't connect

Testing

curl -I http://localhost:18080

returned

HTTP/1.1 307 Temporary Redirect
Location: /containers/

Opening

http://192.168.1.50:18080

displayed

cAdvisor

instead of Horizon.

Conclusion

Port 18080 belongs to cAdvisor, not Horizon.


Step 5 — Inspect HAProxy configuration

Check whether HAProxy contains a Horizon frontend/backend.

docker exec haproxy grep -n horizon /etc/haproxy/haproxy.cfg

Expected

Configuration entries similar to

frontend horizon
backend horizon

Result

No output.

Conclusion

HAProxy has no Horizon configuration.


Step 6 — Verify Horizon is enabled

grep -n "enable_horizon\|enable_haproxy" /etc/kolla/globals.yml

Result

enable_haproxy: "yes"
enable_horizon: "yes"

Conclusion

Horizon is enabled in Kolla configuration.


Step 7 — Check Docker port mappings

docker inspect horizon --format '{{json .NetworkSettings.Ports}}'

docker inspect haproxy --format '{{json .NetworkSettings.Ports}}'

Result

{}

for both containers.

Explanation

This is normal in Kolla-Ansible.

Kolla containers typically use

network_mode: host

rather than Docker port publishing.


Step 8 — Verify Horizon’s Apache server

Initial attempt

docker exec horizon curl -I http://localhost/

failed.

Reason:

Apache is not bound to localhost.

Inspect listening ports.

docker exec horizon ss -tlnp

Result

192.168.1.51:80
apache2

Apache was listening only on

192.168.1.51

not

127.0.0.1

Therefore test using

docker exec horizon curl -I http://192.168.1.51/

or simply browse to

http://192.168.1.51/

Result

OpenStack Horizon login page displayed successfully.


Step 9 — Determine the actual Horizon URL

Successful login page

http://192.168.1.51/

Therefore

Current deployment

192.168.1.51:80


Horizon

NOT

192.168.1.50:8080/openstack-horizon/

Root Cause

The deployment completed successfully.

The issue was that

  • Horizon is serving directly from the controller IP
192.168.1.51
  • HAProxy is not currently proxying Horizon through the VIP
192.168.1.50
  • Port 18080 belongs to cAdvisor, leading to confusion.

Expected Architecture

Ideally

Browser


192.168.1.50 (VIP)

HAProxy


192.168.1.51
Horizon

Current state

Browser


192.168.1.51
Horizon

Next Diagnostic Steps

1. Check generated HAProxy configuration

docker exec haproxy grep -n -A20 -B5 horizon /etc/haproxy/haproxy.cfg

Expected

frontend horizon
backend horizon

If absent, HAProxy was not configured for Horizon.


2. Search generated Kolla configuration

grep -R "horizon" /etc/kolla/

Verify that Horizon configuration has been generated correctly.


3. Reconfigure HAProxy and Horizon

If configuration is missing, regenerate it using the correct Kolla-Ansible syntax:

source /opt/kolla-venv/bin/activate

kolla-ansible reconfigure -i "$KOLLA_INVENTORY" --tags haproxy,horizon

After completion verify again:

docker exec haproxy grep -n horizon /etc/haproxy/haproxy.cfg

4. Test the VIP

Finally verify that the VIP serves Horizon:

curl -I http://192.168.1.50/

Expected

HTTP/1.1 302 Found

or

HTTP/1.1 200 OK

and the browser should display:

http://192.168.1.50/

instead of requiring direct access to:

http://192.168.1.51/

Key Lessons Learned

  • A healthy Docker container does not guarantee the service is externally reachable.
  • Always verify which ports are actually listening with ss -tlnp.
  • A 307 redirect to /containers/ indicated the request was reaching cAdvisor, not Horizon.
  • Kolla-Ansible commonly uses host networking, so empty Docker port mappings ({}) are expected.
  • curl localhost may fail if Apache is bound only to a specific interface; inspect bind addresses with ss.
  • The absence of Horizon entries in haproxy.cfg is a strong indicator that HAProxy is not proxying the Horizon service.
  • When using Kolla-Ansible, the correct command format is:
kolla-ansible <subcommand> -i "$KOLLA_INVENTORY" [options]

For example:

kolla-ansible reconfigure -i "$KOLLA_INVENTORY" --tags haproxy,horizon

rather than placing the -i option before the subcommand.