OpenStack Horizon -- Web Dashboard
Introduction
Horizon is the web-based dashboard for OpenStack cloud operators and users. It provides a graphical interface to OpenStack services -- launching instances, managing networks, creating volumes, viewing images, and administering projects and users -- without requiring CLI or API knowledge. Horizon is built on the Django web framework and uses a plugin architecture where each OpenStack service contributes panels to the dashboard.
The dashboard organizes content into three panel groups: Project (user-facing resource management), Admin (cloud administrator operations), and Identity (Keystone user/project/domain management). Each panel group loads dynamically based on the user's Keystone role -- a regular user sees only Project panels, while an admin sees all three groups.
Horizon authenticates through Keystone sessions. When a user logs in through the dashboard, Horizon obtains a Keystone token and stores it in the session backend. All subsequent API calls from the dashboard use this token, meaning Horizon respects the same RBAC policies as the CLI and API. Horizon does not have its own user database -- all authentication and authorization flows through Keystone.
Deploy
Horizon deployment via Kolla-Ansible requires enabling the service in globals.yml:
# /etc/kolla/globals.yml
enable_horizon: "yes"
# TLS for HTTPS access (recommended for production)
kolla_enable_tls_external: "yes"
kolla_external_fqdn_cert: "/etc/kolla/certificates/haproxy.pem"
After deployment, Horizon runs as a container behind HAProxy (or nginx, depending on configuration). The default access port is 443 (HTTPS) or 80 (HTTP) on the external VIP address.
Verification commands:
# Verify Horizon container is running
docker ps --filter name=horizon
# Check container health
docker inspect --format '{{.State.Health.Status}}' horizon
# Verify HAProxy routing to Horizon
curl -sI https://<kolla_external_vip_address>/auth/login/ | head -5
# Verify web service is responsive (expect 200 or 302)
curl -so /dev/null -w "%{http_code}" https://<kolla_external_vip_address>/auth/login/
Initial admin login: After kolla-ansible post-deploy, the admin credentials are stored in /etc/kolla/admin-openrc.sh. The default admin user is admin in the default domain. The password is the value of keystone_admin_password in /etc/kolla/passwords.yml.
Configure
Session Backend
Horizon stores user sessions in a backend -- the choice affects performance and reliability:
# Memcached (default in Kolla-Ansible, recommended)
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',
'LOCATION': 'memcached:11211',
}
}
# Database (more durable, slower)
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
Session timeout controls how long a user stays logged in:
SESSION_TIMEOUT = 3600 # 1 hour (seconds)
SESSION_COOKIE_SECURE = True # Requires HTTPS
SESSION_COOKIE_HTTPONLY = True # Prevent JavaScript access
Multi-Domain Support
For clouds with multiple Keystone domains:
OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True
OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'Default'
When enabled, the login page shows a "Domain" field. Users must specify their domain to authenticate.
Panel Visibility
Enable or disable specific dashboard panels:
# Disable panels users shouldn't access
OPENSTACK_NEUTRON_NETWORK = {
'enable_router': True,
'enable_quotas': True,
'enable_distributed_router': False,
'enable_ha_router': False,
'enable_fip_topology_check': True,
}
# Hide specific panels
OPENSTACK_HEAT_STACK = {
'enable': True # Set False to hide Heat panels
}
Custom Branding
Kolla-Ansible supports Horizon customization through config overrides:
# Override directory structure
/etc/kolla/config/horizon/
custom_local_settings # Python settings overrides
themes/ # Custom theme directory
mytheme/
static/
_styles.scss # Custom CSS
img/
logo.svg # Custom logo
logo-splash.svg # Login page logo
favicon.ico # Browser favicon
Key branding settings:
SITE_BRANDING = "My Cloud Dashboard"
AVAILABLE_THEMES = [
('default', 'Default', 'themes/default'),
('mytheme', 'My Theme', 'themes/mytheme'),
]
DEFAULT_THEME = 'mytheme'
Security Settings
# ALLOWED_HOSTS must match the hostname users access
ALLOWED_HOSTS = ['*'] # Restrict in production: ['cloud.example.com']
# CSRF protection
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
# API endpoint configuration
OPENSTACK_KEYSTONE_URL = "http://keystone-internal:5000/v3"
OPENSTACK_API_VERSIONS = {
"identity": 3,
"image": 2,
"volume": 3,
}
Kolla-Ansible Config Overrides
To apply customizations in a Kolla-Ansible managed deployment:
# Place custom settings in the override file
mkdir -p /etc/kolla/config/horizon/
cat > /etc/kolla/config/horizon/custom_local_settings << 'EOF'
SESSION_TIMEOUT = 7200
SITE_BRANDING = "Production Cloud"
OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True
EOF
# Apply changes
kolla-ansible -i all-in-one reconfigure --tags horizon
Operate
User Access Management
Horizon does not manage users directly -- all user management flows through Keystone:
# Create a user (via CLI, reflected in Horizon)
openstack user create --domain default --password changeme newuser
# Assign role in project (grants Horizon panel access)
openstack role add --project myproject --user newuser member
# List users visible in Horizon admin panel
openstack user list --domain default
Session Monitoring
# Check memcached session statistics
docker exec -it memcached sh -c 'echo "stats" | nc localhost 11211'
# Monitor active sessions (look for curr_items)
docker exec -it memcached sh -c 'echo "stats" | nc localhost 11211 | grep curr_items'
Cache Management
# Flush memcached cache (forces all users to re-authenticate)
docker exec -it memcached sh -c 'echo "flush_all" | nc localhost 11211'
# Restart Horizon to clear internal caches
docker restart horizon
Log Analysis
# Horizon application logs
docker logs horizon
docker logs horizon --tail 100 --follow
# Access logs (requests to the dashboard)
docker exec horizon cat /var/log/kolla/horizon/horizon.log
# Error-specific filtering
docker logs horizon 2>&1 | grep -i "error\|exception\|traceback"
Performance Tuning
- Session timeout: Balance security (shorter timeout) vs usability (longer timeout). Default 3600s is reasonable for most deployments.
- Compression: Enable gzip compression in the web server configuration to reduce page load times.
- Static assets: Ensure
collectstatichas been run (Kolla-Ansible handles this automatically). Static assets should be served directly by the web server, not Django. - Caching: Memcached should have enough memory allocated for the expected number of concurrent sessions. Each session uses approximately 2-4 KB.
Troubleshoot
500 Internal Server Error
Memcached down: Horizon stores sessions in memcached by default. If memcached is unreachable, every request fails with a 500 error. Check: docker ps --filter name=memcached -- if the container is not running, restart it: docker restart memcached. Verify connectivity: docker exec horizon python -c "import socket; s=socket.create_connection(('memcached', 11211)); print('OK')".
Keystone unreachable: If Horizon cannot reach the Keystone API, all operations fail. Check: docker exec horizon curl -s http://keystone-internal:5000/v3/ | python -m json.tool. If Keystone is down, restart it first -- Horizon depends on Keystone for every operation.