Value of SESSION_ENGINE in settings.py had been changed from "cache" to "signed_cookies" in patch: https://review.openstack.org/#/c/6473/12. According info in deployment.rst is out of sync, fix it. Closes-Bug: 1568747 Change-Id: Iaa104479dcf0e094e5c6e9c63c3a518064f6fb6e
8.9 KiB
Deploying Horizon
This guide aims to cover some common questions, concerns and pitfalls you may encounter when deploying Horizon in a production environment.
settings
Note
The Service Catalog returned by the Identity Service after a user has successfully authenticated determines the dashboards and panels that will be available within the OpenStack Dashboard. If you are not seeing a particular service you expected (e.g. Object Storage/Swift or Networking/Neutron) make sure your Service Catalog is configured correctly.
Prior to the Essex release of Horizon these features were controlled
by individual settings in the local_settings.py
file. This
code has been long-since removed and those pre-Essex settings have no
impact now.
Configure Your Identity Service Host
The one thing you must do in order to run Horizon is to
specify the host for your OpenStack Identity Service endpoint. To do
this, set the value of the OPENSTACK_HOST
settings in your
local_settings.py
file.
Logging
Logging is an important concern for production deployments, and the intricacies of good logging configuration go far beyond what can be covered here. However there are a few points worth noting about the logging included with Horizon, how to customize it, and where other components may take over:
- Horizon's logging uses Django's logging configuration mechanism,
which can be customized in your
local_settings.py
file through theLOGGING
dictionary. - Horizon's default logging example sets the log level to
"INFO"
, which is a reasonable choice for production deployments. For development, however, you may want to change the log level to"DEBUG"
. - Horizon also uses a number of 3rd-party clients which log
separately. The log level for these can still be controlled through
Horizon's
LOGGING
config, however behaviors may vary beyond Horizon's control. - For more information regarding configuring logging in Horizon, please read the Django logging directive and the Python logging directive documentation. Horizon is built on Python and Django.
File Uploads
Horizon allows users to upload files via their web browser to other OpenStack services such as Glance and Swift. Files uploaded through this mechanism are first stored on the Horizon server before being forwarded on - files are not uploaded directly or streamed as Horizon receives them. As Horizon itself does not impose any restrictions on the size of file uploads, production deployments will want to consider configuring their server hosting the Horizon application to enforce such a limit to prevent large uploads exhausting system resources and disrupting services. Deployments using Apache2 can use the LimitRequestBody directive to achieve this.
Uploads to the Glance image store service tend to be particularly
large - in the order of hundreds of megabytes to multiple gigabytes.
Deployments are able to disable local image uploads through Horizon by
setting HORIZON_IMAGES_ALLOW_UPLOAD
to False
in your local_settings.py
file.
Note
This will not disable image creation altogether, as this setting does not affect images created by specifying an image location (URL) as the image source.
Session Storage
Horizon uses Django's
sessions framework for handling user session data; however that's
not the end of the story. There are numerous session backends available,
which are controlled through the SESSION_ENGINE
setting in
your local_settings.py
file. What follows is a quick
discussion of the pros and cons of each of the common options as they
pertain to deploying Horizon specifically.
Local Memory Cache
Enabled by:
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
CACHES = {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'
}
Local memory storage is the quickest and easiest session backend to set up, as it has no external dependencies whatsoever. However, it has two significant drawbacks:
- No shared storage across processes or workers.
- No persistence after a process terminates.
It is not recommended for production use, or even for serious development work. For better options, read on.
Memcached
Enabled by:
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
CACHES = {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache'
'LOCATION': 'my_memcached_host:11211',
}
External caching using an application such as memcached offers persistence and shared storage, and can be very useful for small-scale deployment and/or development. However, for distributed and high-availability scenarios memcached has inherent problems which are beyond the scope of this documentation.
Memcached is an extremely fast and efficient cache backend for cases where it fits the deployment need. But it's not appropriate for all scenarios.
Requirements:
- Memcached service running and accessible.
- Python memcached module installed.
Database
Enabled by:
SESSION_ENGINE = 'django.core.cache.backends.db.DatabaseCache'
DATABASES = {
'default': {
# Database configuration here
}
}
Database-backed sessions are scalable (using an appropriate database strategy), persistent, and can be made high-concurrency and highly-available.
The downside to this approach is that database-backed sessions are one of the slower session storages, and incur a high overhead under heavy usage. Proper configuration of your database deployment can also be a substantial undertaking and is far beyond the scope of this documentation.
Cached Database
To mitigate the performance issues of database queries, you can also
consider using Django's cached_db
session backend which
utilizes both your database and caching infrastructure to perform
write-through caching and efficient retrieval. You can enable this
hybrid setting by configuring both your database and cache as discussed
above and then using:
SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
Cookies
signed_cookies
is a session backend that is available to
you which avoids server load and scaling problems.
This backend stores session data in a cookie which is stored by the user's browser. The backend uses a cryptographic signing technique to ensure session data is not tampered with during transport (this is not the same as encryption, session data is still readable by an attacker).
The pros of this session engine are that it doesn't require any additional dependencies or infrastructure overhead, and it scales indefinitely as long as the quantity of session data being stored fits into a normal cookie.
The biggest downside is that it places session data into storage on the user's machine and transports it over the wire. It also limits the quantity of session data which can be stored.
For a thorough discussion of the security implications of this session backend, please read the Django documentation on cookie-based sessions.
Secure Site Recommendations
When implementing Horizon for public usage, with the website served through HTTPS, it is recommended that the following settings are applied.
To help protect the session cookies from cross-site
scripting, add the following to local_settings.py
:
CSRF_COOKIE_HTTPONLY = True
SESSION_COOKIE_HTTPONLY = True
Client-side JavaScript will not be able to access the cookie if this set to True. Note that the HTTPOnly is a flag included in Set-Cookie HTTP response header and is not honored consistently by all browsers.
Additionally, adding the following flags to
local_settings.py
marks the cookies as secure, which
ensures that the cookie is only sent under an HTTPS connection:
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
You can also disable browser
autocompletion for the authentication form by modifying the
HORIZON_CONFIG
dictionary in local_settings.py
by adding the key password_autocomplete
with the value
off
as shown here:
HORIZON_CONFIG = {
...
'password_autocomplete': 'off',
}