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.