From d55409b91df4acad6e40fcf1964401bd90ca9827 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Fri, 23 Sep 2016 19:31:26 +0200 Subject: [PATCH 1/4] Documentation refactor. wip --- doc/additional/virtualmachine.rst | 74 ----------- doc/getting_started.rst | 203 ++++++++++++++++++++++++++++++ doc/index.rst | 1 - 3 files changed, 203 insertions(+), 75 deletions(-) delete mode 100644 doc/additional/virtualmachine.rst create mode 100644 doc/getting_started.rst diff --git a/doc/additional/virtualmachine.rst b/doc/additional/virtualmachine.rst deleted file mode 100644 index 471c2c418..000000000 --- a/doc/additional/virtualmachine.rst +++ /dev/null @@ -1,74 +0,0 @@ -Using the virtual machine -************************* - -Introduction -============ - -A virtual machine with a ready-to-use Modoboa setup is available `here -`_. It is composed of -the following components: - -* Debian 6.0 (squeeze) -* Modoboa and its prerequisites -* MySQL -* Postfix -* Dovecot -* nginx and gunicorn - -Actually, it is the result you obtain if you follow the official -documentation. - -The disk image is using the `VMDK -`_ format and is compressed using -bzip2. To decompress it, just run the following command:: - - $ bunzip2 modoboa.vmdk.bz2 - -If you can't use the vmdk format, you can use `qemu -`_ to convert it to another one. For example:: - - $ qemu-img convert modoboa.vmdk -O qcow2 modoboa.qcow2 - -Then, just use your prefered virtualization software (qemu, kvm, -virtualbox, etc.) to start the machine. You'll need to configure at -least one bridged network interface if you want to be able to play -with Modoboa, ie. your machine must be visible from your network. - -The default network interface of the machine (``eth0``) is configured -to use the DHCP protocol. - -Connect to the machine -====================== - -The following UNIX users are available if you want to connect to the system: - -===== ======== ==================== -Login Password Description -===== ======== ==================== -root demo the root user -demo demo an unpriviliged user -===== ======== ==================== - -To connect to Modoboa, first connect to the system and retrieve its -current network address like this:: - - $ /sbin/ifconfig eth0 - -Once you know its address, open a web browser and go to this url:: - - http:///admin/ - -You should see the login page. Here are the users available by default: - -================ ======== ============================================ -Login Password Capabitilies -================ ======== ============================================ -admin password Default super administrator. Can do anything - on the admin but can't access applications - -admin@demo.local admin Administrator of the domain *demo.local*. - Can administrater its domain and access to - applications. - -user@demo.local user Simple user. Can access to applications. -================ ======== ============================================ diff --git a/doc/getting_started.rst b/doc/getting_started.rst new file mode 100644 index 000000000..1c80da81c --- /dev/null +++ b/doc/getting_started.rst @@ -0,0 +1,203 @@ +############### +Getting started +############### + +************ +Installation +************ + +Using the installer +=================== + +If you start from scratch and want to deploy a complete mail server, +you will love the `modoboa installer +`_! It is the easiest +and the quickest way to setup a fully functional server (modooba, +postfix, dovecot, amavis and more) on one machine. + +.. warning:: + + For now, only Debian and CentOS based Linux distributions are + supported. We do our best to improve compatibility but if you use + another Linux or a UNIX system, you will have to install Modoboa + :ref:`by_hand`. + +To use it, just run the following commands in your terminal:: + + $ git clone https://github.com/modoboa/modoboa-installer + $ cd modoboa-installer + $ sudo ./run.py + +Wait a few minutes and you're done \o/ + +.. _by_hand: + +By hand +======= + +In case you already have a running server (postfix, dovecot, etc.) or +you want to build a multi-machine architecture, you can install +Modoboa manually. + +Since Modoboa is a web application written in Python, the procedure +can be splitted in two parts: installing the application and +installing a web server. + +Modoboa +------- + +Prepare the system +~~~~~~~~~~~~~~~~~~ + +First of all, we recommand the following context: + +* using a dedicated system user +* using a `virtualenv `_ to + install the application because it will isolate it (and its + dependencies) from the rest of your system + +The following example illustrates how to realize this (Debian like system):: + + > sudo apt-get install python-virtualenv python-pip + > sudo useradd modoboa + > sudo -i modoboa + > virtualenv env + (env)> source env/bin/activate + (env)> pip install -U pip + +FIXME: dépendances système pour compilation + +Then, install Modoboa:: + + (env)> pip install modoboa + +Database +~~~~~~~~ + +.. warning:: + + This documentation does not cover the installation of a database + server but only the setup of a functional database that Modoboa + will use. + +Thanks to Django, Modoboa is compatible with the following databases: + +* PostgreSQL +* MySQL / MariaDB +* SQLite + +Since the last one does not require particular actions, only the first +two ones are described. + +PostgreSQL +********** + +Install the corresponding Python binding:: + + (env)> pip install psycopg2 + +Then, create a user and a database:: + + > sudo -i postgres + > + +MySQL / MariaDB +*************** + +Install the corresponding Python binding:: + + (env)> pip install MySQL-Python + +Then, create a user and a database:: + + > mysqladmin -u root -p create modoboa + +Deploy an instance +~~~~~~~~~~~~~~~~~~ + +`modoboa-admin.py`, a command line tool, lets you deploy a +*ready-to-use* Modoboa site using only one instruction:: + + (env)> modoboa-admin.py deploy instance --collectstatic \ + --domain --dburl default:database-url + +.. note:: + + You can install additional extensions during the deploy process. To + do so, use the ``--extensions`` option which accepts a list of + names as argument (``--extensions ext1 ext2 ...``). If you want to + install all extensions, just use the ``all`` keyword like this + ``--extensions all``. + + If you choose to install extensions one at a time, you will have to + add their names in settings.py to ``MODOBOA_APPS``. Also ensure that + you have the line ``from modoboa_amavis.settings import *`` at the + end of this file. + + The list of available extensions can be found on the :doc:`index + page <../index>`. Instructions to install them are available on + each extensions page. + +.. note:: + + You can specify more than one database connection using the + ``--dburl`` option. Multiple connections are differentiated by a + prefix. + + The primary connection must use the ``default:`` prefix (as shown + in the example above). For the `amavis + `_ extension, use the + ``amavis:`` prefix. For example: ``--dburl + default: amavis:``. + + A database url should meet the following syntax + ``://[user:pass@][host:port]/dbname`` **OR** + ``sqlite:////full/path/to/your/database/file.sqlite``. + +The command will ask you a few questions, answer them and you're +done. You can now go to the :ref:`first_use` section. + +In case you need a **silent installation** (e.g. if you're using +Salt-Stack, Ansible or whatever), it's possible to supply the database +credentials as commandline arguments. + +You can consult the complete option list by running the following +command:: + + $ modoboa-admin.py help deploy + + + +******* +Upgrade +******* + +.. warning:: + + The new version you are going to install may need to modify your + database. Before you start, make sure to backup everything! + +Most of the time, upgrading your installation to a newer Modoboa +version only requires a few actions. In any case, you will need to +apply the general procedure first and then check if the version you +are installing requires specific actions. + +.. note:: + + In case you use a dedicated user and/or a virtualenv, do not forget to + use them:: + + > sudo -i + > source /bin/activate + +The general procedure is as follows:: + + > pip install modoboa== + > cd + > python manage.py migrate + > python manage.py collectstatic + +Once done, check if the version you are installing requires +:ref:`specific_upgrade_instructions`. + +Finally, restart your web server. diff --git a/doc/index.rst b/doc/index.rst index fa9ecd85a..381770048 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -61,7 +61,6 @@ Additional resource :maxdepth: 2 additional/migrating - additional/virtualmachine ******************* Contributing From 3decd518adbe90a4e48e599fe9c9c2699ecf0407 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 29 Sep 2016 21:29:19 +0200 Subject: [PATCH 2/4] Documentation refactor. wip --- doc/getting_started.rst | 203 -------------- doc/getting_started/upgrade.rst | 302 --------------------- doc/index.rst | 5 +- doc/installation.rst | 463 ++++++++++++++++++++++++++++++++ doc/upgrade.rst | 336 +++++++++++++++++++++++ 5 files changed, 801 insertions(+), 508 deletions(-) delete mode 100644 doc/getting_started.rst create mode 100644 doc/installation.rst create mode 100644 doc/upgrade.rst diff --git a/doc/getting_started.rst b/doc/getting_started.rst deleted file mode 100644 index 1c80da81c..000000000 --- a/doc/getting_started.rst +++ /dev/null @@ -1,203 +0,0 @@ -############### -Getting started -############### - -************ -Installation -************ - -Using the installer -=================== - -If you start from scratch and want to deploy a complete mail server, -you will love the `modoboa installer -`_! It is the easiest -and the quickest way to setup a fully functional server (modooba, -postfix, dovecot, amavis and more) on one machine. - -.. warning:: - - For now, only Debian and CentOS based Linux distributions are - supported. We do our best to improve compatibility but if you use - another Linux or a UNIX system, you will have to install Modoboa - :ref:`by_hand`. - -To use it, just run the following commands in your terminal:: - - $ git clone https://github.com/modoboa/modoboa-installer - $ cd modoboa-installer - $ sudo ./run.py - -Wait a few minutes and you're done \o/ - -.. _by_hand: - -By hand -======= - -In case you already have a running server (postfix, dovecot, etc.) or -you want to build a multi-machine architecture, you can install -Modoboa manually. - -Since Modoboa is a web application written in Python, the procedure -can be splitted in two parts: installing the application and -installing a web server. - -Modoboa -------- - -Prepare the system -~~~~~~~~~~~~~~~~~~ - -First of all, we recommand the following context: - -* using a dedicated system user -* using a `virtualenv `_ to - install the application because it will isolate it (and its - dependencies) from the rest of your system - -The following example illustrates how to realize this (Debian like system):: - - > sudo apt-get install python-virtualenv python-pip - > sudo useradd modoboa - > sudo -i modoboa - > virtualenv env - (env)> source env/bin/activate - (env)> pip install -U pip - -FIXME: dépendances système pour compilation - -Then, install Modoboa:: - - (env)> pip install modoboa - -Database -~~~~~~~~ - -.. warning:: - - This documentation does not cover the installation of a database - server but only the setup of a functional database that Modoboa - will use. - -Thanks to Django, Modoboa is compatible with the following databases: - -* PostgreSQL -* MySQL / MariaDB -* SQLite - -Since the last one does not require particular actions, only the first -two ones are described. - -PostgreSQL -********** - -Install the corresponding Python binding:: - - (env)> pip install psycopg2 - -Then, create a user and a database:: - - > sudo -i postgres - > - -MySQL / MariaDB -*************** - -Install the corresponding Python binding:: - - (env)> pip install MySQL-Python - -Then, create a user and a database:: - - > mysqladmin -u root -p create modoboa - -Deploy an instance -~~~~~~~~~~~~~~~~~~ - -`modoboa-admin.py`, a command line tool, lets you deploy a -*ready-to-use* Modoboa site using only one instruction:: - - (env)> modoboa-admin.py deploy instance --collectstatic \ - --domain --dburl default:database-url - -.. note:: - - You can install additional extensions during the deploy process. To - do so, use the ``--extensions`` option which accepts a list of - names as argument (``--extensions ext1 ext2 ...``). If you want to - install all extensions, just use the ``all`` keyword like this - ``--extensions all``. - - If you choose to install extensions one at a time, you will have to - add their names in settings.py to ``MODOBOA_APPS``. Also ensure that - you have the line ``from modoboa_amavis.settings import *`` at the - end of this file. - - The list of available extensions can be found on the :doc:`index - page <../index>`. Instructions to install them are available on - each extensions page. - -.. note:: - - You can specify more than one database connection using the - ``--dburl`` option. Multiple connections are differentiated by a - prefix. - - The primary connection must use the ``default:`` prefix (as shown - in the example above). For the `amavis - `_ extension, use the - ``amavis:`` prefix. For example: ``--dburl - default: amavis:``. - - A database url should meet the following syntax - ``://[user:pass@][host:port]/dbname`` **OR** - ``sqlite:////full/path/to/your/database/file.sqlite``. - -The command will ask you a few questions, answer them and you're -done. You can now go to the :ref:`first_use` section. - -In case you need a **silent installation** (e.g. if you're using -Salt-Stack, Ansible or whatever), it's possible to supply the database -credentials as commandline arguments. - -You can consult the complete option list by running the following -command:: - - $ modoboa-admin.py help deploy - - - -******* -Upgrade -******* - -.. warning:: - - The new version you are going to install may need to modify your - database. Before you start, make sure to backup everything! - -Most of the time, upgrading your installation to a newer Modoboa -version only requires a few actions. In any case, you will need to -apply the general procedure first and then check if the version you -are installing requires specific actions. - -.. note:: - - In case you use a dedicated user and/or a virtualenv, do not forget to - use them:: - - > sudo -i - > source /bin/activate - -The general procedure is as follows:: - - > pip install modoboa== - > cd - > python manage.py migrate - > python manage.py collectstatic - -Once done, check if the version you are installing requires -:ref:`specific_upgrade_instructions`. - -Finally, restart your web server. diff --git a/doc/getting_started/upgrade.rst b/doc/getting_started/upgrade.rst index 9c41de0f0..60afc1ad9 100644 --- a/doc/getting_started/upgrade.rst +++ b/doc/getting_started/upgrade.rst @@ -42,308 +42,6 @@ version you're installing. To finish, restart the web server process according to the environment you did choose. See :ref:`webservers` for more details. - -.. _specific_upgrade_instructions: - -***************************** -Specific upgrade instructions -***************************** - -1.6.0 -===== - -An interesting feature brougth by this version is the capability to -make different checks about MX records. For example, Modoboa can -query main `DNSBL `_ providers -for every defined domain. With this, you will quickly now if one the -domains you manage is listed or not. To activate it, add the -following line to your crontab:: - - */30 * * * * /manage.py modo check_mx - -The communication with Modoboa public API has been reworked. Instead -of sending direct synchronous queries (for example to check new -versions), a cron job has been added. To activate it, add the -following line to your crontab:: - - 0 * * * * /manage.py communicate_with_public_api - -Please also note that public API now uses TLS so you must update your -configuration as follows:: - - MODOBOA_API_URL = 'https://api.modoboa.org/1/' - -1.5.0 -===== - -The API has been greatly improved and a documentation is now -available. To enable it, add ``'rest_framework_swagger'`` to the -``INSTALLED_APPS`` variable in :file:`settings.py` as follows:: - - INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.sites', - 'django.contrib.staticfiles', - 'reversion', - 'rest_framework.authtoken', - 'rest_framework_swagger', - ) - -Then, add the following content into :file:`settings.py`, just after -the ``REST_FRAMEWORK`` variable:: - - SWAGGER_SETTINGS = { - "is_authenticated": False, - "api_version": "1.0", - "exclude_namespaces": [], - "info": { - "contact": "contact@modoboa.com", - "description": ("Modoboa API, requires a valid token."), - "title": "Modoboa API", - } - } - -You're done. The documentation is now available at the following address: - - http:///docs/api/ - -Finally, if you find a ``TEMPLATE_CONTEXT_PROCESSORS`` variable in -your :file:`settings.py` file, make sure it looks like this:: - - TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + [ - 'modoboa.core.context_processors.top_notifications', - ] - -1.4.0 -===== - -.. warning:: - - Please make sure to use Modoboa 1.3.5 with an up-to-date database - before an upgrade to 1.4.0. - -.. warning:: - - Do not follow the regular upgrade procedure for this version. - -Some extension have been moved back into the main repository. The main -reason for that is that using Modoboa without them doesn't make sense. - -First of all, you must rename the following applications listed inside -the ``MODOBOA_APPS`` variable: - -+--------------------------+--------------------+ -|Old name |New name | -+==========================+====================+ -|modoboa_admin |modoboa.admin | -+--------------------------+--------------------+ -|modoboa_admin_limits |modoboa.limits | -+--------------------------+--------------------+ -|modoboa_admin_relaydomains|modoboa.relaydomains| -+--------------------------+--------------------+ - -Then, apply the following steps: - -#. Uninstall old extensions:: - - $ pip uninstall modoboa-admin modoboa-admin-limits modoboa-admin-relaydomains - -#. Install all extension updates using pip (check the *Modoboa > Information* page) - -#. Manually migrate database:: - - $ cd - $ python manage.py migrate auth - $ python manage.py migrate admin 0001 --fake - $ python manage.py migrate admin - $ python manage.py migrate limits 0001 --fake - $ python manage.py migrate relaydomains 0001 --fake - $ python manage.py migrate - -#. Finally, update static files:: - - $ python manage.py collectstatic - -This version also introduces a REST API. To enable it: - -#. Add ``'rest_framework.authtoken'`` to the ``INSTALLED_APPS`` variable - -#. Add the following configuration inside ``settings.py``:: - - # Rest framework settings - - REST_FRAMEWORK = { - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework.authentication.TokenAuthentication', - ), - 'DEFAULT_PERMISSION_CLASSES': ( - 'rest_framework.permissions.IsAuthenticated', - ) - } - -#. Run the following command:: - - $ python manage.py migrate - -1.3.5 -===== - -To enhance security, Modoboa now checks the `strength of user -passwords _`. - -To use this feature, add the following configuration into the ``settings.py`` file:: - - # django-passwords - - PASSWORD_MIN_LENGTH = 8 - - PASSWORD_COMPLEXITY = { - "UPPER": 1, - "LOWER": 1, - "DIGITS": 1 - } - - -1.3.2 -===== - -Modoboa now uses the *atomic requests* mode to preserve database -consistency (`reference -`_). - -To enable it, update the ``DATABASES`` variable in ``settings.py`` as -follows:: - - DATABASES = { - "default": { - # stuff before... - "ATOMIC_REQUESTS": True - }, - "amavis": { - # stuff before... - "ATOMIC_REQUESTS": True - } - } - -1.3.0 -===== - -This release does not bring awesome new features but it is a necessary -bridge to the future of Modoboa. All extensions now have their own git -repository and the deploy process has been updated to reflect this -change. - -Another important update is the use of Django 1.7. Besides its new -features, the migration system has been reworked and is now more -robust than before. - -Before we begin with the procedure, here is a table showing old -extension names and their new name: - -+----------------------------------------+--------------------------+--------------------------+ -|Old name |New package name |New module name | -+========================================+==========================+==========================+ -|modoboa.extensions.admin |modoboa-admin |modoboa_admin | -+----------------------------------------+--------------------------+--------------------------+ -|modoboa.extensions.limits |modoboa-admin-limits |modoboa_admin_limits | -+----------------------------------------+--------------------------+--------------------------+ -|modoboa.extensions.postfix_autoreply |modoboa-postfix-autoreply |modoboa_postfix_autoreply | -+----------------------------------------+--------------------------+--------------------------+ -|modoboa.extensions.postfix_relay_domains|modoboa-admin-relaydomains|modoboa_admin_relaydomains| -+----------------------------------------+--------------------------+--------------------------+ -|modoboa.extensions.radicale |modoboa-radicale |modoboa_radicale | -+----------------------------------------+--------------------------+--------------------------+ -|modoboa.extensions.sievefilters |modoboa-sievefilters |modoboa_sievefilters | -+----------------------------------------+--------------------------+--------------------------+ -|modoboa.extensions.stats |modoboa-stats |modoboa_stats | -+----------------------------------------+--------------------------+--------------------------+ -|modoboa.extensions.webmail |modoboa-webmail |modoboa_webmail | -+----------------------------------------+--------------------------+--------------------------+ - -Here are the required steps: - -#. Install the extensions using pip (look at the second column in the table above):: - - $ pip install - -#. Remove ``south`` from ``INSTALLED_APPS`` - -#. Rename old extension names inside ``MODOBOA_APPS`` (look at the third column in the table above) - -#. Remove ``modoboa.lib.middleware.ExtControlMiddleware`` from ``MIDDLEWARE_CLASSES`` - -#. Change ``DATABASE_ROUTERS`` to:: - - DATABASE_ROUTERS = ["modoboa_amavis.dbrouter.AmavisRouter"] - -#. Run the following commands:: - - $ cd - $ python manage.py migrate - -#. Reply ``yes`` to the question - -#. Run the following commands:: - - $ python manage.py load_initial_data - $ python manage.py collectstatic - -#. The cleanup job has been renamed in Django, so you have to modify your crontab entry:: - - - 0 0 * * * /manage.py cleanup - + 0 0 * * * /manage.py clearsessions - -1.2.0 -===== - -A new notification service let administrators know about new Modoboa -versions. To activate it, you need to update the -``TEMPLATE_CONTEXT_PROCESSORS`` variable like this:: - - from django.conf import global_settings - - TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + ( - 'modoboa.core.context_processors.top_notifications', - ) - -and to define the new ``MODOBOA_API_URL`` variable:: - - MODOBOA_API_URL = 'http://api.modoboa.org/1/' - -The location of external static files has changed. To use them, add a -new path to the ``STATICFILES_DIRS``:: - - # Additional locations of static files - STATICFILES_DIRS = ( - # Put strings here, like "/home/html/static" or "C:/www/django/static". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. - "/bower_components", - ) - -Run the following commands to define the hostname of your instance:: - - $ cd - $ python manage.py set_default_site - -If you plan to use the Radicale extension: - -#. Add ``'modoboa.extensions.radicale'`` to the ``MODOBOA_APPS`` variable - -#. Run the following commands:: - - $ cd - $ python manage.py syncdb - -.. warning:: - - You also have to note that the :file:`sitestatic` directory has moved from - ```` to ```` (it's probably - the parent directory). You have to adapt your web server configuration - to reflect this change. 1.1.7: manual learning for SpamAssassin ======================================= diff --git a/doc/index.rst b/doc/index.rst index 381770048..0de085cd4 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -13,11 +13,10 @@ Getting started .. toctree:: :maxdepth: 2 - getting_started/install - getting_started/upgrade + installation + upgrade getting_started/configuration - ******* Plugins ******* diff --git a/doc/installation.rst b/doc/installation.rst new file mode 100644 index 000000000..9aecdc052 --- /dev/null +++ b/doc/installation.rst @@ -0,0 +1,463 @@ +############ +Installation +############ + +Using the installer +=================== + +If you start from scratch and want to deploy a complete mail server, +you will love the `modoboa installer +`_! It is the easiest +and the quickest way to setup a fully functional server (modooba, +postfix, dovecot, amavis and more) on one machine. + +.. warning:: + + For now, only Debian and CentOS based Linux distributions are + supported. We do our best to improve compatibility but if you use + another Linux or a UNIX system, you will have to install Modoboa + :ref:`by_hand`. + +To use it, just run the following commands in your terminal: + +.. sourcecode:: bash + + > git clone https://github.com/modoboa/modoboa-installer + > cd modoboa-installer + > sudo ./run.py + +Wait a few minutes and you're done \o/ + +.. _by_hand: + +By hand +======= + +In case you already have a running server (postfix, dovecot, etc.) or +you want to build a multi-machine architecture, you can install +Modoboa manually. + +Prepare the system +------------------ + +First of all, we recommand the following context: + +* Use a dedicated system user +* Use a `virtualenv `_ to + install the application because it will isolate it (and its + dependencies) from the rest of your system + +The following example illustrates how to realize this (Debian like system): + +.. sourcecode:: bash + + > sudo apt-get install python-virtualenv python-pip + > sudo useradd modoboa + > sudo -i modoboa + > virtualenv env + (env)> source env/bin/activate + (env)> pip install -U pip + +FIXME: dépendances système pour compilation + +Then, install Modoboa: + +.. sourcecode:: bash + + (env)> pip install modoboa + +Database +-------- + +.. warning:: + + This documentation does not cover the installation of a database + server but only the setup of a functional database that Modoboa + will use. + +Thanks to Django, Modoboa is compatible with the following databases: + +* PostgreSQL +* MySQL / MariaDB +* SQLite + +Since the last one does not require particular actions, only the first +two ones are described. + +PostgreSQL +********** + +Install the corresponding Python binding: + +.. sourcecode:: bash + + (env)> pip install psycopg2 + +Then, create a user and a database: + +.. sourcecode:: bash + + > sudo -i postgres + > + +MySQL / MariaDB +*************** + +Install the corresponding Python binding: + +.. sourcecode:: bash + + (env)> pip install MySQL-Python + +Then, create a user and a database: + +.. sourcecode:: bash + + > mysqladmin -u root -p create modoboa + +Deploy an instance +------------------ + +``modoboa-admin.py``, a command line tool, lets you deploy a +*ready-to-use* Modoboa site using only one instruction:: + + (env)> modoboa-admin.py deploy instance --collectstatic \ + --domain --dburl default:database-url + +.. note:: + + You can install additional extensions during the deploy process. To + do so, use the ``--extensions`` option which accepts a list of + names as argument (``--extensions ext1 ext2 ...``). If you want to + install all extensions, just use the ``all`` keyword like this + ``--extensions all``. + + If you choose to install extensions one at a time, you will have to + add their names in settings.py to ``MODOBOA_APPS``. Also ensure that + you have the line ``from modoboa_amavis.settings import *`` at the + end of this file. + + The list of available extensions can be found on the :doc:`index + page <../index>`. Instructions to install them are available on + each extensions page. + +.. note:: + + You can specify more than one database connection using the + ``--dburl`` option. Multiple connections are differentiated by a + prefix. + + The primary connection must use the ``default:`` prefix (as shown + in the example above). For the `amavis + `_ extension, use the + ``amavis:`` prefix. For example: ``--dburl + default: amavis:``. + + A database url should meet the following syntax + ``://[user:pass@][host:port]/dbname`` **OR** + ``sqlite:////full/path/to/your/database/file.sqlite``. + +The command will ask you a few questions, answer them and you're +done. You can now go to the :ref:`first_use` section. + +In case you need a **silent installation** (e.g. if you're using +Salt-Stack, Ansible or whatever), it's possible to supply the database +credentials as commandline arguments. + +You can consult the complete option list by running the following +command:: + + $ modoboa-admin.py help deploy + +.. _webservers: + +Web server +---------- + +.. note:: + + The following instructions are meant to help you get your site up + and running quickly. However it is not possible for the people + contributing documentation to Modoboa to test every single + combination of web server, wsgi server, distribution, etc. So it is + possible that **your** installation of uwsgi or nginx or Apache or + what-have-you works differently. Keep this in mind. + +.. _apache2: + +Apache2 +******* + +First, make sure that ``mod_wsgi`` is installed on your server. + +Create a new virtualhost in your Apache configuration and put the +following content inside:: + + + ServerName + DocumentRoot + + Alias /media/ /media/ + /media> + Order deny,allow + Allow from all + + + Alias /sitestatic/ /sitestatic/ + /sitestatic> + Order deny,allow + Allow from all + + + WSGIScriptAlias / //wsgi.py + + + +This is just one possible configuration. + +To use mod_wsgi daemon mode, add the two following directives just +under ``WSGIScriptAlias``:: + + WSGIDaemonProcess example.com python-path=:/lib/python2.7/site-packages + WSGIProcessGroup example.com + +Replace values between ``<>`` with yours. If you don't use a +`virtualenv `_, just +remove the last part of the ``WSGIDaemonProcess`` directive. + +.. note:: + + You will certainly need more configuration in order to launch + Apache. + +.. _nginx-label: + +Nginx +***** + +This section covers two different ways of running Modoboa behind +`Nginx `_ using a WSGI application server. Choose +the one you prefer between `Green Unicorn `_ or +`uWSGI `_. + +In both cases, you'll need to download and `install nginx +`_. + +Green Unicorn +============= + +Firstly, `Download and install gunicorn +`_. Then, use the following sample +gunicorn configuration (create a new file named +:file:`gunicorn.conf.py` inside Modoboa's root dir):: + + backlog = 2048 + bind = "unix:/var/run/gunicorn/modoboa.sock" + pidfile = "/var/run/gunicorn/modoboa.pid" + daemon = True + debug = False + workers = 2 + logfile = "/var/log/gunicorn/modoboa.log" + loglevel = "info" + +To start gunicorn, execute the following commands:: + + $ cd + $ gunicorn -c gunicorn.conf.py .wsgi:application + +Now the nginx part. Just create a new virtual host and use the +following configuration:: + + upstream modoboa { + server unix:/var/run/gunicorn/modoboa.sock fail_timeout=0; + } + + server { + listen 443 ssl; + ssl on; + keepalive_timeout 70; + + server_name ; + root ; + + access_log /var/log/nginx/.access.log; + error_log /var/log/nginx/.error.log; + + ssl_certificate ; + ssl_certificate_key ; + + location /sitestatic/ { + autoindex on; + } + + location /media/ { + autoindex on; + } + + location / { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_redirect off; + proxy_set_header X-Forwarded-Protocol ssl; + proxy_pass http://modoboa; + } + } + +If you do not plan to use SSL then change the listen directive to +``listen 80;`` and delete each of the following directives:: + + ssl on; + keepalive_timeout 70; + ssl_certificate ; + ssl_certificate_key ; + proxy_set_header X-Forwarded-Protocol ssl; + +If you do plan to use SSL, you'll have to generate a certificate and a +key. `This article +`__ +contains information about how to do it. + +Paste this content to your configuration (replace values between +``<>`` with yours) and restart nginx. + +uWSGI +===== + +The following setup is meant to get you started quickly. You should +read the documentation of both nginx and uwsgi to understand how to +optimize their configuration for your site. + +The Django documentation includes the following warning regarding +uwsgi: + +.. warning:: + + Some distributions, including Debian and Ubuntu, ship an outdated + version of uWSGI that does not conform to the WSGI + specification. Versions prior to 1.2.6 do not call close on the + response object after handling a request. In those cases the + request_finished signal isn’t sent. This can result in idle + connections to database and memcache servers. + +Use uwsgi 1.2.6 or newer. If you do not, you *will* run into +problems. Modoboa will fail in obscure ways. + +To use this setup, first `download and install uwsgi +`_. + +Here is a sample nginx configuration:: + + server { + listen 443 ssl; + ssl on; + keepalive_timeout 70; + + server_name ; + root ; + + ssl_certificate ; + ssl_certificate_key ; + + access_log /var/log/nginx/.access.log; + error_log /var/log/nginx/.error.log; + + location /sitestatic/ { + autoindex on; + alias ; + } + + # Whether or not Modoboa uses a media directory depends on how + # you configured Modoboa. It does not hurt to have this. + location /media/ { + autoindex on; + alias ; + } + + # This denies access to any file that begins with + # ".ht". Apache's .htaccess and .htpasswd are such files. A + # Modoboa installed from scratch would not contain any such + # files, but you never know what the future holds. + location ~ /\.ht { + deny all; + } + + location / { + include uwsgi_params; + uwsgi_pass ; + uwsgi_param UWSGI_SCRIPT .wsgi:application; + uwsgi_param UWSGI_SCHEME https; + } + } + +```` must be replaced by the value you used +when :ref:`you deployed your instance `. + +If you do not plan to use SSL then change the listen directive to +``listen 80;`` and delete each of the following directives:: + + ssl on; + keepalive_timeout 70; + ssl_certificate ; + ssl_certificate_key ; + uwsgi_param UWSGI_SCHEME https; + +If you do plan to use SSL, you'll have to generate a certificate and a +key. `This article +`_ +contains information about how to do it. + +Make sure to replace the ``<...>`` in the sample configuration with +appropriate values. Here are some explanations for the cases that may +not be completely self-explanatory: + +```` + Where Modoboa's :file:`settings.py` resides. This is also where the + :file:`sitestatic` and :file:`media` directories reside. + +```` + This is the URL which will be the root of your Modoboa site at your + domain. For instance, if your Modoboa installation is reachable at + at ``https://foo/modoboa`` then ```` is + ``/modoboa``. In this case you probably also have to set the + ``alias`` directives to point to where Modoboa's sitestatic and + media directories are because otherwise nginx won't be able to find + them. + + If Modoboa is at the root of your domain, then ```` is an empty string and can be deleted from the configuration + above. In this case, you probably do not need the ``alias`` + directives. + +```` + The location where uwsig is listening. It could be a unix domain + socket or an address:port combination. Ubuntu configures uwsgi so + that the port is:: + + unix:/run/uwsgi/app//socket + + where ```` is the name of the application. + +Your uwsgi configuration should be:: + + [uwsgi] + # Not needed when using uwsgi from pip + # plugins = python + chdir = + module = .wsgi:application + master = true + harakiri = 60 + processes = 4 + vhost = true + no-default-app = true + +The plugins directive should be turned on if you use a uwsgi +installation that requires it. If uwsgi was installed from pip, it +does not require it. In the configuration above: + +```` + The directory where :file:`manage.py` resides. This directory is the + parent of ```` + +```` + The name that you passed to ``modoboa-admin.py deploy`` when you + created your Modoboa instance. diff --git a/doc/upgrade.rst b/doc/upgrade.rst new file mode 100644 index 000000000..832c74d48 --- /dev/null +++ b/doc/upgrade.rst @@ -0,0 +1,336 @@ +####### +Upgrade +####### + +.. warning:: + + The new version you are going to install may need to modify your + database. Before you start, make sure to backup everything! + +Most of the time, upgrading your installation to a newer Modoboa +version only requires a few actions. In any case, you will need to +apply the general procedure first and then check if the version you +are installing requires specific actions. + +.. note:: + + In case you use a dedicated user and/or a virtualenv, do not forget to + use them: + + .. sourcecode:: bash + + > sudo -i + > source /bin/activate + +The general procedure is as follows:: + + > pip install modoboa== + > cd + > python manage.py migrate + > python manage.py collectstatic + +Once done, check if the version you are installing requires +:ref:`specific_upgrade_instructions`. + +Finally, restart your web server. + +.. _specific_upgrade_instructions: + +Specific instructions +********************* + +1.6.0 +===== + +An interesting feature brougth by this version is the capability to +make different checks about MX records. For example, Modoboa can +query main `DNSBL `_ providers +for every defined domain. With this, you will quickly now if one the +domains you manage is listed or not. To activate it, add the +following line to your crontab:: + + */30 * * * * /manage.py modo check_mx + +The communication with Modoboa public API has been reworked. Instead +of sending direct synchronous queries (for example to check new +versions), a cron job has been added. To activate it, add the +following line to your crontab:: + + 0 * * * * /manage.py communicate_with_public_api + +Please also note that public API now uses TLS so you must update your +configuration as follows:: + + MODOBOA_API_URL = 'https://api.modoboa.org/1/' + +1.5.0 +===== + +The API has been greatly improved and a documentation is now +available. To enable it, add ``'rest_framework_swagger'`` to the +``INSTALLED_APPS`` variable in :file:`settings.py` as follows:: + + INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.sites', + 'django.contrib.staticfiles', + 'reversion', + 'rest_framework.authtoken', + 'rest_framework_swagger', + ) + +Then, add the following content into :file:`settings.py`, just after +the ``REST_FRAMEWORK`` variable:: + + SWAGGER_SETTINGS = { + "is_authenticated": False, + "api_version": "1.0", + "exclude_namespaces": [], + "info": { + "contact": "contact@modoboa.com", + "description": ("Modoboa API, requires a valid token."), + "title": "Modoboa API", + } + } + +You're done. The documentation is now available at the following address: + + http:///docs/api/ + +Finally, if you find a ``TEMPLATE_CONTEXT_PROCESSORS`` variable in +your :file:`settings.py` file, make sure it looks like this:: + + TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + [ + 'modoboa.core.context_processors.top_notifications', + ] + +1.4.0 +===== + +.. warning:: + + Please make sure to use Modoboa 1.3.5 with an up-to-date database + before an upgrade to 1.4.0. + +.. warning:: + + Do not follow the regular upgrade procedure for this version. + +Some extension have been moved back into the main repository. The main +reason for that is that using Modoboa without them doesn't make sense. + +First of all, you must rename the following applications listed inside +the ``MODOBOA_APPS`` variable: + ++--------------------------+--------------------+ +|Old name |New name | ++==========================+====================+ +|modoboa_admin |modoboa.admin | ++--------------------------+--------------------+ +|modoboa_admin_limits |modoboa.limits | ++--------------------------+--------------------+ +|modoboa_admin_relaydomains|modoboa.relaydomains| ++--------------------------+--------------------+ + +Then, apply the following steps: + +#. Uninstall old extensions:: + + $ pip uninstall modoboa-admin modoboa-admin-limits modoboa-admin-relaydomains + +#. Install all extension updates using pip (check the *Modoboa > Information* page) + +#. Manually migrate database:: + + $ cd + $ python manage.py migrate auth + $ python manage.py migrate admin 0001 --fake + $ python manage.py migrate admin + $ python manage.py migrate limits 0001 --fake + $ python manage.py migrate relaydomains 0001 --fake + $ python manage.py migrate + +#. Finally, update static files:: + + $ python manage.py collectstatic + +This version also introduces a REST API. To enable it: + +#. Add ``'rest_framework.authtoken'`` to the ``INSTALLED_APPS`` variable + +#. Add the following configuration inside ``settings.py``:: + + # Rest framework settings + + REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework.authentication.TokenAuthentication', + ), + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticated', + ) + } + +#. Run the following command:: + + $ python manage.py migrate + +1.3.5 +===== + +To enhance security, Modoboa now checks the `strength of user +passwords _`. + +To use this feature, add the following configuration into the ``settings.py`` file:: + + # django-passwords + + PASSWORD_MIN_LENGTH = 8 + + PASSWORD_COMPLEXITY = { + "UPPER": 1, + "LOWER": 1, + "DIGITS": 1 + } + + +1.3.2 +===== + +Modoboa now uses the *atomic requests* mode to preserve database +consistency (`reference +`_). + +To enable it, update the ``DATABASES`` variable in ``settings.py`` as +follows:: + + DATABASES = { + "default": { + # stuff before... + "ATOMIC_REQUESTS": True + }, + "amavis": { + # stuff before... + "ATOMIC_REQUESTS": True + } + } + +1.3.0 +===== + +This release does not bring awesome new features but it is a necessary +bridge to the future of Modoboa. All extensions now have their own git +repository and the deploy process has been updated to reflect this +change. + +Another important update is the use of Django 1.7. Besides its new +features, the migration system has been reworked and is now more +robust than before. + +Before we begin with the procedure, here is a table showing old +extension names and their new name: + ++----------------------------------------+--------------------------+--------------------------+ +|Old name |New package name |New module name | ++========================================+==========================+==========================+ +|modoboa.extensions.admin |modoboa-admin |modoboa_admin | ++----------------------------------------+--------------------------+--------------------------+ +|modoboa.extensions.limits |modoboa-admin-limits |modoboa_admin_limits | ++----------------------------------------+--------------------------+--------------------------+ +|modoboa.extensions.postfix_autoreply |modoboa-postfix-autoreply |modoboa_postfix_autoreply | ++----------------------------------------+--------------------------+--------------------------+ +|modoboa.extensions.postfix_relay_domains|modoboa-admin-relaydomains|modoboa_admin_relaydomains| ++----------------------------------------+--------------------------+--------------------------+ +|modoboa.extensions.radicale |modoboa-radicale |modoboa_radicale | ++----------------------------------------+--------------------------+--------------------------+ +|modoboa.extensions.sievefilters |modoboa-sievefilters |modoboa_sievefilters | ++----------------------------------------+--------------------------+--------------------------+ +|modoboa.extensions.stats |modoboa-stats |modoboa_stats | ++----------------------------------------+--------------------------+--------------------------+ +|modoboa.extensions.webmail |modoboa-webmail |modoboa_webmail | ++----------------------------------------+--------------------------+--------------------------+ + +Here are the required steps: + +#. Install the extensions using pip (look at the second column in the table above):: + + $ pip install + +#. Remove ``south`` from ``INSTALLED_APPS`` + +#. Rename old extension names inside ``MODOBOA_APPS`` (look at the third column in the table above) + +#. Remove ``modoboa.lib.middleware.ExtControlMiddleware`` from ``MIDDLEWARE_CLASSES`` + +#. Change ``DATABASE_ROUTERS`` to:: + + DATABASE_ROUTERS = ["modoboa_amavis.dbrouter.AmavisRouter"] + +#. Run the following commands:: + + $ cd + $ python manage.py migrate + +#. Reply ``yes`` to the question + +#. Run the following commands:: + + $ python manage.py load_initial_data + $ python manage.py collectstatic + +#. The cleanup job has been renamed in Django, so you have to modify your crontab entry:: + + - 0 0 * * * /manage.py cleanup + + 0 0 * * * /manage.py clearsessions + +1.2.0 +===== + +A new notification service let administrators know about new Modoboa +versions. To activate it, you need to update the +``TEMPLATE_CONTEXT_PROCESSORS`` variable like this:: + + from django.conf import global_settings + + TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + ( + 'modoboa.core.context_processors.top_notifications', + ) + +and to define the new ``MODOBOA_API_URL`` variable:: + + MODOBOA_API_URL = 'http://api.modoboa.org/1/' + +The location of external static files has changed. To use them, add a +new path to the ``STATICFILES_DIRS``:: + + # Additional locations of static files + STATICFILES_DIRS = ( + # Put strings here, like "/home/html/static" or "C:/www/django/static". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + "/bower_components", + ) + +Run the following commands to define the hostname of your instance:: + + $ cd + $ python manage.py set_default_site + +If you plan to use the Radicale extension: + +#. Add ``'modoboa.extensions.radicale'`` to the ``MODOBOA_APPS`` variable + +#. Run the following commands:: + + $ cd + $ python manage.py syncdb + +.. warning:: + + You also have to note that the :file:`sitestatic` directory has moved from + ```` to ```` (it's probably + the parent directory). You have to adapt your web server configuration + to reflect this change. From e4e4e4c53cd878695dac2193c8a96f013978be58 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 18 Oct 2016 17:28:34 +0200 Subject: [PATCH 3/4] Refactored documentation. --- CONTRIBUTING.rst | 20 +- doc/_static/api_access_form.png | Bin 0 -> 17340 bytes doc/_static/modoboa_logo.png | Bin 0 -> 13830 bytes doc/additional/migrating.rst | 15 - doc/conf.py | 2 +- doc/{getting_started => }/configuration.rst | 0 doc/contributing.rst | 32 +- doc/{extending => contributing}/events.rst | 0 .../getting_started.rst | 0 .../plugin_api.rst | 0 doc/getting_started/install.rst | 200 -------- doc/getting_started/upgrade.rst | 301 ------------ doc/index.rst | 121 ++--- doc/installation.rst | 450 ++---------------- .../dovecot.rst} | 80 +--- doc/manual_installation/modoboa.rst | 140 ++++++ doc/manual_installation/postfix.rst | 67 +++ .../webserver.rst} | 63 ++- doc/plugins/amavis.rst | 7 - doc/plugins/postfix_autoreply.rst | 7 - doc/plugins/radicale.rst | 5 - doc/plugins/sievefilters.rst | 5 - doc/plugins/statistics.rst | 7 - doc/plugins/webmail.rst | 7 - doc/rest_api.rst | 31 ++ doc/upgrade.rst | 71 ++- modoboa/core/forms.py | 2 +- 27 files changed, 451 insertions(+), 1182 deletions(-) create mode 100644 doc/_static/api_access_form.png create mode 100644 doc/_static/modoboa_logo.png delete mode 100644 doc/additional/migrating.rst rename doc/{getting_started => }/configuration.rst (100%) rename doc/{extending => contributing}/events.rst (100%) rename doc/{extending => contributing}/getting_started.rst (100%) rename doc/{extending => contributing}/plugin_api.rst (100%) delete mode 100644 doc/getting_started/install.rst delete mode 100644 doc/getting_started/upgrade.rst rename doc/{integration/imap_and_smtp.rst => manual_installation/dovecot.rst} (83%) create mode 100644 doc/manual_installation/modoboa.rst create mode 100644 doc/manual_installation/postfix.rst rename doc/{integration/web_servers.rst => manual_installation/webserver.rst} (88%) delete mode 100644 doc/plugins/amavis.rst delete mode 100644 doc/plugins/postfix_autoreply.rst delete mode 100644 doc/plugins/radicale.rst delete mode 100644 doc/plugins/sievefilters.rst delete mode 100644 doc/plugins/statistics.rst delete mode 100644 doc/plugins/webmail.rst create mode 100644 doc/rest_api.rst diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 99efbbdd1..5c18a6a0b 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,19 +1 @@ -Contributions are always welcome but please try to follow those few rules: - -- Modoboa tries to respect the `PEP8 `_. - -- If you add some code, add some tests too. You can run the tests - suite locally by using `tox `_ - -There are also a few commands that can help you to contribute: - -Start a basic Modoboa instance with a few fixture:: - - $ tox -e serve - -You can log in with admin/password. - -Build the docs to see your changes:: - - $ tox -e doc - $ firefox .tox/doc/tmp/html/index.html +.. include:: doc/contributing.rst diff --git a/doc/_static/api_access_form.png b/doc/_static/api_access_form.png new file mode 100644 index 0000000000000000000000000000000000000000..fb1bf02579373d469597487658e64952c95b0794 GIT binary patch literal 17340 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 literal 0 HcmV?d00001 diff --git a/doc/_static/modoboa_logo.png b/doc/_static/modoboa_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..fe42c28ca534451388b3f4b412e54c7922bdccd3 GIT binary patch literal 13830 zcmYLQ1z3~c_a7l3f~bI$lt>Fw8(k6tj@&>}=?)PFIFXc+RJwb>C~0XBq??V=Ak8Kq zB@KV@`+J`M`#js;`#I;Hd(XM&?%s1FOiSYhIVn9U001CYRZ-Ld0PxY*?;|8c*WW$A z(s!?aZogGAa03AN*={~~Uiq>f*C3s{lD<2{#oFD|?41=r-qOX~ibd7Q%*IN`%FOb; zYp<0Q004|tRg{N%P5(|Gbb0h5Wi9Yi`Et(b6FDJ$odrYkm|!Vkz9WD3lIp){ihL<4 z^%Wvp3C_G@+rjRe+OB7hEf8Bv^G}WFR&gEWf34 zIo(hIN%pbI@Dz2C<|vvK8&C7VK@J9O$Ny3I*ch4FxgP78efysjs|a^-crxYB&nmcY zoon!0*G+Q$v_ZSA8|a%y1cR_ygrz)VS!_a+PCfs!Bw?56Hia1MK7-ks*`!}OmZiqv z-((R${}dRn*+^0vHS$l`EM@}|{)Y;Tvq;C$>x2)$2>z3eptq*a6UDfN8vnDvzhubR zbNin98z%sOYnZL!;NP;|p~Uy*K20=cbl9`r;C@9O7_ITsF_=FP@zGTNx9mu0q~#3( z0NDyn<`2I({8}+o{f1?M{st33N6}(aR&d8wcX_d3V}DArbxb2JHx5K$H_hEcNsn#YFeB~-{8lcg`B|+51OmZ z3h&^pb}y`ZzrTS2&)&-D46b2$J|kmB5Q5_>#Q!V>u4zeDZXjmiV$6F$hkKZJ!|7Kn zmVDV>{6WO5(0@{s_=E>ZsjKpzUG3j1n3yR#$a^x4N~0aV+)>Xp}&_y1XnY6#k)ML_%S{gdL_Ci6A< zaU7{mS4a5294TP7n;b%}op7>$jmn||8N_K_=a~Vw>E9Uj29RVox1fp1uW*+8r;26J zVH&na>s3zTSq%M3+gR25jBd}3IKYg4By``Nj5mgErSs_m`#*Dh`&^>}T(1WGye#zs z?5(U^bF2TyZ8RAHEpO8zc%dK0@!sk`tQ-upG_@b?r&_rcrS(8X;l?BVlp+dz7uyvV z1-#zgzbR%r)qW_~IsBrB1;GCfB=o=LZ{tFY%j%gH`Y(&bydl5gvr&gxLe~iQ3jNPU z^2+h(ZZOjaY@5tYOoy*xD7`v=TvrCz0|>yOUMLsJW@wxjQ6KKBynk0!(r2t^abDoz zUZS{Ka|Z_CDl2ln{WO#Ke0i=%zmA1~q$dxUlQ_k6*^RA!onv1q#QI`UNCmdqTB1qtG&bJ0p4bzSwI~b+O8Cn?9fbfDavl;bh8$ zgq?Krx2bL{!6FG^ly}f!Tf%#eAFFtSSlS@PuiWpB`L`v7Vm+vZ{&7)47_}+A#O{Am zO^2l3Ab{V=_E9>+&q4RNL<~AjXm6lNAlh73ja;s0fYtDy=^YUC+V)!a?v>tnjGr`w z?_NI9PrOn48|EZYbf`{XfWPg(E;^8E@6QF~ViLF+KL9anrDiU2ai{807sp9nXIpg( z$7dbH6s~i>v~pm@*Vb{CyBTu;c_8$C^y543OBa+&7aL-`<3~TEqZuiEcmKX2yBO#Q z@qNJX#^rZ1nwWwqlqQ{K=*>~)n{xy2=87+8FiB-T2~*^aa|*`vXb8Rc#H ziNo)e)jY%D37Zy~)h$5JBy_)aP&E8;SADBAr;qC|w%uF{*~)j9TU$;Q=jHuN;m>?* zL`cDyi{5gXhanWqf3XeHWY%#@XZ?0m<?G69l^dC7cR1zEg-$zalJf}z;Wq!dz5e=h#)!9 z!?id>L;5kRyu5f1l`AaFsK2gr);FDEuYus#b?^Luxvk8I7D;VUGhYOENH8Q>qdZHf zzAbY~Tc~%NjE>tt24iC_rGeQvdR)U&%KKhq$)qADjE`;%76fymDcMS$sG_X92*A=2 zKS2Z~mxSsMQ*Ud!jaC&DMUeq7dS(Pr+q6(MNV2%-@*Iq~Q^yin%mmYOn>Cm+t}p0d z)bBXlFjbQ-S}wQFT7NCQjOU@WOW!Pv9tC!%WK^8%8X0Ti_-ScUt>OiI+N;L)L(=kZ4wUMB5^hd_+MePJ8Qes@ls_rlckmk2z5(nBE1J1 zEk19iTVIvZ^9$Ge9hGyLcYg#R2cJ-s@%&xuy&vo`{ZAA||NAdg7Y zHD5}^d~fdDYGqWJdFD1VtS~I5fB$QSYZm7-Y255~X)4Z#f`_Q?QxZjR3d=s2Lt-uV zjnD6<>}}W_p3ah_m_|zLM%K`gwMMYvH~9utOuIG8K{$QHP3nbok^K8|8%M+xxOPfw zEuUBE=gtevm?ayw`6T?Vkm-?9i@(6>wo9&q-8a@l15Hvg@6_Ck{I-L<+rM9l$_;&QqGGPU#=b2HBc{5l27}Db`oBW~+9Wr^&d7FF3vF z0X*(=QJV(l(y1+X%hE#Tm;49gE37^b!aDx4IA~+UCk`VN5~)+$Q(PMM@}6l5&uI=n ze3R-DyCH$w?BjW->LzWoRp(jY`>7U7%qM#!dxg1DX*MJ(^^iC69Dg|f#R0V70XZwe$Kl);x-R+ zWvqu*@2s@9uF1E)s1xLEW@>U1yabvQ5m+AnVnNl}7e{E8J||%$akDydlZDk%!l;1qx?Vc~KRLisBPC-~d^;uTV?^J_ zUvKDtJ;gvU;|Xh0MgYe9d2Any6a4>mR zv@-kD`#F!*Y)O!hs5E-qV7xnUTsL~==o4`l{D*=`f$?bkAeTB~*vnXR`SxNG0bD1! zR;o0y{6GY_`+*ke@E>~VLhkPHH z@4Oycx-+B~hMebKHr9QJl`LeZt3s*jK>hXt+=MX+``WRRKJ47#a-!pEwDG}8xs?;^ zJ0N$y3bUezrh&ONc$A{!ltW%Wbb5KIBgjq1$1EE@Bo044oaIZ(05SQb31zQ4h@-z4 zc+sh8?zUd-_;Sg*C;l|-2POQ?6``J)3BtWT(!AXJYDzRJ^x@~CzPWm@Rd1D#qkJTgocOgdAz3vaN#svpwOW* zqi@4d6$Odyx-7A?aAGNFD6-?3XvE^m^2&Avt-dk$&FUKo_&MB`HtIN73A1@eBM;fK zNJ|&JI_1zNqot9;BAGxo~_fsWC^=-EdboGrJZ8g;gwU{Ej!4|Rjc~V z&qFZc2JQiKOJwOfkX{63*myurYgrr|VTYiYrGd4KMNsakVB8a<5tbvpB56ryKJu0o~IJ+KTd{F(|En(mU5qV98 z$rFR&?{n)28=->fVxSdq3bs|U;J^pY;`nu0pVs&`&HEnl;3pCva|B2rXJ;5cq`t@ct~( z*hUfcAJr7B8i{iVQxwGHZd8QbM1SibgFuIY2H{tXI&W^zb8fL}(wC+G(<( z>rS8@31m6ncrxlrZ+YrmV2OIvCl`NA^QI57ucy&96q$7ejap7`nq!5 z_|%jfuPSKeQh?2Mli-<&s`fRwOi)IZMCvvnO%Y-c49)6sU}A{Z%GkBxW_p@eO$zrD zh{jzmb7L0J#vh&B;2rEeAjAdav_{OVoFWyIT6-Wq?KtmUT zO+BEZA9~%6WDWoB$X*VM8fFge@YB#f7{1S1+z(o=kKYmNiS|yknbwp zB}zEjDNYT0XS4*Rpm9UT?0l{v7F3tFKv9!4d^cRB)B(_VEVy{$8z52j!<} zbsA8AE?ck93C6<4$Aa<745aO{M_-AMA3j(|tl9&_?bTc5IT=^J+AGSvi;>MOTCaW< zEK$&|+O3u8Y1R)1xx_wy#@Jb;E@~XW$v~a$**F*Mj}|=M4J;xjKFD+MdZjS@RY_Vm zEKpkgI_>k4vpJY!0XQYvjc9oAJQqQN?3+e;ULIR*V@lk}-_TFavg2?v=R;=qX+dN8 z?vEEquY;4v^WO4AsRj|(c8JcN&C?DNycuMoy`OY2&gJc!Eo7n}GC z<9tfVF)k<8R}AldnwWq2+>8fwHMaMJ)+Z}0)OK2z z{lq{1S(N8cmfFGjyb;9A5kxpg{0Q{JiYFQa{ZhK%#_R1dG8<1JHJzhmrXEY{aoHf# z5*z8sJ}FI;8FOC)VclgNVOJVCx93}FH>61LrPt$9iC5HN~ zj{?qNR5YzxewGLoweci4s4O+%fLAEwE)z)n8#1LHhG9c`e?(Hu4&*cHpX?(8+a5ed zDZujmO@Qgv?Me!B9s29$`uLy;3FU8jqt0jQg}UQ1X(A}@$i?s3>@OWY!@I;$jdyWV zRA)sjJmB69x>Rh~J^H;03)!ze<$aZJYu}$j=b@?k3)58TG<*H`GLARTSfdz~-|^OG zBNcTee`Lm$BDIXDJ3HHu5`|?9^aBbnU`usag%w$|5?$g+Qe>wVTj6w>jye*^iQ4C9 z!1A+wH?1G^z!^Nm78gLJM`Jn8ke-l`iBj#?C%JF01FByGHI5$|B9A(JeOXAOisW@` zmiO0KC0aDlB;mE~=tt0EFD`BSx4OOBTYomv*4bh?yQopq;GVY;r*n^RWH z%7_l~DxO=t|6V<6kFL}ocz63b!N?9o^(uuHl#Eb;(W%S6$+&DSxYw=;Ub*`63mT^L ztp3lFnqV_+gYMcmbCx8%M^GB?P^6e2wsW{KjFjPFJf6oye)>a31P^LVu2RUK@z**d z5~-v<=8Z{Ep`#nl9^A3t5GIC@`!Rx7pvCTnEqC!Nxckjbbw@*p@K(C|H1#YE_MaNY zclm*H?P*2%mnC>#y(QFUm(w1$kA2z!9|IQ8>L!o8|CT_&z=QWWCED{`OeOy-(L3uA zOL_#oU)mz{Ry=Vlwgtg$OI89wYRmbw_U*F*^FFFiq~xk&qN9rU>wsvgk=vb|6jK5S5p z1dsHRyqJH3t|za&R4lpdKp3rZ1(0Jdm6WEpW)G$2flBgE)%a0k$X+Y)*TnmKv1ctb zo2#-V*-L)p#TFSva`465{fU(kLQ~qV1H_!VUg4i@fr#|t@p8kkA#e%Hy%(|kQ^XHn z_7o>f#0L;ma_mgWs^Wr(FpvInHefrtg5l#>S)9fU!t=cT!} zk(zqb;y#|ja;oal_j!i3e?K(7QCus}!0o;k7;?Rk`kww_mNMM~GGHyDo8+K?n}g+A zH@`&*(Dhm^5MV$6AqV_P2R)H<=T>}6L*z+%gSI`gQV~d!auZ?1ABD#`gtA;X9e3Wb zAiO4JEg~eIRcRgcyy+f$&+Cr`TK!53${<{$`AmJR5-IiJkTuKsamrMO0usB#y`wQZnYNv(@jbQT}jZcnAOnh(N!7f zw>fC(-Ejb)N7@17M+kLi%cdp>pLCug_fidm=PCE{3|B?B=;4|h7u?sC$}odF7-SBR z!a5O{&4hU{NA)AcpQocxsf&jLpA8_T-}T<*FE*rr{FTZJ5S-ks6T>J3{EiSHM%*dr zC>V6F(7m&g(fdoJ+E1Nk$a`PzHlubBES}M`K+#JD$0LlVZCp^VV=68AHMOPH+wH8eYm2xf_rB+adNoq&z$*q0-kxr>TMU$dYB}-i31TwpaVMynK>6hNw(kO<6hX zQb;-9H9>yumFVs=@)#5Kw_;upxnBKJzm5_n;C~cc?`4qYFE1^)b_JYptvpd0&2ty= zcmpXaK>N9;>k05W(7zddYW}fC49}6eBEyhWi>g)@XoZ}K!SgfLqKibmPl7u+6=kM!Q1#bwl!rZV6W43LZ>+##?HpyXl%(%$ktOtx}4yyTQsxGnumI8 zD)-k}?ZxhP;pe}U`i46&NTib--Uyr1jP~aDu8+}Wds)azMN@@cUMNu{_rfdPU#F)1 zc^f|bp9+y`k~rHH2yO#=VX3q$soO9Qe?S)n?gfPUtwUmkF^XdQZgXqTCXyRfX*i;5vhp`tk8#Yyz$b z6N`=DK=B;9JsidEr~@Bg_h(Zikcfg_zd3^B4@;I%AxNZE4Q87D7do7>l!Yv|kvf5d z;lJJ!t83s`aVf&3v|dN(OHaOS@0$2E{PajW2XlslzPQaWL(;x`h%K@_O_VnQ2qGKd zc!0JZ6DG8O)>^9BFL}9|4m9H*Xlu7*Zq9x6tx)&-y6Jm=hQ7UB(P2-7n^*wjMGn#Z zjetiaTB>J;I;s~cU>%PjxLUd={2e209khE4j41FXKcxkt&p(r!0<<^}O_-QSpkyk& z3LRtj>_=PK=b*PPXTSEf@tlW$E8)T#UBg ziP-YeA~E?*T4VuoJ?Y-9p>pLsdVn-oHe3txNZ*2OBd@}mEq}Tqg`Ut|J-Ui0rvC&H zoPi(~MW5=KcPt^xEDLR@WoxY;tEDHEY$z6U8iN8-DC5})#IX(Xq&AVJKeUQ9w6Jyr zRADSXkxSjy^>?Wzpvz`TfOjHjsc%?X`Sl3kx;H4u5c+eHC5Bd?Mugmy9iX5-ko;Mv z;E`#%$V5soT=Ug9=E0_#(;JvD_cgysIHHWPqXA3E-9sW#P=Lsu7m`v<8b?*V?ScK9QOj~{QSzj{|99&%b6oc-Fy;!B-&Hm+r-Pcf)pw_A%L65*kZrZr7Z z{+1`;)0q=yi%++I$csWm{lBkXLtA?^$ku(*&-)pg@BR8{;s4{uoG zM+rDTVsh0jCZj<_&K$H5Fm*#c#EKV{b38zd%aGA0c;Qd>Ni_6XU-GKwn!7C}qT8w_JnUhP;o?mREUca$7z|>R0=ZE0t=_DGn6R2@)XEY~HLO#HU`Q6H_VP=L1S_KbJ?rt%q7U*es3Uf3u0j_R(^Zb!|Gam}Xrc!AssLnc3 zmGJ}673hCx^y9X)i~Zfg&Vb0mH_Rr*DZxtLDlR?~OU*Rs9rU-+`T#P{pV&$9uTKrSR+pZeCS=)4`hZT!l7h6Sp;tAyx({oW7c=V z_4qJ@LIqwQdFPvWf$UEa$E-T!ein!n$?|$CWq~PI+EzaB7dw#eQIL;FyuO9SS_59h z;d#Pg8mPnu9h31Au|LL6Zkn>nZexH6?(G4l#!Z43z=E4>YfhTyr?fOCZ2C*L6;s&) ztpXborcB3xJ{jhFiBpO}t!(P4>R5xSESvPf12h#}$D}9;K4SFzI(9$IYvk$T`MN!V1F zs|?Rbv7pE|-;eucyfjePg44>)8U2`BJ1zcHMy(#GvpTabNi^VI;vh|IV#FN@b9~Le zn-`RWag(5=IVJP;2pUwQ-=}etSq@VZ&c6>%ae%;U^@m>)9SrPgs5M!CG?eZ(7-rNk zLSmDQL1VBCxdj^g;g_@&&zsO4Pr)PrIa#jEhV)-Yx@0x|4?ICtv-h1`-JfKz#E9o; zBol>AJ{fE6e|Y){7KQw6ZSeNsqvHg4LwqRk7yE=;`k^Ci(_oXQzY;I^D0r9hVZwWe zpxtuKUEpEU|&N-u!J4q zN!^0T+lIUh#)QKFsHidk2xNUil=Nsz^aJzFjZCkLJNx{3q+|Ha;;+8#u3I2_g zaJ=7UggBzZr>l83X|eO}a>J=anyL922+pPQRVaj11(MeqNi5f6Iq(1FzU6ZDO1+0A zfOB66r7A7{{8wW}I6o~m50A=P$8m41=}vG%NSP6ngIddyWyXybN~b7#nuC%RyTZl; zDO^!T*BMfq2222Gxu-7mYVXt;q_r-+)wISa?6<3EHLt)YSw`2&Z?XwG$_Z)sYWERy zYZ=q6A6r(;gjMUZ8oNa>si4Ws=@-`k84?OHd_GLA$%*Rf-XDG1Lg**g^HJ`lqJj5j z)5KIE%A`rGrOY!(R=aI7OT@TE1#~W>RIX=$N$5x!`(%~E8PKxP(BoM!eHS~mc6%}4 z53!+8)z_oB7Cg%M&o3zLu`eT|U&<$AX`a0%+`-mn${bcXO2}JMi;sc|_tnUV`0q5f z5g^AM7CCeD_$kVuL;Gd)aWV}$AGq(-ErPz<&ow5I|1O})x2;|2z*!U1I-v-m*U_Hns$;F)x5_s?Lb6OX>_HrpRAt+&v5y#xz&#s{g@U zXk|N^BIAh&=#5SK$q|>!p*RA$=yt!dqtHO>pgzwrv~BCBvT>=NhCGK5PVLnaP`_Xa zuaW_;xh$h&zo5x-@0)Qp>1DYfhfNr?c3oUzZck;{+C47lgMVgrtnE+u481+lM1+DT zc>h<2EcwTUo6XPj?XI1)`fW+yCbrtTy8N=Uqt-WFuyso+Cnt4h)3>FSbOSTSvB@&M zjCwQO&oz>$X~2sQG&PVd*ePI77l(kRiJg|oimKXR;>H2Mgu(Ik9thK`sy1gM{qu4z zJ}B)lV$gl+5L(U(pLhWGcvO@rbm^hKmo}KC4s<=lygCBUvRtylhauf#T$e4U``H+2 zPrKJm8%=Gn^}unboPOhH)?zH39IGU$n+OuWPq!mDc@4-(jAl=W%@AivZC+zvSD(bV zr?1Py__a)Wo6@MK=IvhF?2A79@g%5bc6C8#$n3#)`heu^e9lzd{^J>uRM_QErTImP zYE!{H&YNwN`9sUuNP7n~t4ikKlH^Vko6HHi+k9C3yl-Ry1trz{RcVO%_UvchWUbtDm4EH!PoT>yUJde{sB4MQ3Tpt4~D@_**On>iMiUS_8zLtevSI;Da9S7u;eqB%yqYdCsgeMz>vE<7NUJe6U z#%cN=%cBKBFZyJvglq?nhHdkuG=E0=M02GsxSj=UpWjev8AbtDanGAu@ zQP!(gyfC@;qJIZI0C_^_>&Zb~&?9~cZQH)xiwU;h4;t+dF?2qybyhQ=am zq@xDlPb3eM#*K78N<@mfDzy&&u>PtfU)z0UW#!j)fjw49 z0n=>Lv3QXsQ51UWKn90Ae?aDj>0^?cf?}Jj{uo>8Opj^@l(f0V{Qbr9>`lufe^Rbj z0Kjx?c|?lD{nR)+71BpG_wASgg~CEY@8XSLGAuCqt{4U!J>0x9%&6%a z=`M|drzJ*NrPoB9q`8|EJmO2FyL3{nS#f)#5%g^y@cBFt@s?WX|M!7Ze{6k-J z6nFLE4iwl|HDqayq@>{gp&$6P@U2Gc(c6%7uG96yjqf9etrVdbz`#s*(Z8MR2_L*Q z{;U_qen)socT-}<%L9|M_uXEI&fBv45%O5JwTIUt#w zE17Ozn%T)`-RY)FZbus*O)@3Zk7uo>{EKl-odu)2ulHuXFL_6IlNJ;Reg*;h7O5OO zoaN|@^#t)|1s7I#CZEhT41N3plgi3r!vuQyeOOMRv~uSaR2e^^aL?q0?^wTT4!e>W zgPo7C&Bey%GR(n}YNl4;EfF5hE$RC;J#p=~7%c|Z-1TRsS88FH;0n;xU4>!`Y4Cp5 zj##&EbopSPmpO81BvqI(`!1uD6kW4OZZ6>t@l)3f=C6kjqK4QRe*Y{?pO5+7w6HvN z>AFoN!}zEE&iU(h#;HCy(L=C4(~z0ZU`B~Hr|{_?%^Md5>L!iPr=}f43~D$XU?syfbD=Vx+U7z{ z9T$s;qTP1O^xmgBj2(5Wy!fddfDcgoQ$EpP80qZP&-BS$F?zw0j@A9HbtbqGAN-2i z=W4_sv~5fo_$vrM-hY6vufL>!Sw2`I`>dF2EM~t;Vj-3eT=>Wi@a5^SmOC@tnTcyS zJKe}`UBW8sL31-pOEl=NgOO#%QlmVEETJHLYb04>B5+VXIHh$t?N~;~5iTXDXCowv z7MNfmcs?C<4jDY^_2J(piSA$7*Y4(=+1<~gU8t4R^%II2`4jsBq#5Sb2$8EOOnhf#!`{dnpqy=|t zM|BZM&qjHl$As3w^vl@wzPf_IL^Sc-5;n>`^ukvAyuO<>^Mm8)ao4(xp`XzAM6N*j zK((}&4ZWFP#E%epu3?hL>GgUXv>SG4bM^SXj zjx3Ad;{13CMPT*p?YxWWk&D9M?W2*Q$l85^g#N|v2!!Yp4lAA;(Pb9VR&G-#9}xsV zW!!-6JbR?BydV4XP-wBoKx#_nOogrYN745UfqmLx8pcPn-H?`o!UksD(pag`ovd_* zGxBb}#CGjLRRix!NHDIPcWY!-!aBFK*tB{mqCso=wna1PGZHevA>Kj2B7NVQhFKdt z-Yp5e_VCsiOU&?w4&Nn#@wzLv#k*pW~K(y^I;r!6@BolR(BYa{d8^E&|_ zIdb68C@h3QhnB%MmO&KoA`BC`s!q2gzZ~Z!eYJz$vmQN*aCXEW8N!=3yH5u@{PCC# z74e#j^C5*mfCyLtpO=7730ihASq9JR2GuUY+}Zeu;b|5dSsH;N%mw?Cml*kfwQ-ND zSUAz7Xk5c<{rS0GSyCi;vyt(--3t5rv_A<-^yoj!VZuwo&W6=x=g-9Lu;zTtECN-e z3pue5GzJ#^R-p~pM!v6lF*@W{e)fVd(bbvi8zaK$O)a?Q%eCDDm%dbFgufmlb)+Id zB}=&f`9o`|^1|HTd+9NiYS6YCK?B7!IU7j*#rwJ!8}l|ofgao5bdGRiYbCo7yP3pI zpAp-1xlcn5X&3@wg6N)%O` zI|5ZlCs898RMYjN9xWF2WK1+ov)(ISt?bXwz~9_Ohx_t|B2M-3zf_dHc(y~TSnB_X zS|x^|_A!4gvsa~Rn&f+^$Dm;gAA#mo{~}Ty{wkiLT~O7Jj2=WW2`=uJ)2y5uCfK}Y? z(Cn_$;VT9O6`!X*3)1uYIhkwKa6hcm!1oAH$n4(2fN7;A#FPHhvj1_V;)S$*#pT1w z^cj8vA3xC{^_G%93>wL^CnN79$-eY|-f1+m_ZBd*QU3Vsc9db_ty;08Fusb`oPNFF zh1-zyp_tjvHv6Q?Z>MrLKbFw`dK;-}pegjMzk_I_bEipY@nhoqk@|j$G*xo4u)TAr z`JeZ*Rse6*$DLDRrF<{b$bKv0tyx=13^xI_^S7eM3N2CtPh5@adH*I>y>u#Zs_T%; zZuG!}*j5i%HL#f>b-RfzVAdj^##9_#eRNDs91^o7N%yr4MuVTa9nfDKz5k+4PXUI( z`8kL>8k>n&un}Io^PJ{awWWLtU%}bmw~Zw5U*rt^Wb|!{bWKdi+s{>WUt5YX%7}h% zD%M8O!Nwn++f3xcl(*d#Na_M*6+Z5SwKe9qPKsOyhZ30dWohvJO`kO19gAu=x2?4P z#o*_3F_%YFL#?s4M($3#4}THEtIHdg4uSP9v?I^LJ!l_fR=#%qn7Rr2W~@<;f9Js$ z@BEvQi;ld=(zb*4H6|ruIsw2h|7BBX!9XR!AaL9(O0oOvx5PdLZkAZCU{vsmTF!E| z!D;`>{fjNhsPB(f{r}|TJ4}I%?AYaJuxmMtukgcQzY zO}Iw~tY|%-50Gnt&BtiV{P?mthi9eC+X(&X!xLSqs!jd#3%o6>@CQYG2bP8}OJnD; zi|sdy6T_j~9TeMEP9?c)6Z@~DLutq#%bMo0xyiu&)*tWe!ITbK;~y~;Fc&&+w<8Wd z{}JO0@a@=?IUQNhpg}EKP7H;_weyvo?QE{m#HudU!n6;fjq_OaiuBUNs?ju1_Ymm`1SOg z``BZL8}xosi3(6%+!7J|`fZwv3FX;+Eyc1b!EvhOGK3(?*h4+)HM1bpWBH4ANYTHG z0AQG*8zUoCz4B0vfrKMGGHH{^3bW1AC_({R@>c@*k?s;$OWs^6fm|R|9p2IdN*@N~ zA0HUl#2Q(T&kPm*<}vr(XHF+(DCPnI{DO=M{&yl4U|(Jp0!{NH!U;I`M%z+a-Ci+KE{)gd2KbJ%qZ^9~spJbnlJsCgpNFZiy~ z!7zlBsKBfG5qIO9;#4~IJ5Qz+9{`56P~No+AwB@@ghUqAFC`0!>ioIB7P% zzif@;P0;LqtGXYlfYHFnZ~_kH>pfB`svwhX+mFAzx?35v?g9j=7vxSu9yPg=Bv+`p zgKwP*+wI8}F;-){)L2&asLzU6DNTsH32W&6e$ZiYj&a2E@7CsaHvWn<&o2Sv@c?Vn z<}uedG0<>jr-(ryV=PmuqtNK!anF)`M;fP+W!W;Yd^lL>`f`8@`O=3O`_. - -************ -PostfixAdmin -************ - -`Official repository `_. diff --git a/doc/conf.py b/doc/conf.py index 5272f3e50..455555e3c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -127,7 +127,7 @@ else: # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['.static'] +html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. diff --git a/doc/getting_started/configuration.rst b/doc/configuration.rst similarity index 100% rename from doc/getting_started/configuration.rst rename to doc/configuration.rst diff --git a/doc/contributing.rst b/doc/contributing.rst index f31145f8c..a527e687f 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -1,4 +1,30 @@ -Rules -================= +################# +How to contribute +################# -.. include:: ../CONTRIBUTING.rst +Contributions are always welcome but please try to follow those few rules: + +- Modoboa tries to respect the `PEP8 `_ + +- If you add some code, add some tests too. You can run the tests + suite locally by using `tox `_ + +There are also a few commands that can help you to contribute: + +Start a basic Modoboa instance with a few fixture:: + + $ tox -e serve + +You can log in with admin/password. + +Build the docs to see your changes:: + + $ tox -e doc + $ firefox .tox/doc/tmp/html/index.html + + +.. toctree:: + + contributing/getting_started + contributing/plugin_api + contributing/events diff --git a/doc/extending/events.rst b/doc/contributing/events.rst similarity index 100% rename from doc/extending/events.rst rename to doc/contributing/events.rst diff --git a/doc/extending/getting_started.rst b/doc/contributing/getting_started.rst similarity index 100% rename from doc/extending/getting_started.rst rename to doc/contributing/getting_started.rst diff --git a/doc/extending/plugin_api.rst b/doc/contributing/plugin_api.rst similarity index 100% rename from doc/extending/plugin_api.rst rename to doc/contributing/plugin_api.rst diff --git a/doc/getting_started/install.rst b/doc/getting_started/install.rst deleted file mode 100644 index 0446d7583..000000000 --- a/doc/getting_started/install.rst +++ /dev/null @@ -1,200 +0,0 @@ -.. _installation: - -############ -Installation -############ - -***************** -For the lazy ones -***************** - -If you are in a hurry, you will love the `modoboa installer -`_! It's a set of Python -scripts to install a fully functional email server on one machine -(modoboa, postfix, dovecot, amavis and more). - -To use it, just run the following commands in your terminal:: - - $ git clone https://github.com/modoboa/modoboa-installer - $ cd modoboa-installer - $ sudo ./run.py - -Wait a few minutes and you're done \o/ - -If you have more time or if you are just curious, you can install -Modoboa *the old way* by going to the next section. - -************ -Requirements -************ - -* `Python version 2.7+ `_ -* `Django version 1.7+ `_ -* `lxml python module `_ -* `pycrypto python module `_ -* `rrdtool python binding `_ -* `sievelib python module `_ -* `chardet python module `_ -* `argparse python module `_ -* `reversion python module `_ - -.. _get_modoboa: - -*********** -Get Modoboa -*********** - -You can choose between two options: - -* Use the Python package available on the `PyPI `_ -* Download the sources tarball - -The easiest one is to install it from PyPI. Just run the following -command and you're done:: - - $ pip install modoboa - -If you prefer to use the tarball, download the latest one and run the -following procedure:: - - $ tar xzf modoboa-.tar.gz - $ cd modoboa- - $ python setup.py install - -All dependencies will be installed regardless the way you chose. The -only exception concerns the RRDtool binding because there isn't any -python package available, it is directly provided with the official -tarball. - -Fortunately, all major distributions include a ready-to-use -package. On Debian/Ubuntu:: - - $ apt-get install libcairo2-dev libpango1.0-dev librrd-dev - $ apt-get install python-rrdtool - -`virtualenv `_ users -========================================================== - -When you deploy an application using virtualenv, you may have to -compile some dependencies. For example, modoboa relies on lxml, -which is a C python module. In order to install it, you will need to -install the following requirements: - -* python development files -* libxslt development files -* libxml2 development files -* libz development files - -On a Debian like system, just run the following command:: - - $ apt-get install python-dev libxml2-dev libxslt-dev zlib1g-dev - -.. _database: - -******** -Database -******** - -Thanks to Django, Modoboa supports several databases. Depending on -the one you will use, you must install the appropriate python package: - -* `mysqldb `_ for `MySQL `_ -* `psycopg2 `_ for `PostgreSQL `_ - -Then, create a user and a database that will be used by Modoboa. Make -sure your database is using UTF8 as a default charset. - -.. _deployment: - -********** -Deployment -********** - -`modoboa-admin.py`, a command line tool, lets you deploy a -*ready-to-use* Modoboa site using only one instruction:: - - $ modoboa-admin.py deploy modoboa_example --collectstatic [--dburl default:database-url] [--extensions extensions] - -.. note:: - - By default, the core application of Modoboa and some necessary plugins - (admin, relaydomains and limits) are installed. To install extensions, - use the ``--extensions`` option which accepts a list of extension names - as argument (``--extensions ext1 ext2 ...``). - If you want to install all extensions, just use the ``all`` - shortcut like this ``--extensions all``. - - If you choose to install extensions one at a time, you will have to - add their names in settings.py to ``MODOBOA_APPS``. Also ensure that - you have the line ``from modoboa_amavis.settings import *`` at the - end of this file. - - The list of available plugins can be found on the :doc:`index page - <../index>`. Instructions to install them are available on each plugin page. - -.. note:: - - You can specify more than one database connection using the - ``--dburl`` option. Multiple connections are differentiated by a - prefix. The primary connection must use the ``default:`` prefix (as - shown in the example above). For the `amavis extension - `_ extension, use the - ``amavis:`` prefix. An example two connections: ``--dburl - default: amavis:``. - - Your database url should meet the following syntax - ``scheme://[user:pass@][host:port]/dbname`` **OR** - ``sqlite:////full/path/to/your/database/file.sqlite``. - - Available schemes are: - - * postgres - * postgresql - * postgis - * mysql - * mysql2 - * sqlite - -The command will ask you a few questions, answer them and you're -done. You can now go to the :ref:`first_use` section. - -In case you need a **silent installation** (e.g. if you're using -Salt-Stack, Ansible or whatever), it's possible to supply the database -credentials as commandline arguments. - -You can see the complete option list by running the following command:: - - $ modoboa-admin.py help deploy - -.. note:: - - If you plan to serve Modoboa using a URL prefix, you must change the - value of the ``LOGIN_URL`` parameter to ``LOGIN_URL = '//accounts/login/'``. - -.. _first_use: - -********* -First use -********* - -Your installation should now have a default super administrator: - -* Username: ``admin`` -* Password: ``password`` - -It is **strongly** recommended to change this password the first time -you log into Modoboa. - -To check if your installation works, just launch the embedded HTTP -server:: - - $ python manage.py runserver - -You should be able to access Modoboa at http://localhost:8000/. - -For a fully working interface using the embedded HTTP server, you need -to set the ``DEBUG`` parameter in settings.py to ``True``. - -For a production environment, we recommend using a stable webserver -like :ref:`apache2` or :ref:`nginx-label`. Don't forget to set -``DEBUG`` back to ``False``. diff --git a/doc/getting_started/upgrade.rst b/doc/getting_started/upgrade.rst deleted file mode 100644 index 60afc1ad9..000000000 --- a/doc/getting_started/upgrade.rst +++ /dev/null @@ -1,301 +0,0 @@ -################################## -Upgrading an existing installation -################################## - -This section contains all the upgrade procedures required to use -newest versions of Modoboa. - -.. note:: - Before running a migration, we recommend that you make - a copy of your existing database. - -.. _latestversion: - -************** -Latest version -************** - -Fetch the latest version (see :ref:`get_modoboa`) and install -it. ``pip`` users, just run the following command:: - - $ pip install modoboa== - -Replace ```` by the appropriate value. - -As for a fresh installation, ``modoboa-admin.py`` can be used to -upgrade your local configuration. To do so, remove the directory where -your instance was first deployed:: - - $ rm -rf - -.. warning:: - - If you customized your configuration file (:file:`settings.py`) with - non-standard settings, you'll have to re-apply them. - -Finally, run the ``deploy`` comamand. Make sure to consult the -:ref:`deployment` section to know more about the available options. - -If you prefer the manual way, check if -:ref:`specific_upgrade_instructions` are required according to the -version you're installing. - -To finish, restart the web server process according to the environment -you did choose. See :ref:`webservers` for more details. - -1.1.7: manual learning for SpamAssassin -======================================= - -A new feature allows administrators and users to manually train -SpamAssassin in order to customize its behaviour. - -Check :ref:`amavis:sa_manual_learning` to know more about this feature. - -1.1.6: Few bugfixes -=================== - -Catchall aliases were not really functional until this version as they -were eating all domain traffic. - -To fix them, a postfix map file (``sql-mailboxes-self-aliases.cf``) -has been re-introduced and must be listed into the -``virtual_alias_maps`` setting. See :ref:`postfix_config` for the -order. - -1.1.2: Audit trail issues -========================= - -Update the :file:`settings.py` file as follows: - -#. Remove the ``'reversion.middleware.RevisionMiddleware'`` - middleware from the ``MIDDLEWARE_CLASSES`` variable - -#. Add the new ``'modoboa.lib.middleware.RequestCatcherMiddleware'`` - middleware at the end of the ``MIDDLEWARE_CLASSES`` variable - -1.1.1: Few bugfixes -=================== - -For those who installed Dovecot in a non-standard location, it is now -possible to tell Modoboa where to find it. Just define a variable -named ``DOVECOT_LOOKUP_PATH`` in the :file:`settings.py` file and -include the appropriate lookup path inside:: - - DOVECOT_LOOKUP_PATH = ("/usr/sbin/dovecot", "/usr/local/sbin/dovecot") - -.. _1.1.0: - -1.1.0: relay domains and better passwords encryption -==================================================== - -Due to code refactoring, some modifications need to be done into -:file:`settings.py`: - -#. ``MODOBOA_APPS`` must contain the following applications:: - - MODOBOA_APPS = ( - 'modoboa', - 'modoboa.core', - 'modoboa.lib', - - 'modoboa.extensions.admin', - 'modoboa.extensions.limits', - 'modoboa.extensions.postfix_autoreply', - 'modoboa.extensions.webmail', - 'modoboa.extensions.stats', - 'modoboa.extensions.amavis', - 'modoboa.extensions.sievefilters', - ) - -#. Add ``'modoboa.extensions.postfix_relay_domains'`` to - ``MODOBOA_APPS``, just before - ``'modoboa.extensions.limits'`` - -#. ``AUTH_USER_MODEL`` must be set to ``core.User`` - -#. Into ``LOGGING``, replace ``modoboa.lib.logutils.SQLHandler`` by - ``modoboa.core.loggers.SQLHandler`` - -Then, run the following commands to migrate your installation:: - - $ python manage.py syncdb - $ python manage.py migrate core 0001 --fake - $ python manage.py migrate - $ python manage.py collectstatic - -Finally, update both :ref:`Dovecot ` and -:ref:`Postfix ` queries. - -1.0.1: operations on mailboxes -============================== - -The way Modoboa handles **rename** and **delete** operations on -mailboxes has been improved. Make sure to consult :ref:`fs_operations` -and :ref:`Postfix configuration `. Look at the -``smtpd_recipient_restrictions`` setting. - -Run ``modoboa-admin.py postfix_maps --dbtype -`` and compare the files with those that postfix currently -use. Make necessary updates in light of the differences - -1.0.0: production ready, at last -================================ - -Configuration file update -------------------------- - -Several modifications need to be done into :file:`settings.py`. - -#. Add the following import statement:: - - from logging.handlers import SysLogHandler - -#. Set the ``ALLOWER_HOSTS`` variable:: - - ALLOWED_HOSTS = [ - '', - ] - -#. Activate the ``django.middleware.csrf.CsrfViewMiddleware`` - middleware and add the ``reversion.middleware.RevisionMiddleware`` - middleware to ``MIDDLEWARE_CLASSES`` like this:: - - MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.locale.LocaleMiddleware', - # Uncomment the next line for simple clickjacking protection: - # 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'reversion.middleware.RevisionMiddleware', - - 'modoboa.lib.middleware.AjaxLoginRedirect', - 'modoboa.lib.middleware.CommonExceptionCatcher', - 'modoboa.lib.middleware.ExtControlMiddleware', - ) - -#. Add the ``reversion`` application to ``INSTALLED_APPS`` - -#. Remove all modoboa's application from ``INSTALLED_APPS`` and put - them into the new ``MODOBOA_APPS`` variable like this:: - - INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'south', - 'reversion', - ) - - # A dedicated place to register Modoboa applications - # Do not delete it. - # Do not change the order. - MODOBOA_APPS = ( - 'modoboa', - 'modoboa.auth', - 'modoboa.admin', - 'modoboa.lib', - 'modoboa.userprefs', - - 'modoboa.extensions.limits', - 'modoboa.extensions.postfix_autoreply', - 'modoboa.extensions.webmail', - 'modoboa.extensions.stats', - 'modoboa.extensions.amavis', - 'modoboa.extensions.sievefilters', - ) - - INSTALLED_APPS += MODOBOA_APPS - -#. Set the ``AUTH_USER_MODEL`` variable like this:: - - AUTH_USER_MODEL = 'admin.User' - -#. Modify the logging configuration as follows:: - - LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'filters': { - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse' - } - }, - 'formatters': { - 'syslog': { - 'format': '%(name)s: %(levelname)s %(message)s' - }, - }, - 'handlers': { - 'mail_admins': { - 'level': 'ERROR', - 'filters': ['require_debug_false'], - 'class': 'django.utils.log.AdminEmailHandler' - }, - 'console': { - # logging handler that outputs log messages to terminal - 'class': 'logging.StreamHandler', - #'level': 'DEBUG', # message level to be written to console - }, - 'syslog-auth': { - 'class': 'logging.handlers.SysLogHandler', - 'facility': SysLogHandler.LOG_AUTH, - 'formatter': 'syslog' - }, - 'modoboa': { - 'class': 'modoboa.lib.logutils.SQLHandler', - } - }, - 'loggers': { - 'django.request': { - 'handlers': ['mail_admins'], - 'level': 'ERROR', - 'propagate': True, - }, - 'modoboa.auth': { - 'handlers': ['syslog-auth', 'modoboa'], - 'level': 'INFO', - 'propagate': False - }, - 'modoboa.admin': { - 'handlers': ['modoboa'], - 'level': 'INFO', - 'propagate': False - } - } - } - -Postfix and Dovecot configuration update ----------------------------------------- - -It is necessary to update the queries used to retrieve users and mailboxes: - -#. Run ``modoboa-admin.py postfix_maps --dbtype `` and compare the files with those that postfix currently - use. Make necessary updates in light of the differences - -#. Into :file:`dovecot-sql.conf`, update the ``user_query`` query, refer to - :ref:`dovecot_mysql_queries` or :ref:`dovecot_pg_queries` - -#. Update dovecot's configuration to activate the new :ref:`quota related features ` - -Migration issues ----------------- - -When running the ``python manage.py syncdb --migrate`` command, you -may encounter the following issues: - -#. Remove useless content types - - If the script asks you this question, just reply **no**. - -#. South fails to migrate ``reversion`` - - Due to the admin user model change, the script :file:`0001_initial.py` - may fail. Just deactivate ``reversion`` from ``INSTALLED_APPS`` and - run the command again. Once done, reactivate ``reversion`` and run - the command one last time. diff --git a/doc/index.rst b/doc/index.rst index 0de085cd4..baf128dbd 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -3,70 +3,73 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Modoboa's documentation! -======================== +Modoboa documentation +===================== -*************** -Getting started -*************** +.. image:: _static/modoboa_logo.png + :align: center + +Overview +-------- + +Modoboa is a mail hosting and management platform including a modern +and simplified Web User Interface designed to work with `Postfix +`_ and `Dovecot `_. + +It is extensible by nature and comes with a lot of additional extensions: + ++------------------------------------------------+-------------------------+------------------------------------------------------+ +|Name |Description |Documentation | +| | | | +| | | | +| | | | ++================================================+=========================+======================================================+ +|`modoboa-amavis |A frontend for `Amavis |https://modoboa-amavis.readthedocs.io | +|`_ |`_| | +| | | | +| | | | ++------------------------------------------------+-------------------------+------------------------------------------------------+ +|`modoboa-dmarc |A set of tools to use |https://github.com/modoboa-dmarc | +|`_ |`DMARC | | +| |`_ | | ++------------------------------------------------+-------------------------+------------------------------------------------------+ +|`modoboa-imap-migration |Migrate mailboxes from an|https://github.com/modoboa-imap-migration | +|`_ |existing server using | | +| |IMAP (and offlineimap) | | ++------------------------------------------------+-------------------------+------------------------------------------------------+ +|`modoboa-pdfcredentials |Generate PDF documents |https://github.com/modoboa-pdfcredentials | +|`_ |containing account | | +| |credentials | | ++------------------------------------------------+-------------------------+------------------------------------------------------+ +|`modoboa-pfxadmin-migrate |A tool to migrate from |https://github.com/modoboa/modoboa-pfxadmin-migrate | +|`_ |Postfixadmin | | ++------------------------------------------------+-------------------------+------------------------------------------------------+ +|`modoboa-postfix-autoreply |Away message editor |https://modoboa-postfix-autoreply.readthedocs.io | +|`_|(postfix compatible) | | ++------------------------------------------------+-------------------------+------------------------------------------------------+ +|`modoboa-radicale |A frontend for `Radicale |https://modoboa-radicale.readthedocs.io | +|`_ |`_ | | ++------------------------------------------------+-------------------------+------------------------------------------------------+ +|`modoboa-sievefilters |A Sieve filters (rules) |https://modoboa-sievefilters.readthedocs.io | +|`_ |editor | | ++------------------------------------------------+-------------------------+------------------------------------------------------+ +|`modoboa-stats |Graphical statistics |https://modoboa-stats.readthedocs.io | +|`_ |(message traffic and | | +| |more) | | ++------------------------------------------------+-------------------------+------------------------------------------------------+ +|`modoboa-webmail |A simple webmail |https://modoboa-webmail.readthedocs.io | +|`_ | | | ++------------------------------------------------+-------------------------+------------------------------------------------------+ + +Table of contents +----------------- .. toctree:: - :maxdepth: 2 + :maxdepth: 1 installation upgrade - getting_started/configuration - -******* -Plugins -******* - -.. toctree:: - :maxdepth: 2 - - plugins/amavis - plugins/statistics - plugins/radicale - plugins/postfix_autoreply - plugins/sievefilters - plugins/webmail - -******************************** -Integration with other softwares -******************************** - -.. toctree:: - :maxdepth: 2 - - integration/imap_and_smtp - integration/web_servers - -***************** -Extending Modoboa -***************** - -.. toctree:: - :maxdepth: 2 - - extending/getting_started - extending/plugin_api - extending/events - -******************* -Additional resource -******************* - -.. toctree:: - :maxdepth: 2 - - additional/migrating - -******************* -Contributing -******************* - -.. toctree:: - :maxdepth: 2 - + configuration + rest_api contributing contributors diff --git a/doc/installation.rst b/doc/installation.rst index 9aecdc052..4c2d26836 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -2,13 +2,13 @@ Installation ############ -Using the installer -=================== +Recommanded way +=============== If you start from scratch and want to deploy a complete mail server, you will love the `modoboa installer `_! It is the easiest -and the quickest way to setup a fully functional server (modooba, +and the quickest way to setup a fully functional server (modoboa, postfix, dovecot, amavis and more) on one machine. .. warning:: @@ -16,7 +16,7 @@ postfix, dovecot, amavis and more) on one machine. For now, only Debian and CentOS based Linux distributions are supported. We do our best to improve compatibility but if you use another Linux or a UNIX system, you will have to install Modoboa - :ref:`by_hand`. + :ref:`manually `. To use it, just run the following commands in your terminal: @@ -30,434 +30,40 @@ Wait a few minutes and you're done \o/ .. _by_hand: -By hand -======= +Manual installation +=================== -In case you already have a running server (postfix, dovecot, etc.) or -you want to build a multi-machine architecture, you can install -Modoboa manually. +For those who need a manual installation or who just want to setup a +specific part, here are the steps you must follow: -Prepare the system ------------------- +.. toctree:: + :maxdepth: 1 -First of all, we recommand the following context: + manual_installation/modoboa + manual_installation/webserver + manual_installation/dovecot + manual_installation/postfix -* Use a dedicated system user -* Use a `virtualenv `_ to - install the application because it will isolate it (and its - dependencies) from the rest of your system - -The following example illustrates how to realize this (Debian like system): - -.. sourcecode:: bash - - > sudo apt-get install python-virtualenv python-pip - > sudo useradd modoboa - > sudo -i modoboa - > virtualenv env - (env)> source env/bin/activate - (env)> pip install -U pip - -FIXME: dépendances système pour compilation - -Then, install Modoboa: - -.. sourcecode:: bash - - (env)> pip install modoboa - -Database --------- - -.. warning:: - - This documentation does not cover the installation of a database - server but only the setup of a functional database that Modoboa - will use. - -Thanks to Django, Modoboa is compatible with the following databases: - -* PostgreSQL -* MySQL / MariaDB -* SQLite - -Since the last one does not require particular actions, only the first -two ones are described. - -PostgreSQL -********** - -Install the corresponding Python binding: - -.. sourcecode:: bash - - (env)> pip install psycopg2 - -Then, create a user and a database: - -.. sourcecode:: bash - - > sudo -i postgres - > - -MySQL / MariaDB -*************** - -Install the corresponding Python binding: - -.. sourcecode:: bash - - (env)> pip install MySQL-Python - -Then, create a user and a database: - -.. sourcecode:: bash - - > mysqladmin -u root -p create modoboa - -Deploy an instance ------------------- - -``modoboa-admin.py``, a command line tool, lets you deploy a -*ready-to-use* Modoboa site using only one instruction:: - - (env)> modoboa-admin.py deploy instance --collectstatic \ - --domain --dburl default:database-url - -.. note:: - - You can install additional extensions during the deploy process. To - do so, use the ``--extensions`` option which accepts a list of - names as argument (``--extensions ext1 ext2 ...``). If you want to - install all extensions, just use the ``all`` keyword like this - ``--extensions all``. - - If you choose to install extensions one at a time, you will have to - add their names in settings.py to ``MODOBOA_APPS``. Also ensure that - you have the line ``from modoboa_amavis.settings import *`` at the - end of this file. - - The list of available extensions can be found on the :doc:`index - page <../index>`. Instructions to install them are available on - each extensions page. - -.. note:: - - You can specify more than one database connection using the - ``--dburl`` option. Multiple connections are differentiated by a - prefix. - - The primary connection must use the ``default:`` prefix (as shown - in the example above). For the `amavis - `_ extension, use the - ``amavis:`` prefix. For example: ``--dburl - default: amavis:``. - - A database url should meet the following syntax - ``://[user:pass@][host:port]/dbname`` **OR** - ``sqlite:////full/path/to/your/database/file.sqlite``. - -The command will ask you a few questions, answer them and you're -done. You can now go to the :ref:`first_use` section. - -In case you need a **silent installation** (e.g. if you're using -Salt-Stack, Ansible or whatever), it's possible to supply the database -credentials as commandline arguments. - -You can consult the complete option list by running the following -command:: - - $ modoboa-admin.py help deploy - -.. _webservers: - -Web server +Extensions ---------- -.. note:: +Only few commands are needed to add a new extension to your setup. - The following instructions are meant to help you get your site up - and running quickly. However it is not possible for the people - contributing documentation to Modoboa to test every single - combination of web server, wsgi server, distribution, etc. So it is - possible that **your** installation of uwsgi or nginx or Apache or - what-have-you works differently. Keep this in mind. +In case you use a dedicated user and/or a virtualenv, do not forget to +use them: -.. _apache2: +.. sourcecode:: bash -Apache2 -******* + > sudo -i + > source /bin/activate -First, make sure that ``mod_wsgi`` is installed on your server. +Then, run the following commands: -Create a new virtualhost in your Apache configuration and put the -following content inside:: +.. sourcecode:: bash - - ServerName - DocumentRoot + > pip install == + > cd + > python manage.py migrate + > python manage.py collectstatic - Alias /media/ /media/ - /media> - Order deny,allow - Allow from all - - - Alias /sitestatic/ /sitestatic/ - /sitestatic> - Order deny,allow - Allow from all - - - WSGIScriptAlias / //wsgi.py - - - -This is just one possible configuration. - -To use mod_wsgi daemon mode, add the two following directives just -under ``WSGIScriptAlias``:: - - WSGIDaemonProcess example.com python-path=:/lib/python2.7/site-packages - WSGIProcessGroup example.com - -Replace values between ``<>`` with yours. If you don't use a -`virtualenv `_, just -remove the last part of the ``WSGIDaemonProcess`` directive. - -.. note:: - - You will certainly need more configuration in order to launch - Apache. - -.. _nginx-label: - -Nginx -***** - -This section covers two different ways of running Modoboa behind -`Nginx `_ using a WSGI application server. Choose -the one you prefer between `Green Unicorn `_ or -`uWSGI `_. - -In both cases, you'll need to download and `install nginx -`_. - -Green Unicorn -============= - -Firstly, `Download and install gunicorn -`_. Then, use the following sample -gunicorn configuration (create a new file named -:file:`gunicorn.conf.py` inside Modoboa's root dir):: - - backlog = 2048 - bind = "unix:/var/run/gunicorn/modoboa.sock" - pidfile = "/var/run/gunicorn/modoboa.pid" - daemon = True - debug = False - workers = 2 - logfile = "/var/log/gunicorn/modoboa.log" - loglevel = "info" - -To start gunicorn, execute the following commands:: - - $ cd - $ gunicorn -c gunicorn.conf.py .wsgi:application - -Now the nginx part. Just create a new virtual host and use the -following configuration:: - - upstream modoboa { - server unix:/var/run/gunicorn/modoboa.sock fail_timeout=0; - } - - server { - listen 443 ssl; - ssl on; - keepalive_timeout 70; - - server_name ; - root ; - - access_log /var/log/nginx/.access.log; - error_log /var/log/nginx/.error.log; - - ssl_certificate ; - ssl_certificate_key ; - - location /sitestatic/ { - autoindex on; - } - - location /media/ { - autoindex on; - } - - location / { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_redirect off; - proxy_set_header X-Forwarded-Protocol ssl; - proxy_pass http://modoboa; - } - } - -If you do not plan to use SSL then change the listen directive to -``listen 80;`` and delete each of the following directives:: - - ssl on; - keepalive_timeout 70; - ssl_certificate ; - ssl_certificate_key ; - proxy_set_header X-Forwarded-Protocol ssl; - -If you do plan to use SSL, you'll have to generate a certificate and a -key. `This article -`__ -contains information about how to do it. - -Paste this content to your configuration (replace values between -``<>`` with yours) and restart nginx. - -uWSGI -===== - -The following setup is meant to get you started quickly. You should -read the documentation of both nginx and uwsgi to understand how to -optimize their configuration for your site. - -The Django documentation includes the following warning regarding -uwsgi: - -.. warning:: - - Some distributions, including Debian and Ubuntu, ship an outdated - version of uWSGI that does not conform to the WSGI - specification. Versions prior to 1.2.6 do not call close on the - response object after handling a request. In those cases the - request_finished signal isn’t sent. This can result in idle - connections to database and memcache servers. - -Use uwsgi 1.2.6 or newer. If you do not, you *will* run into -problems. Modoboa will fail in obscure ways. - -To use this setup, first `download and install uwsgi -`_. - -Here is a sample nginx configuration:: - - server { - listen 443 ssl; - ssl on; - keepalive_timeout 70; - - server_name ; - root ; - - ssl_certificate ; - ssl_certificate_key ; - - access_log /var/log/nginx/.access.log; - error_log /var/log/nginx/.error.log; - - location /sitestatic/ { - autoindex on; - alias ; - } - - # Whether or not Modoboa uses a media directory depends on how - # you configured Modoboa. It does not hurt to have this. - location /media/ { - autoindex on; - alias ; - } - - # This denies access to any file that begins with - # ".ht". Apache's .htaccess and .htpasswd are such files. A - # Modoboa installed from scratch would not contain any such - # files, but you never know what the future holds. - location ~ /\.ht { - deny all; - } - - location / { - include uwsgi_params; - uwsgi_pass ; - uwsgi_param UWSGI_SCRIPT .wsgi:application; - uwsgi_param UWSGI_SCHEME https; - } - } - -```` must be replaced by the value you used -when :ref:`you deployed your instance `. - -If you do not plan to use SSL then change the listen directive to -``listen 80;`` and delete each of the following directives:: - - ssl on; - keepalive_timeout 70; - ssl_certificate ; - ssl_certificate_key ; - uwsgi_param UWSGI_SCHEME https; - -If you do plan to use SSL, you'll have to generate a certificate and a -key. `This article -`_ -contains information about how to do it. - -Make sure to replace the ``<...>`` in the sample configuration with -appropriate values. Here are some explanations for the cases that may -not be completely self-explanatory: - -```` - Where Modoboa's :file:`settings.py` resides. This is also where the - :file:`sitestatic` and :file:`media` directories reside. - -```` - This is the URL which will be the root of your Modoboa site at your - domain. For instance, if your Modoboa installation is reachable at - at ``https://foo/modoboa`` then ```` is - ``/modoboa``. In this case you probably also have to set the - ``alias`` directives to point to where Modoboa's sitestatic and - media directories are because otherwise nginx won't be able to find - them. - - If Modoboa is at the root of your domain, then ```` is an empty string and can be deleted from the configuration - above. In this case, you probably do not need the ``alias`` - directives. - -```` - The location where uwsig is listening. It could be a unix domain - socket or an address:port combination. Ubuntu configures uwsgi so - that the port is:: - - unix:/run/uwsgi/app//socket - - where ```` is the name of the application. - -Your uwsgi configuration should be:: - - [uwsgi] - # Not needed when using uwsgi from pip - # plugins = python - chdir = - module = .wsgi:application - master = true - harakiri = 60 - processes = 4 - vhost = true - no-default-app = true - -The plugins directive should be turned on if you use a uwsgi -installation that requires it. If uwsgi was installed from pip, it -does not require it. In the configuration above: - -```` - The directory where :file:`manage.py` resides. This directory is the - parent of ```` - -```` - The name that you passed to ``modoboa-admin.py deploy`` when you - created your Modoboa instance. +Then, restart your web sever. diff --git a/doc/integration/imap_and_smtp.rst b/doc/manual_installation/dovecot.rst similarity index 83% rename from doc/integration/imap_and_smtp.rst rename to doc/manual_installation/dovecot.rst index 7c8d1163d..60fdaa319 100644 --- a/doc/integration/imap_and_smtp.rst +++ b/doc/manual_installation/dovecot.rst @@ -1,15 +1,11 @@ -################### -Dovecot and Postfix -################### - .. _dovecot: -******* +####### Dovecot -******* +####### -Modoboa works better with Dovecot 2.0 so the following documentation -is suitable for this combination. +Modoboa requires Dovecot 2+ to work so the following documentation is +suitable for this combination. In this section, we assume dovecot's configuration resides in :file:`/etc/dovecot`, all pathes will be relative to this directory. @@ -403,70 +399,4 @@ Finally, configure the ``sieve`` plugin by editing the Restart Dovecot. -.. _postfix: - -******* -Postfix -******* - -This section gives an example about building a simple virtual hosting -configuration with *Postfix*. Refer to the `official documentation -`_ for more explanation. - -Map files -========= - -You first need to create configuration files (or map files) that will -be used by Postfix to lookup into Modoboa tables. - -To automaticaly generate the requested map files and store them in a -directory, run the following command:: - - $ modoboa-admin.py postfix_maps --dbtype - -```` is the directory where the files will be -stored. Answer the few questions and you're done. - -.. _postfix_config: - -Configuration -============= - -Use the following configuration in the :file:`/etc/postfix/main.cf` file -(this is just one possible configuration):: - - # Stuff before - virtual_transport = lmtp:unix:private/dovecot-lmtp - - relay_domains = - virtual_mailbox_domains = :/etc/postfix/sql-domains.cf - virtual_alias_domains = :/etc/postfix/sql-domain-aliases.cf - virtual_alias_maps = :/etc/postfix/sql-aliases.cf - - relay_domains = :/etc/postfix/sql-relaydomains.cf - transport_maps = - :/etc/postfix/sql-spliteddomains-transport.cf - :/etc/postfix/sql-relaydomains-transport.cf - - smtpd_recipient_restrictions = - # ... - check_recipient_access - :/etc/postfix/sql-maintain.cf - :/etc/postfix/sql-relay-recipient-verification.cf - permit_mynetworks - reject_unauth_destination - reject_unverified_recipient - # ... - - smtpd_sender_login_maps = - :/etc/postfix/sql-sender-login-mailboxes.cf - :/etc/postfix/sql-sender-login-aliases.cf - - smtpd_sender_restrictions = - reject_sender_login_mismatch - - # Stuff after - -Replace ```` by the name of the database you use. - -Restart Postfix. +Now, you can go to the :ref:`postfix` section to finish the installation. diff --git a/doc/manual_installation/modoboa.rst b/doc/manual_installation/modoboa.rst new file mode 100644 index 000000000..119a71303 --- /dev/null +++ b/doc/manual_installation/modoboa.rst @@ -0,0 +1,140 @@ +####### +Modoboa +####### + +This section describes the installation of the web interface (a +`Django `_ project). + +Prepare the system +------------------ + +First of all, we recommand the following context: + +* Use a dedicated system user +* Use a `virtualenv `_ to + install the application because it will isolate it (and its + dependencies) from the rest of your system + +The following example illustrates how to realize this (Debian like system): + +.. sourcecode:: bash + + > sudo apt-get install python-virtualenv python-pip + > sudo useradd modoboa + > sudo -i modoboa + > virtualenv env + (env)> source env/bin/activate + (env)> pip install -U pip + +FIXME: dépendances système pour compilation + +Then, install Modoboa: + +.. sourcecode:: bash + + (env)> pip install modoboa + +Database +-------- + +.. warning:: + + This documentation does not cover the installation of a database + server but only the setup of a functional database that Modoboa + will use. + +Thanks to Django, Modoboa is compatible with the following databases: + +* PostgreSQL +* MySQL / MariaDB +* SQLite + +Since the last one does not require particular actions, only the first +two ones are described. + +PostgreSQL +********** + +Install the corresponding Python binding: + +.. sourcecode:: bash + + (env)> pip install psycopg2 + +Then, create a user and a database: + +.. sourcecode:: bash + + > sudo -i postgres + > + +MySQL / MariaDB +*************** + +Install the corresponding Python binding: + +.. sourcecode:: bash + + (env)> pip install MySQL-Python + +Then, create a user and a database: + +.. sourcecode:: bash + + > mysqladmin -u root -p create modoboa + +Deploy an instance +------------------ + +``modoboa-admin.py``, a command line tool, lets you deploy a +*ready-to-use* Modoboa site using only one instruction:: + + (env)> modoboa-admin.py deploy instance --collectstatic \ + --domain --dburl default:database-url + +.. note:: + + You can install additional extensions during the deploy process. To + do so, use the ``--extensions`` option which accepts a list of + names as argument (``--extensions ext1 ext2 ...``). If you want to + install all extensions, just use the ``all`` keyword like this + ``--extensions all``. + + If you choose to install extensions one at a time, you will have to + add their names in settings.py to ``MODOBOA_APPS``. Also ensure that + you have the line ``from modoboa_amavis.settings import *`` at the + end of this file. + + The list of available extensions can be found on the :doc:`index + page <../index>`. Instructions to install them are available on + each extensions page. + +.. note:: + + You can specify more than one database connection using the + ``--dburl`` option. Multiple connections are differentiated by a + prefix. + + The primary connection must use the ``default:`` prefix (as shown + in the example above). For the `amavis + `_ extension, use the + ``amavis:`` prefix. For example: ``--dburl + default: amavis:``. + + A database url should meet the following syntax + ``://[user:pass@][host:port]/dbname`` **OR** + ``sqlite:////full/path/to/your/database/file.sqlite``. + +The command will ask you a few questions, answer them and you're +done. + +If you need a **silent installation** (e.g. if you're using +Salt-Stack, Ansible or whatever), it's possible to supply the database +credentials as commandline arguments. + +You can consult the complete option list by running the following +command:: + + $ modoboa-admin.py help deploy + +Now you can continue to the :ref:`webserver` section. diff --git a/doc/manual_installation/postfix.rst b/doc/manual_installation/postfix.rst new file mode 100644 index 000000000..d584cbfdb --- /dev/null +++ b/doc/manual_installation/postfix.rst @@ -0,0 +1,67 @@ +.. _postfix: + +####### +Postfix +####### + +This section gives an example about building a simple virtual hosting +configuration with *Postfix*. Refer to the `official documentation +`_ for more explanation. + +Map files +========= + +You first need to create configuration files (or map files) that will +be used by Postfix to lookup into Modoboa tables. + +To automaticaly generate the requested map files and store them in a +directory, run the following command:: + + $ modoboa-admin.py postfix_maps --dbtype + +```` is the directory where the files will be +stored. Answer the few questions and you're done. + +.. _postfix_config: + +Configuration +============= + +Use the following configuration in the :file:`/etc/postfix/main.cf` file +(this is just one possible configuration):: + + # Stuff before + virtual_transport = lmtp:unix:private/dovecot-lmtp + + relay_domains = + virtual_mailbox_domains = :/etc/postfix/sql-domains.cf + virtual_alias_domains = :/etc/postfix/sql-domain-aliases.cf + virtual_alias_maps = :/etc/postfix/sql-aliases.cf + + relay_domains = :/etc/postfix/sql-relaydomains.cf + transport_maps = + :/etc/postfix/sql-spliteddomains-transport.cf + :/etc/postfix/sql-relaydomains-transport.cf + + smtpd_recipient_restrictions = + # ... + check_recipient_access + :/etc/postfix/sql-maintain.cf + :/etc/postfix/sql-relay-recipient-verification.cf + permit_mynetworks + reject_unauth_destination + reject_unverified_recipient + # ... + + smtpd_sender_login_maps = + :/etc/postfix/sql-sender-login-mailboxes.cf + :/etc/postfix/sql-sender-login-aliases.cf + + smtpd_sender_restrictions = + reject_sender_login_mismatch + + # Stuff after + +Replace ```` by the name of the database you use. + +Restart Postfix. diff --git a/doc/integration/web_servers.rst b/doc/manual_installation/webserver.rst similarity index 88% rename from doc/integration/web_servers.rst rename to doc/manual_installation/webserver.rst index 851738c5d..e4f5164d0 100644 --- a/doc/integration/web_servers.rst +++ b/doc/manual_installation/webserver.rst @@ -1,14 +1,8 @@ -.. _webservers: +.. _webserver: -########### -Web servers -########### - -.. _apache2: - -******* -Apache2 -******* +########## +Web server +########## .. note:: @@ -19,31 +13,34 @@ Apache2 possible that **your** installation of uwsgi or nginx or Apache or what-have-you works differently. Keep this in mind. -mod_wsgi -======== +.. _apache2: -First, make sure that mod_wsgi is installed on your server. +Apache2 +******* + +First, make sure that ``mod_wsgi`` is installed on your server. Create a new virtualhost in your Apache configuration and put the following content inside:: ServerName - DocumentRoot + DocumentRoot - Alias /media/ /media/ - /media> + Alias /media/ /media/ + /media> Order deny,allow Allow from all - Alias /sitestatic/ /sitestatic/ - /sitestatic> + Alias /sitestatic/ /sitestatic/ + /sitestatic> Order deny,allow Allow from all - WSGIScriptAlias / /wsgi.py + WSGIScriptAlias / //wsgi.py + This is just one possible configuration. @@ -51,7 +48,7 @@ This is just one possible configuration. To use mod_wsgi daemon mode, add the two following directives just under ``WSGIScriptAlias``:: - WSGIDaemonProcess example.com python-path=:/lib/python2.7/site-packages + WSGIDaemonProcess example.com python-path=:/lib/python2.7/site-packages WSGIProcessGroup example.com Replace values between ``<>`` with yours. If you don't use a @@ -59,24 +56,17 @@ Replace values between ``<>`` with yours. If you don't use a remove the last part of the ``WSGIDaemonProcess`` directive. .. note:: + You will certainly need more configuration in order to launch Apache. +Now, you can go the :ref:`dovecot` section to continue the installation. + .. _nginx-label: -***** Nginx ***** -.. note:: - - The following instructions are meant to help you get your site up - and running quickly. However it is not possible for the people - contributing documentation to Modoboa to test every single - combination of web server, wsgi server, distribution, etc. So it is - possible that **your** installation of uwsgi or nginx or Apache or - what-have-you works differently. Keep this in mind. - This section covers two different ways of running Modoboa behind `Nginx `_ using a WSGI application server. Choose the one you prefer between `Green Unicorn `_ or @@ -86,7 +76,7 @@ In both cases, you'll need to download and `install nginx `_. Green Unicorn -============= ++++++++++++++ Firstly, `Download and install gunicorn `_. Then, use the following sample @@ -120,7 +110,7 @@ following configuration:: keepalive_timeout 70; server_name ; - root ; + root ; access_log /var/log/nginx/.access.log; error_log /var/log/nginx/.error.log; @@ -160,11 +150,12 @@ key. `This article contains information about how to do it. Paste this content to your configuration (replace values between -``<>`` with yours), restart nginx and enjoy a really fast -application! +``<>`` with yours) and restart nginx. + +Now, you can go the :ref:`dovecot` section to continue the installation. uWSGI -===== ++++++ The following setup is meant to get you started quickly. You should read the documentation of both nginx and uwsgi to understand how to @@ -304,3 +295,5 @@ does not require it. In the configuration above: ```` The name that you passed to ``modoboa-admin.py deploy`` when you created your Modoboa instance. + +Now, you can go the :ref:`dovecot` section to continue the installation. diff --git a/doc/plugins/amavis.rst b/doc/plugins/amavis.rst deleted file mode 100644 index 268448917..000000000 --- a/doc/plugins/amavis.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _amavis_frontend: - -#################### -Amavisd-new frontend -#################### - -`Official documentation `_. diff --git a/doc/plugins/postfix_autoreply.rst b/doc/plugins/postfix_autoreply.rst deleted file mode 100644 index e1683a6b6..000000000 --- a/doc/plugins/postfix_autoreply.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _postfix_ar: - -########################### -Postfix auto-reply messages -########################### - -`Official documentation `_. diff --git a/doc/plugins/radicale.rst b/doc/plugins/radicale.rst deleted file mode 100644 index 456529d41..000000000 --- a/doc/plugins/radicale.rst +++ /dev/null @@ -1,5 +0,0 @@ -################# -Radicale frontend -################# - -`Official documentation `_. diff --git a/doc/plugins/sievefilters.rst b/doc/plugins/sievefilters.rst deleted file mode 100644 index 0d714afc9..000000000 --- a/doc/plugins/sievefilters.rst +++ /dev/null @@ -1,5 +0,0 @@ -############# -Sieve filters -############# - -`Official documentation `_. diff --git a/doc/plugins/statistics.rst b/doc/plugins/statistics.rst deleted file mode 100644 index 50fd452b0..000000000 --- a/doc/plugins/statistics.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _stats: - -#################### -Graphical statistics -#################### - -`Official documentation `_. diff --git a/doc/plugins/webmail.rst b/doc/plugins/webmail.rst deleted file mode 100644 index b9df5e984..000000000 --- a/doc/plugins/webmail.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _webmail: - -####### -Webmail -####### - -`Official documentation `_. diff --git a/doc/rest_api.rst b/doc/rest_api.rst new file mode 100644 index 000000000..70178848b --- /dev/null +++ b/doc/rest_api.rst @@ -0,0 +1,31 @@ +######## +REST API +######## + +To ease the integration with external sources (software or other), +Modoboa provides a REST API. + +Every installed instance comes with a ready-to-use API and a +documentation. You will find them using the following url patterns: + +* API: *http:///api/v1/* +* Documentation: *http:///docs/api/* + +An `example `_ of this +documentation is available on the official demo. + +Using this API requires an authentication and for now, only a token +based authentication is supported. To get a valid token, log-in to +your instance with a super administrator, go to *Settings > API* and +activate the API access. Press the Update button and wait until the +page is reloaded, the token will be displayed. + +.. image:: _static/api_access_form.png + :align: center + +To make valid API calls, every requests you send must embed this token +within an Authorization HTTP header like this:: + + Authorization: Token + +and the content type of those requests must be ``application/json``. diff --git a/doc/upgrade.rst b/doc/upgrade.rst index 832c74d48..be02393d8 100644 --- a/doc/upgrade.rst +++ b/doc/upgrade.rst @@ -2,38 +2,83 @@ Upgrade ####### +Modoboa +******* + .. warning:: The new version you are going to install may need to modify your database. Before you start, make sure to backup everything! Most of the time, upgrading your installation to a newer Modoboa -version only requires a few actions. In any case, you will need to +version only requires a few actions. In every case, you will need to apply the general procedure first and then check if the version you are installing requires specific actions. -.. note:: - - In case you use a dedicated user and/or a virtualenv, do not forget to - use them: +In case you use a dedicated user and/or a virtualenv, do not forget to +use them: - .. sourcecode:: bash +.. sourcecode:: bash - > sudo -i - > source /bin/activate + > sudo -i + > source /bin/activate -The general procedure is as follows:: +Then, run the following commands: - > pip install modoboa== - > cd - > python manage.py migrate - > python manage.py collectstatic +.. sourcecode:: bash + + > pip install modoboa== + > cd + > python manage.py migrate + > python manage.py collectstatic Once done, check if the version you are installing requires :ref:`specific_upgrade_instructions`. Finally, restart your web server. +Sometimes, you might need to upgrade postfix map files too. To do so, +just run the ``generate_postfix_maps`` command on the same directory +than the one used for installation (:file:`/etc/postfix` by default). + +Make sure to use root privileges and run the following command: + +.. sourcecode:: bash + + > python manage.py generate_postfix_maps --destdir + +Then, reload postfix. + +Extensions +********** + +If a new version is available for an extension you're using, it is +recommanded to install it. Upgrading an extensions is pretty and the +procedure is almost the same than the one used for Modoboa. + +In case you use a dedicated user and/or a virtualenv, do not forget to +use them: + +.. sourcecode:: bash + + > sudo -i + > source /bin/activate + +Then, run the following commands: + +.. sourcecode:: bash + + > pip install == + > cd + > python manage.py migrate + > python manage.py collectstatic + +Finally, restart your web server. + +It is a generic upgrade procedure which will be enough most of the +time but it is generally a good idea to check the associated +documentation. + .. _specific_upgrade_instructions: Specific instructions diff --git a/modoboa/core/forms.py b/modoboa/core/forms.py index 816dc5878..45bdb5f55 100644 --- a/modoboa/core/forms.py +++ b/modoboa/core/forms.py @@ -97,7 +97,7 @@ class APIAccessForm(forms.Form): """Form to control API access.""" enable_api_access = forms.BooleanField( - label=_("Enable API access"), required=False) + label=ugettext_lazy("Enable API access"), required=False) def __init__(self, *args, **kwargs): """Initialize form.""" From 0af78cff3f5441085cde1528f177bfdcf9b9dc49 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 19 Oct 2016 09:45:30 +0200 Subject: [PATCH 4/4] Few fixes. --- doc/contributing.rst | 28 +++++++---------- doc/contributing/getting_started.rst | 47 +++++++++++++++++++++++++--- doc/contributing/plugin_api.rst | 20 ++++++------ doc/manual_installation/modoboa.rst | 2 ++ test-requirements.txt | 1 + 5 files changed, 66 insertions(+), 32 deletions(-) diff --git a/doc/contributing.rst b/doc/contributing.rst index a527e687f..5ef78dfb8 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -2,28 +2,22 @@ How to contribute ################# -Contributions are always welcome but please try to follow those few rules: +Contributions are always welcome. If you want to submit a patch, +please respect the following rules: -- Modoboa tries to respect the `PEP8 `_ +- Open a pull request on the appropriate repository +- Respect `PEP8 `_ +- Document your patch and respect `PEP 257 `_ +- Add unit tests and make sure the global coverage does not decrease -- If you add some code, add some tests too. You can run the tests - suite locally by using `tox `_ - -There are also a few commands that can help you to contribute: - -Start a basic Modoboa instance with a few fixture:: - - $ tox -e serve - -You can log in with admin/password. - -Build the docs to see your changes:: - - $ tox -e doc - $ firefox .tox/doc/tmp/html/index.html +If all those steps are validated, your contribution will generally be +integrated. +Table of contents +================= .. toctree:: + :maxdepth: 1 contributing/getting_started contributing/plugin_api diff --git a/doc/contributing/getting_started.rst b/doc/contributing/getting_started.rst index e36961b34..621e9a58f 100644 --- a/doc/contributing/getting_started.rst +++ b/doc/contributing/getting_started.rst @@ -1,6 +1,6 @@ -############################### -Development recipes for Modoboa -############################### +########### +Useful tips +########### You would like to work on Modoboa but you don't know where to start? You're at the right place! Browse this page to learn useful tips. @@ -51,8 +51,9 @@ You're ready to go! Manage static files =================== -Modoboa uses `bower `_ (thanks to `django-bower `_) -to manage its CSS and javascript dependencies. +Modoboa uses `bower `_ (thanks to `django-bower +`_) to manage its CSS and +javascript dependencies. Those dependencies are listed in a file called :file:`dev_settings.py` located inside the :file:`/modoboa/core` @@ -66,6 +67,42 @@ If you want to add a new dependency, just complete the It will download and store the required files into the :file:`/modoboa/bower_components` directory. +Test your modifications +======================= + +If you deployed a specific instance for your development needs, you +can run the tests suite as follows: + +.. sourcecode:: bash + + > python manage.py test modoboa.core modoboa.lib modoboa.admin modoboa.limits modoboa.relaydomains + +Otherwise, you can run the tests suite from the repository using `tox +`_. + +Start a basic Modoboa instance +============================== + +From the repository, run the following command to launch a simple +instance with a few fixtures: + +.. sourcecode:: bash + + > tox -e serve + +You can use admin/password to log in. + +Build the documentation +======================= + +If you need to modify the documenation and want to see the result, you +can build it as follows: + +.. sourcecode:: bash + + > tox -e doc + > firefox .tox/doc/tmp/html/index.html + FAQ === diff --git a/doc/contributing/plugin_api.rst b/doc/contributing/plugin_api.rst index 984072927..5d2ff90e3 100644 --- a/doc/contributing/plugin_api.rst +++ b/doc/contributing/plugin_api.rst @@ -1,5 +1,5 @@ ################### -Adding a new plugin +Create a new plugin ################### ************ @@ -14,19 +14,20 @@ implementation provides the following possibilities: * Register callback actions for specific events Plugins are nothing more than Django applications with an extra piece -of code that integrates them into Modoboa. The *modo_extension.py* file -will contain a complete description of the plugin: +of code that integrates them into Modoboa. The +:file:`modo_extension.py` file will contain a complete description of +the plugin: * Admin and user parameters * Observed events * Custom menu entries The communication between both applications is provided by -:ref:`events`. Modoboa offers some kind of hooks to let plugin add custom -actions. +:ref:`events`. Modoboa offers some kind of hooks to let plugins add +custom actions. -The following subsections describe plugin architecture and explain -how you can create your own plugin. +The following subsections describe the plugin architecture and explain +how you can create your own. ***************** The required glue @@ -45,7 +46,6 @@ of the future extension:: class MyExtension(ModoExtension): - """My custom Modoboa extension.""" name = "myext" @@ -82,9 +82,9 @@ Parameters A plugin can declare its own parameters. There are two levels available: * 'Administration' parameters : used to configure the plugin, editable - inside the *Admin > Settings > Parameters* page, + inside the *Admin > Settings > Parameters* page * 'User' parameters : per-user parameters (or preferences), editable - inside the *Options > Preferences* page. + inside the *Options > Preferences* page Playing with parameters ======================= diff --git a/doc/manual_installation/modoboa.rst b/doc/manual_installation/modoboa.rst index 119a71303..865492e00 100644 --- a/doc/manual_installation/modoboa.rst +++ b/doc/manual_installation/modoboa.rst @@ -34,6 +34,8 @@ Then, install Modoboa: (env)> pip install modoboa +.. _database: + Database -------- diff --git a/test-requirements.txt b/test-requirements.txt index a1b4ef1c5..554f0a065 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,3 +1,4 @@ factory-boy>=2.4 testfixtures==4.7.0 httmock==1.2.5 +tox