c7c0753cd4
Horizon requires Django 1.7 or 1.8 only right now. The docs need to be updated per this change. Change-Id: Ic6670580d5782b8ce29b3f84f3050368443bb629
236 lines
9.4 KiB
ReStructuredText
236 lines
9.4 KiB
ReStructuredText
=================
|
|
Deploying Horizon
|
|
=================
|
|
|
|
This guide aims to cover some common questions, concerns and pitfalls you
|
|
may encounter when deploying Horizon in a production environment.
|
|
|
|
.. seealso:: :doc:`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 the
|
|
``LOGGING`` 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.
|
|
|
|
.. _Django logging directive: https://docs.djangoproject.com/en/1.5/topics/logging
|
|
.. _Python logging directive: http://docs.python.org/2/library/logging.html
|
|
|
|
.. warning::
|
|
|
|
At this time there is `a known bug in python-keystoneclient`_ where it will
|
|
log the complete request body of any request sent to Keystone through it
|
|
(including logging passwords in plain text) when the log level is set to
|
|
``"DEBUG"``. If this behavior is not desired, make sure your log level is
|
|
``"INFO"`` or higher.
|
|
|
|
.. _a known bug in python-keystoneclient: https://bugs.launchpad.net/keystone/+bug/1004114
|
|
|
|
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.
|
|
|
|
|
|
.. _LimitRequestBody directive: http://httpd.apache.org/docs/2.2/mod/core.html#limitrequestbody
|
|
|
|
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.
|
|
|
|
.. _Django's sessions framework: https://docs.djangoproject.com/en/dev/topics/http/sessions/
|
|
|
|
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.
|
|
|
|
The local memory backend is enabled as the default for Horizon solely because
|
|
it has no dependencies. 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`_.
|
|
|
|
.. _Django documentation on cookie-based sessions: https://docs.djangoproject.com/en/dev/topics/http/sessions/#using-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',
|
|
}
|
|
|
|
.. _cross-site scripting: https://www.owasp.org/index.php/HttpOnly
|
|
.. _browser autocompletion: https://wiki.mozilla.org/The_autocomplete_attribute_and_web_documents_using_XHTML
|