From 0067d2354898d5be14f3e108e6db95742cee0fc5 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Fri, 16 Jan 2026 13:54:12 +0100 Subject: [PATCH] Removed old documentation --- .github/workflows/documentation.yml | 2 - .github/workflows/modoboa.yml | 2 - .gitignore | 3 - MANIFEST.in | 2 +- doc/Makefile | 130 -- doc/_static/api_access_form.png | Bin 17340 -> 0 bytes doc/_static/modoboa_logo.png | Bin 7319 -> 0 bytes doc/conf.py | 226 --- doc/configuration.rst | 645 -------- doc/contributing.rst | 24 - doc/contributing/getting_started.rst | 131 -- doc/contributing/plugin_api.rst | 205 --- doc/contributing/translation.rst | 18 - doc/contributors.rst | 9 - doc/index.rst | 43 - doc/installation.rst | 101 -- doc/manual_installation/amavis.rst | 292 ---- doc/manual_installation/dovecot.rst | 602 ------- doc/manual_installation/modoboa.rst | 326 ---- doc/manual_installation/opendkim.rst | 81 - doc/manual_installation/postfix.rst | 109 -- doc/manual_installation/radicale.rst | 127 -- doc/manual_installation/webserver.rst | 354 ---- doc/moving.rst | 159 -- doc/rebuild_virtual_env.rst | 76 - doc/requirements.txt | 2 - doc/rest_api.rst | 39 - doc/upgrade.rst | 2157 ------------------------- 28 files changed, 1 insertion(+), 5864 deletions(-) delete mode 100644 doc/Makefile delete mode 100644 doc/_static/api_access_form.png delete mode 100644 doc/_static/modoboa_logo.png delete mode 100644 doc/conf.py delete mode 100644 doc/configuration.rst delete mode 100644 doc/contributing.rst delete mode 100644 doc/contributing/getting_started.rst delete mode 100644 doc/contributing/plugin_api.rst delete mode 100644 doc/contributing/translation.rst delete mode 100644 doc/contributors.rst delete mode 100644 doc/index.rst delete mode 100644 doc/installation.rst delete mode 100644 doc/manual_installation/amavis.rst delete mode 100644 doc/manual_installation/dovecot.rst delete mode 100644 doc/manual_installation/modoboa.rst delete mode 100644 doc/manual_installation/opendkim.rst delete mode 100644 doc/manual_installation/postfix.rst delete mode 100644 doc/manual_installation/radicale.rst delete mode 100644 doc/manual_installation/webserver.rst delete mode 100644 doc/moving.rst delete mode 100644 doc/rebuild_virtual_env.rst delete mode 100644 doc/requirements.txt delete mode 100644 doc/rest_api.rst delete mode 100644 doc/upgrade.rst diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 6a3fad742..e7059d971 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -4,13 +4,11 @@ on: paths-ignore: - 'modoboa/**' - 'frontend/**' - - 'doc/**' pull_request: branches: [ master ] paths-ignore: - 'modoboa/**' - 'frontend/**' - - 'doc/**' jobs: cache-and-install: diff --git a/.github/workflows/modoboa.yml b/.github/workflows/modoboa.yml index 6eec728ec..1d9d35794 100644 --- a/.github/workflows/modoboa.yml +++ b/.github/workflows/modoboa.yml @@ -9,7 +9,6 @@ on: paths-ignore: - 'modoboa/**.po' - 'frontend/**' - - 'doc/**' - 'doc-ng/**' - '.editorconfig' - '.readthedocs.yml' @@ -20,7 +19,6 @@ on: paths-ignore: - 'modoboa/**.po' - 'frontend/**' - - 'doc/**' - 'doc-ng/**' - '.editorconfig' - '.readthedocs.yml' diff --git a/.gitignore b/.gitignore index 3b3c04c36..dae15019d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,6 @@ *.mo *.db modoboa.egg-info -doc/.build -doc/.static -doc/.templates DEV .idea .ropeproject diff --git a/MANIFEST.in b/MANIFEST.in index 41cca873c..4d176cb8d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,4 +4,4 @@ recursive-include modoboa/frontend_dist * recursive-include modoboa *.html *.js *.css *.png *.po *.mo *.json *.gif *.ttf *.woff *.woff2 recursive-include modoboa/core/templates *.tpl recursive-include modoboa/core/commands/templates *.tpl -recursive-include doc * +recursive-include doc-ng * diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index 88aa7bed0..000000000 --- a/doc/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = .build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Modoboa.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Modoboa.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/Modoboa" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Modoboa" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - make -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/_static/api_access_form.png b/doc/_static/api_access_form.png deleted file mode 100644 index fb1bf02579373d469597487658e64952c95b0794..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17340 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 diff --git a/doc/_static/modoboa_logo.png b/doc/_static/modoboa_logo.png deleted file mode 100644 index a00cf98b6c76ac83cfa824e3daeb0effc3ea9a28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7319 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 v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# 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"] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = "Modoboadoc" - - -# -- Options for LaTeX output -------------------------------------------------- - -# The paper size ('letter' or 'a4'). -# latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -# latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ("index", "Modoboa.tex", "Modoboa Documentation", "Antoine Nguyen", "manual"), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Additional stuff for the LaTeX preamble. -# latex_preamble = '' - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [("index", "modoboa", "Modoboa Documentation", ["Antoine Nguyen"], 1)] diff --git a/doc/configuration.rst b/doc/configuration.rst deleted file mode 100644 index b45ef47e3..000000000 --- a/doc/configuration.rst +++ /dev/null @@ -1,645 +0,0 @@ -############# -Configuration -############# - -***************** -Online parameters -***************** - -Modoboa provides online panels to modify internal parameters. There -are two available levels: - -* Application level: global parameters, define how the application - behaves. Available at *Modoboa > Parameters* - -* User level: per user customization. Available at *User > Settings > - Preferences* - -Regardless level, parameters are displayed using tabs, each tab -corresponding to one application. - -.. _admin-params: - -General parameters -================== - -The *admin* application exposes several parameters, they are presented below: - -+--------------------+---------------------+-------------------------------+--------------------+ -|Name |Tab |Description |Default value | -+====================+=====================+===============================+====================+ -|Authentication type |General |The backend used for |Local | -| | |authentication | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Default password |General |Scheme used to crypt |sha512crypt | -|scheme | |mailbox passwords | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Rounds |General |Number of rounds (only used by |70000 | -| | |`sha256crypt` and | | -| | |`sha512crypt`). Must be between| | -| | |1000 and 999999999, inclusive. | | -| | | | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Secret key |General |A key used to |random value | -| | |encrypt users' | | -| | |password in sessions | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Sender address |General |Email address used to send | | -| | |notifications. | | -| | | | | -| | | | | -| | | | | -| | | | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Enable communication|General |Enable communication with |yes | -| | |Modoboa public API | | -| | | | | -| | | | | -| | | | | -| | | | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Check new versions |General |Automatically checks if a newer|yes | -| | |version is available | | -| | | | | -| | | | | -| | | | | -| | | | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Send statistics |General |Send statistics to Modoboa |yes | -| | |public API (counters and used | | -| | |extensions) | | -| | | | | -| | | | | -| | | | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Top notifications |General |Interval between two top |30 | -|check interval | |notification checks (in | | -| | |seconds) | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Maximum log record |General |The maximum age in |365 | -|age | |days of a log record | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Items per page |General |Number of displayed |30 | -| | |items per page | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Default top |General |The default |userprefs | -|redirection | |redirection used | | -| | |when no application | | -| | |is specified | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Enable MX checks |Admin |Check that every domain has a |yes | -| | |valid MX record | | -| | | | | -| | | | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Valid MXs |Admin |A list of IP or network address| | -| | |every MX should match. A | | -| | |warning will be sent if a | | -| | |record does not respect this | | -| | |it. | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Enable DNSBL checks |Admin |Check every domain against |yes | -| | |major DNSBL providers | | -| | | | | -| | | | | -+--------------------+---------------------+-------------------------------+--------------------+ -|DKIM keys storage |Admin |Path to a directory where DKIM | | -|directory | | generated keys will be stored | | -| | | | | -| | | | | -| | | | | -| | | | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Default DKIM key |Admin |The default size (in bits) for |2048 | -|length | |new keys | | -| | | | | -| | | | | -| | | | | -| | | | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Handle mailboxes on |Admin |Rename or remove |no | -|filesystem | |mailboxes on the | | -| | |filesystem when they | | -| | |get renamed or | | -| | |removed within | | -| | |Modoboa | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Mailboxes owner |Admin |The UNIX account who |vmail | -| | |owns mailboxes on | | -| | |the filesystem | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Default domain quota|Admin |Default quota (in MB) applied |0 | -| | |to freshly created domains with| | -| | |no value specified. A value of | | -| | |0 means no quota. | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Automatic account |Admin |When a mailbox is |no | -|removal | |removed, also remove | | -| | |the associated | | -| | |account | | -+--------------------+---------------------+-------------------------------+--------------------+ -|Automatic |Admin |Create a domain and a mailbox |yes | -|domain/mailbox | |when an account is | | -|creation | |automatically created | | -| | | | | -+--------------------+---------------------+-------------------------------+--------------------+ - -.. warning:: - - If Dovecot is not running on the same host than Modoboa, you will have - to define which password schemes are supported. To do so, open the - :file:`settings.py` file and add a ``DOVECOT_SUPPORTED_SCHEMES`` - variable with the output of the command: ``doveadm pw -l``. - -.. note:: - - If you are not familiar with virtual domain hosting, you should - take a look at `postfix's documentation - `_. This `How to - `_ - also contains useful information. - -.. note:: - - A random secret key will be generated each time the *Parameters* - page is refreshed and until you save parameters at least once. - -.. note:: - - Specific LDAP parameters are also available, see :ref:`LDAP - authentication `. - -*********** -Media files -*********** - -Modoboa uses a specific directory to upload files (ie. when the -webmail is in use) or to create ones (ex: graphical statistics). This -directory is named ``media`` and is located inside modoboa's -installation directory (called ``modoboa_site`` in this -documentation). - -To work properly, the system user which runs modoboa (``www-data``, -``apache``, whatever) must have write access to this directory. - - -.. _customization: - -************* -Customization -************* - -Custom logo -=========== - -You have the possibility to use a custom logo instead of the default -one on the login page and inside generated PDF documents. - -To do so, open the :file:`settings.py` file and add a -``MODOBOA_CUSTOM_LOGO`` variable. This variable must contain the -relative URL of your logo under ``MEDIA_URL``. For example:: - - MODOBOA_CUSTOM_LOGO = os.path.join(MEDIA_URL, "custom_logo.png") - -Then copy your logo file into the directory indicated by -``MEDIA_ROOT``. - -You can also customize the logo(s) used in the frontend application -(left menu and creation forms). - -To do so, copy the corresponding files inside the frontend directory -directly (defaults to ``/srv/modoboa/instance/frontend``). - -Then, edit the :file:`config.json` file located in this very same -directory and add the following variables:: - - "MENU_LOGO_PATH": "/cusrtom_logo.png", - "CREATION_FORM_LOGO_PATH": "/custom_logo2.png" - -****************** -Host configuration -****************** - -.. note:: - - This section is only relevant when Modoboa handles mailboxes - renaming and removal from the filesystem, which requires that - Dovecot is installed and running on this host. If it is installed - at a non-standard directory, paths to its binaries can be set in the - :file:`settings.py` file with the ``DOVECOT_LOOKUP_PATH`` and - ``DOVEADM_LOOKUP_PATH`` variables. - -To manipulate mailboxes on the filesystem, you must allow the user who -runs Modoboa to execute commands as the user who owns mailboxes. - -To do so, edit the :file:`/etc/sudoers` file and add the following inside:: - - ALL=() NOPASSWD: ALL - -Replace values between ``<>`` by the ones you use. - -.. _timezone_lang: - -********************** -Time zone and language -********************** - -Modoboa is available in many languages. - -To specify the default language to use, edit the :file:`settings.py` file -and modify the ``LANGUAGE_CODE`` variable:: - - LANGUAGE_CODE = 'fr' # or 'en' for english, etc. - -.. note:: - - Each user has the possibility to define the language he prefers. - -In the same configuration file, specify the timezone to use by -modifying the ``TIME_ZONE`` variable. For example:: - - TIME_ZONE = 'Europe/Paris' - -******************* -Sessions management -******************* - -Modoboa uses `Django's session framework -`_ -to store per-user information. - -Few parameters need to be set in the :file:`settings.py` configuration -file to make Modoboa behave as expected:: - - SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Default value - -This parameter is optional but you must ensure it is set to ``False`` -(the default value). - -The default configuration file provided by the ``modoboa-admin.py`` -command is properly configured. - -********************** -Logging authentication -********************** - -To trace login attempts to the web interface, Modoboa uses python -`SysLogHandler `_ -so you can see them in your syslog authentication log file -(`/var/log/auth.log` in most cases). - -Depending on your configuration, you may have to edit the :file:`settings.py` file -and add `'address': '/dev/log'` to the logging section:: - - 'syslog-auth': { - 'class': 'logging.handlers.SysLogHandler', - 'facility': SysLogHandler.LOG_AUTH, - 'address': '/dev/log', - 'formatter': 'syslog' - }, - -*********************** -External authentication -*********************** - -.. _ldap_auth: - -LDAP -==== - -Modoboa supports external LDAP authentication using the following extra components: - -* `Python LDAP client `_ -* `Django LDAP authentication backend `_ - -If you want to use this feature, you must first install those components:: - - $ pip install python-ldap django-auth-ldap - -Then, all you have to do is to modify the :file:`settings.py` file. Add a -new authentication backend to the `AUTHENTICATION_BACKENDS` variable, -like this:: - - AUTHENTICATION_BACKENDS = ( - 'modoboa.lib.authbackends.LDAPBackend', - # 'modoboa.lib.authbackends.LDAPSecondaryBackend', # Useful for a fallback mechanism - 'django.contrib.auth.backends.ModelBackend', - ) - -Finally, go to *Modoboa > Parameters > General* and set *Authentication -type* to LDAP. - -From there, new parameters will appear to let you configure the way -Modoboa should connect to your LDAP server. They are described just below: - -+--------------------+---------------------------------+--------------------+ -|Name |Description |Default value | -+====================+=================================+====================+ -|Server address |The IP address of |localhost | -| |the DNS name of the | | -| |LDAP server | | -+--------------------+---------------------------------+--------------------+ -|Server port |The TCP port number |389 | -| |used by the LDAP | | -| |server | | -+--------------------+---------------------------------+--------------------+ -|Use a secure |Use an SSL/TLS |no | -|connection |connection to access | | -| |the LDAP server | | -+--------------------+---------------------------------+--------------------+ -|Authentication |Choose the |Direct bind | -|method |authentication | | -| |method to use | | -+--------------------+---------------------------------+--------------------+ -|User DN template |The template used to | | -|(direct bind mode) |construct a user's | | -| |DN. It should | | -| |contain one | | -| |placeholder | | -| |(ie. ``%(user)s``) | | -+--------------------+---------------------------------+--------------------+ -|Bind BN |The distinguished | | -| |name to use when | | -| |binding to the LDAP | | -| |server. Leave empty | | -| |for an anonymous | | -| |bind | | -+--------------------+---------------------------------+--------------------+ -|Bind password |The password to use | | -| |when binding to the | | -| |LDAP server (with | | -| |'Bind DN') | | -+--------------------+---------------------------------+--------------------+ -|Search base |The distinguished | | -| |name of the search | | -| |base | | -+--------------------+---------------------------------+--------------------+ -|Search filter |An optional filter string |(mail=%(user)s) | -| |(e.g. '(objectClass=person)'). In| | -| |order to be valid, it must be | | -| |enclosed in parentheses. | | -+--------------------+---------------------------------+--------------------+ -|Password attribute |The attribute used |userPassword | -| |to store user | | -| |passwords | | -+--------------------+---------------------------------+--------------------+ -|Active Directory |Tell if the LDAP |no | -| |server is an Active | | -| |Directory one | | -+--------------------+---------------------------------+--------------------+ -|Administrator groups|Members of those LDAP Posix | | -| |groups will be created ad domain | | -| |administrators. Use ';' | | -| |characters to separate groups. | | -+--------------------+---------------------------------+--------------------+ -|Group type |The type of group used by your |PosixGroup | -| |LDAP directory. | | -| | | | -| | | | -+--------------------+---------------------------------+--------------------+ -|Groups search base |The distinguished name of the | | -| |search base used to find groups | | -| | | | -| | | | -+--------------------+---------------------------------+--------------------+ -|Domain/mailbox |Automatically create a domain and|yes | -|creation |a mailbox when a new user is | | -| |created just after the first | | -| |successful authentication. You | | -| |will generally want to disable | | -| |this feature when the relay | | -| |domains extension is in use | | -+--------------------+---------------------------------+--------------------+ - - -If you need additional parameters, you will find a detailed -documentation `here `_. - -Once the authentication is properly configured, the users defined in -your LDAP directory will be able to connect to Modoboa, the associated -domain and mailboxes will be automatically created if needed. - -The first time a user connects to Modoboa, a local account is created -if the LDAP username is a valid email address. By default, this -account belongs to the *SimpleUsers* group and it has a mailbox. - -To automatically create domain administrators, you can use the -**Administrator groups** setting. If a LDAP user belongs to one the -listed groups, its local account will belong to the *DomainAdmins* -group. In this case, the username is not necessarily an email address. - -Users will also be able to update their LDAP password directly from -Modoboa. - -.. note:: - - Modoboa doesn't provide any synchronization mechanism once a user - is registered into the database. Any modification done from the - directory to a user account will not be reported to Modoboa (an - email address change for example). Currently, the only solution is - to manually delete the Modoboa record, it will be recreated on the - next user login. - -.. _smtp_auth: - -SMTP -==== - -It is possible to use an existing SMTP server as an authentication -source. To enable this feature, edit the :file:`settings.py` file and -change the following setting: - -.. sourcecode:: python - - AUTHENTICATION_BACKENDS = ( - 'modoboa.lib.authbackends.SMTPBackend', - 'django.contrib.auth.backends.ModelBackend', - ) - -SMTP server location can be customized using the following settings: - -.. sourcecode:: python - - AUTH_SMTP_SERVER_ADDRESS = 'localhost' - AUTH_SMTP_SERVER_PORT = 25 - AUTH_SMTP_SECURED_MODE = None # 'ssl' or 'starttls' are accepted - - -.. _ldap_sync: - -******************** -LDAP synchronization -******************** - -Modoboa can synchronize accounts with an LDAP directory (tested with -OpenLDAP) but this feature is not enabled by default. To activate it, -add ``modoboa.ldapsync`` to ``MODOBOA_APPS`` in the -:file:`settings.py` file:: - - MODOBOA_APPS = ( - 'modoboa', - 'modoboa.core', - 'modoboa.lib', - 'modoboa.admin', - 'modoboa.transport', - 'modoboa.relaydomains', - 'modoboa.limits', - 'modoboa.parameters', - 'modoboa.dnstools', - 'modoboa.ldapsync', - ) - -and enable it from the admin panel. - -.. warning:: - - Make sure to install additional :ref:`requirements ` - otherwise it won't work. - -The following parameters are available and must be filled: - -+--------------------+---------------------------------+--------------------+ -|Name |Description |Default value | -+====================+=================================+====================+ -|Enable LDAP |Control LDAP synchronization |no | -|synchronization |state | | -| | | | -+--------------------+---------------------------------+--------------------+ -|Bind DN |The DN of a user with write | | -| |permission to create/update | | -| |accounts | | -+--------------------+---------------------------------+--------------------+ -|Bind password |The associated password | | -| | | | -| | | | -+--------------------+---------------------------------+--------------------+ -|Account DN template |The template used to build | | -| |account DNs (must contain a | | -| |%(user)s placeholder | | -+--------------------+---------------------------------+--------------------+ - - -******************** -Database maintenance -******************** - -Cleaning the logs table -======================= - -Modoboa logs administrator specific actions into the database. A -clean-up script is provided to automatically remove oldest -records. The maximum log record age can be configured through the -online panel. - -To use it, you can setup a cron job to run every night:: - - 0 0 * * * /manage.py cleanlogs - # - # Or like this if you use a virtual environment: - # 0 0 * * * /manage.py cleanlogs - -Cleaning the session table -========================== - -Django does not provide automatic purging. Therefore, it's your job to -purge expired sessions on a regular basis. - -Django provides a sample clean-up script: ``django-admin.py -clearsessions``. That script deletes any session in the session table -whose ``expire_date`` is in the past. - -For example, you could setup a cron job to run this script every night:: - - 0 0 * * * /manage.py clearsessions - # - # Or like this if you use a virtual environment: - # 0 0 * * * /manage.py clearsessions - -.. _inactive_accounts: - -Cleaning inactive accounts -========================== - -Thanks to :ref:`lastlogin`, it is now possible to monitor inactive -accounts. An account is considered inactive if no login has been -recorded for the last 30 days (this value can be changed through the -admin panel). - -A management command is available to disable or delete inactive -accounts. For example, you could setup a cron job to run it every -night:: - - 0 0 * * * /manage.py clean_inactive_accounts - # - # Or like this if you use a virtual environment: - # 0 0 * * * /manage.py clean_inactive_accounts - -The default behaviour is to disable accounts. You can delete them -using the ``--delete`` option. - -************* -DMARC reports -************* - -.. _dmarcdoc: - -A set of tools to use DMARC through Modoboa. - -This feature is still in BETA stage, for now it only parses XML aggregated -reports and generate visual reports on a per-domain basis. - -Installation -============ - -.. note:: - - modoboa-installer can automatically set it up for you. - -Make sure to install the following additional system package according to your distribution: - -+-----------------+ -| Debian / Ubuntu | -+=================+ -| libmagic1 | -+-----------------+ - -+------------+ -| CentOS | -+============+ -| file-devel | -+------------+ - - -Integration with Postfix -======================== - -A management command is provided to automatically parse DMARC -aggregated reports (rua) and feed the database. The execution of this -command can be automated with the definition of a postfix service and -a custom transport table. - -First, declare a new service in ``/etc/postfix/master.cf``:: - - dmarc-rua-parser unix - n n - - pipe - flags= user=vmail:vmail argv= /manage.py import_aggregated_report --pipe - -Define a new transport table inside ``/etc/postfix/main.cf``:: - - transport_maps = - hash:/etc/postfix/dmarc_transport - # other transport maps... - -Create a file called ``/etc/postfix/dmarc_transport`` with the following content:: - - dmarc-rua-parser: - -.. note:: - You must not declare this email address as an identity (user account or alias), else DMARC reports will be directed to your mailbox and won't be parsed. - -Hash the file using the following command:: - - $ postmap /etc/postfix/dmarc_transport - -Finally, reload postfix:: - - $ service postfix reload diff --git a/doc/contributing.rst b/doc/contributing.rst deleted file mode 100644 index 3233b627b..000000000 --- a/doc/contributing.rst +++ /dev/null @@ -1,24 +0,0 @@ -################# -How to contribute -################# - -Contributions are always welcome. If you want to submit a patch, -please respect the following rules: - -- 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 all those steps are validated, your contribution will generally be -integrated. - -Table of contents -================= - -.. toctree:: - :maxdepth: 1 - - contributing/getting_started - contributing/plugin_api - contributing/translation diff --git a/doc/contributing/getting_started.rst b/doc/contributing/getting_started.rst deleted file mode 100644 index 581220ec4..000000000 --- a/doc/contributing/getting_started.rst +++ /dev/null @@ -1,131 +0,0 @@ -############### -Getting started -############### - -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. - -With Docker -=========== - -A docker image is available for developers. To use it, you must -install `docker `_ and -`docker-compose `_ first. - -If not already done, clone the repo and open it:: - - $ git clone https://github.com/modoboa/modoboa.git - $ cd modoboa - -Then, just run the following command:: - - $ docker-compose up - -Then if not done already, run this command to create an OIDC application -in order to be able to log in from the frontend: - -.. sourcecode:: bash - - $ docker exec modoboa-api '/bin/sh -c python3 /code/test_project/manage.py createapplication --name frontend --client-id "LVQbfIIX3khWR3nDvix1u9yEGHZUxcx53bhJ7FlD" --user 1 --algorithm RS256 --redirect-uris 'https://localhost:3000/login/logged' public authorization-code' - $ docker exec modoboa-api '/bin/sh -c python3 /code/test_project/manage.py createapplication --name Dovecot --skip-authorization --client-id=dovecot --client-secret=Toto12345 confidential client-credentials' - -It will start the docker environment and make a Modoboa instance -available at ``https://localhost:8000`` and the new admin interface at ``https://localhost:3000``. - -If you don't want to use docker or need a more complex development -setup, go to the next section. - -Without Docker -============== - -Prepare a virtual environment ------------------------------ - -A `virtual environment -`_ is a good way to -setup a development environment on your machine. - -To do so, run the following commands:: - - $ python3 -m venv - $ source /bin/activate - $ git clone https://github.com/modoboa/modoboa.git - $ cd modoboa - $ pip install -e .[dev] - -This will create a symbolic link to your local copy so -any modification you make will be automatically available in your -environment, no need to copy them. - -Deploy an instance for development ----------------------------------- - -.. warning:: - - Make sure to :ref:`create a database ` before running - this step. The format of the database url is also described in this - page. - -Now that you have setup a development environment, you can deploy a -test instance and run it:: - - $ cd - $ modoboa-admin.py deploy --dburl default: --domain localhost --devel instance - $ python manage.py runserver - -You're ready to go! You should be able to access Modoboa at -``http://localhost:8000`` using ``admin:password`` as credentials. - -Frontend -======== - -The 2.0 version of Modoboa introduces a completely new interface written -with the `Vue.js `_ framework. The source files are -located in the :file:`frontend/` directory. - -To set it up, you will need to install NodeJS and Yarn - to manage the -dependencies. Then, navigate to the :file:`frontend/` directory and run:: - - $ yarn install - -You can now build it and serve it - while running your instance too to -serve the API - with:: - - $ yarn serve - -Tests -===== - -If you deployed an instance for development, you can launch the tests -from it with:: - - $ python manage.py test modoboa - -You could also test just some them, i.e.:: - - $ python manage.py test modoboa.core.tests.test_authentication - -Alternatively, you can use `tox `_ from -the repository to run all the tests and check the coverage with:: - - $ tox - -You could limit the environment to a specific Python version with the -``-e py`` argument. - -Note that it is also possible to quickly run a test instance without -any deployment - e.g. to preview some changes - by running:: - - $ tox -e serve - -Documentation -============= - -The source files are located in the file:`doc/` folder and are written -in reStructuredText (reST). They are formatted in HTML and compiled -thanks to `Sphinx `_. - -To build it and see the result, run:: - - $ tox -e doc - $ open .tox/doc/tmp/html/index.html diff --git a/doc/contributing/plugin_api.rst b/doc/contributing/plugin_api.rst deleted file mode 100644 index 2422eea27..000000000 --- a/doc/contributing/plugin_api.rst +++ /dev/null @@ -1,205 +0,0 @@ -################### -Create a new plugin -################### - -************ -Introduction -************ - -Modoboa offers a plugin API to expand its capabilities. The current -implementation provides the following possibilities: - -* Expand navigation by adding entry points to your plugin inside the GUI -* Access and modify administrative objects (domains, mailboxes, etc.) -* 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 -:file:`modo_extension.py` file will contain a complete description of -the plugin: - -* Admin and user parameters -* Custom menu entries - -The communication between both applications is provided by `Django -signals -`_. - -The following subsections describe the plugin architecture and explain -how you can create your own. - -***************** -The required glue -***************** - -To create a new plugin, just start a new django application like -this (into Modoboa's directory):: - - $ python manage.py startapp - -Then, you need to register this application using the provided -API. Just copy/paste the following example into the :file:`modo_extension.py` file -of the future extension:: - - from modoboa.core.extensions import ModoExtension, exts_pool - - - class MyExtension(ModoExtension): - """My custom Modoboa extension.""" - - name = "myext" - label = "My Extension" - version = "0.1" - description = "A description" - url = "myext_root_location" # optional, name is used if not defined - - def load(self): - """This method is called when Modoboa loads available and activated plugins. - - Declare parameters and register events here. - """ - pass - - def load_initial_data(self): - """Optional: provide initial data for your extension here.""" - pass - - exts_pool.register_extension(MyExtension) - -Once done, simply add your extension's module name to the -``MODOBOA_APPS`` variable located inside :file:`settings.py`. Finally, -run the following commands:: - - $ python manage.py migrate - $ python manage.py load_initial_data - $ python manage.py collectstatic - -********** -Parameters -********** - -A plugin can declare its own parameters. There are two levels available: - -* 'Global' parameters : used to configure the plugin, editable - inside the *Admin > Settings > Parameters* page -* 'User' parameters : per-user parameters (or preferences), editable - inside the *Options > Preferences* page - -Playing with parameters -======================= - -Parameters are defined using `Django forms -`_ and Modoboa -adds two special forms you can inherit depending on the level of -parameter(s) you want to add: - -* ``modoboa.parameters.forms.AdminParametersForm``: for general parameters - -* ``modoboa.parameters.forms.UserParametersForm``: for user parameters - -To register new parameters, add the following line into the ``load`` -method of your plugin class:: - - from modoboa.parameters import tools as param_tools - param_tools.registry.add( - LEVEL, YourForm, ugettext_lazy("Title")) - -Replace ``LEVEL`` by ``"global"`` or ``"user"``. - -*********************** -Custom role permissions -*********************** - -Modoboa uses Django's internal permission system. Administrative roles -are nothing more than groups (``Group`` instances). - -An extension can add new permissions to a group by listening to the -``extra_role_permissions`` signal. Here is an example: - -.. sourcecode:: python - - from django.dispatch import receiver - from modoboa.core import signals as core_signals - - PERMISSIONS = { - "Resellers": [ - ("relaydomains", "relaydomain", "add_relaydomain"), - ("relaydomains", "relaydomain", "change_relaydomain"), - ("relaydomains", "relaydomain", "delete_relaydomain"), - ("relaydomains", "service", "add_service"), - ("relaydomains", "service", "change_service"), - ("relaydomains", "service", "delete_service") - ] - } - - @receiver(core_signals.extra_role_permissions) - def extra_role_permissions(sender, role, **kwargs): - """Add permissions to the Resellers group.""" - return constants.PERMISSIONS.get(role, []) - -********************* -Extending admin forms -********************* - -The forms used to edit objects (account, domain, etc.) through the admin -panel are composed of tabs. You can extend them (ie. add new -tabs) in a pretty easy way thanks to custom signals. - -Account -======= - -To add a new tab to the account edition form, define new listeners -(handlers) for the following signals: - -* ``modoboa.admin.signals.extra_account_forms`` - -* ``modoboa.admin.signals.get_account_form_instances`` - -* ``modoboa.admin.signals.check_extra_account_form`` (optional) - -Example: - -.. sourcecode:: python - - from django.dispatch import receiver - from modoboa.admin import signals as admin_signals - - - @receiver(admin_signals.extra_account_forms) - def extra_account_form(sender, user, account, **kwargs): - return [ - {"id": "tabid", "title": "Title", "cls": MyFormClass} - ] - - @receiver(admin_signals.get_account_form_instances) - def fill_my_tab(sender, user, account, **kwargs): - return {"id": my_instance} - - -Domain -====== - -To add a new tab to the domain edition form, define new listeners -(handlers) for the following signals: - -* ``modoboa.admin.signals.extra_domain_forms`` - -* ``modoboa.admin.signals.get_domain_form_instances`` - -Example: - -.. sourcecode:: python - - from django.dispatch import receiver - from modoboa.admin import signals as admin_signals - - - @receiver(admin_signals.extra_domain_forms) - def extra_account_form(sender, user, domain, **kwargs): - return [ - {"id": "tabid", "title": "Title", "cls": MyFormClass} - ] - - @receiver(admin_signals.get_domain_form_instances) - def fill_my_tab(sender, user, domain, **kwargs): - return {"id": my_instance} diff --git a/doc/contributing/translation.rst b/doc/contributing/translation.rst deleted file mode 100644 index ab89e6bc4..000000000 --- a/doc/contributing/translation.rst +++ /dev/null @@ -1,18 +0,0 @@ -########### -Translation -########### - -Modoboa needs you to translate the project ! Feel free to join the translation team. - -The project is using Transifex. To start with translation, you will need to create an account and join `modoboa's team `_ - -.. _translation: - -Frontend -======== - -When editing the frontend, you may need to update localization files for transifex to pick up your changes. - -To do so, after finishing editing, go to the frontend directory and run the following command:: - - $ make makemessages diff --git a/doc/contributors.rst b/doc/contributors.rst deleted file mode 100644 index c7792a499..000000000 --- a/doc/contributors.rst +++ /dev/null @@ -1,9 +0,0 @@ -Contributors -============ - -.. Add yourself - -- `Antidot `_ -- `Bearstech `_ -- `CAP-REL `_ -- `Dalnix `_ diff --git a/doc/index.rst b/doc/index.rst deleted file mode 100644 index 780fe8c8e..000000000 --- a/doc/index.rst +++ /dev/null @@ -1,43 +0,0 @@ -.. Modoboa documentation master file, created by - sphinx-quickstart on Mon Jan 3 22:29:25 2011. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Modoboa documentation -===================== - -.. 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 `_. - -And it is extensible by nature and comes with a lot of additional extensions: - -+---------------------------------------------------------+-------------------------+------------------------------------------------------+ -|Name |Description |Documentation | -| | | | -| | | | -| | | | -+---------------------------------------------------------+-------------------------+------------------------------------------------------+ -|`modoboa-pfxadmin-migrate |A tool to migrate from |https://github.com/modoboa/modoboa-pfxadmin-migrate | -|`_ |Postfixadmin | | -+---------------------------------------------------------+-------------------------+------------------------------------------------------+ - -Table of contents ------------------ - -.. toctree:: - :maxdepth: 1 - - installation - upgrade - configuration - moving - rest_api - contributing - contributors diff --git a/doc/installation.rst b/doc/installation.rst deleted file mode 100644 index 44c5a8db4..000000000 --- a/doc/installation.rst +++ /dev/null @@ -1,101 +0,0 @@ -############ -Installation -############ - -Requirements -=============== -You will need a Server to perform well with at least: - -* CPU: 2 -* RAM: 2GB -* Disk: 10GB -* Python 3.8+ -* Postgres 12+ or MariaDB 10.4+ or MySQL 8+ or sqlite3 or LDAP - -.. note:: **👀 Heads up for modoboa versions 1.15 and later** - - Python 2 support has been dropped with modoboa version 1.15. - If you still have Python 2 installed on your system either uninstall it - or force modoboa user to run with Python 3. - -If you want to run virus scan on your server you will need **4GB** of RAM. - -Recommended 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 (modoboa, -postfix, dovecot, amavis and more) on one machine. - -.. warning:: - - For now, only Debian 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:`manually `. - -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 - - -if you get this warning - '/usr/bin/env: ‘python’: No such file or directory', do make sure sure python is installed on your server. Sometimes python is installed but the installer can't detect it or which python version to run, especially on a debian based system. Then run this command first. - -.. sourcecode:: bash - - > sudo apt-get install python3-virtualenv python3-pip - -For the sake of simplicity, you can also install the ``python-is-python3`` package. -It allows you to use ``python`` command. - -Wait a few minutes and you're done \o/ - -.. _by_hand: - -Manual installation -=================== - -For those who need a manual installation or who just want to setup a -specific part, here are the steps you must follow: - -.. toctree:: - :maxdepth: 1 - - manual_installation/modoboa - manual_installation/webserver - manual_installation/dovecot - manual_installation/postfix - manual_installation/opendkim - manual_installation/radicale - manual_installation/amavis - -Extensions ----------- - -Only few commands are needed to add a new extension to your setup. - -In case you use a dedicated user and/or a virtualenv, do not forget to -use them: - -.. sourcecode:: bash - - > sudo -u -i bash - > source /bin/activate - -Then, run the following commands: - -.. sourcecode:: bash - - > pip install == - > cd - > python manage.py migrate - > python manage.py collectstatic - > python manage.py check --deploy - -Then, restart your web server. diff --git a/doc/manual_installation/amavis.rst b/doc/manual_installation/amavis.rst deleted file mode 100644 index 5fd413ed2..000000000 --- a/doc/manual_installation/amavis.rst +++ /dev/null @@ -1,292 +0,0 @@ -###### -Amavis -###### - -Quick Amavis setup -================== - -By default, amavis doesn't use a database. To configure this -behaviour, you first need to create a dedicated database. This step is a -bit manual since no *ready-to-use* SQL schema is provided by -amavis. The information is located inside README files, one for `MySQL -`_ and one for `PostgreSQL -`_. - -Then, you must tell amavis to use this database for lookups and -quarantined messages storing. Here is a working configuration sample:: - - @lookup_sql_dsn = - (['DBI::database=;host=;port=', '', ']']); - - @storage_sql_dsn = - (['DBI::database=;host=;port=', '', ']']); - - # PostgreSQL users NEED this parameter! - # MySQL users only need this parameter is email addresses are stored - # using the VARBINARY type. - $sql_allow_8bit_address = 1; - - $virus_quarantine_method = 'sql:'; - $spam_quarantine_method = 'sql:'; - $banned_files_quarantine_method = 'sql:'; - $bad_header_quarantine_method = 'sql:'; - - $virus_quarantine_to = 'virus-quarantine'; - $banned_quarantine_to = 'banned-quarantine'; - $bad_header_quarantine_to = 'bad-header-quarantine'; - $spam_quarantine_to = 'spam-quarantine'; - -Replace values between ``<>`` by yours. To know how to configure -amavis to allow quarantined messages release, read this :ref:`section -`. - -.. note:: - - Amavis configuration allows for separate lookup and storage - databases but Modoboa doesn't support it yet. - -.. note:: - - ``$sql_partition_tag`` should remain undefined in ``amavisd.conf``. Modoboa - does not support the use of ``sql_partition_tag``, setting this value can - result in quarantined messages not showing or the wrong messages being - released or learnt as ham/spam. - -Connect Modoboa and Amavis -========================== - -You must tell to Modoboa where it can find the amavis -database. Inside :file:`settings.py`, add a new connection to the -``DATABASES`` variable like this:: - - DATABASES = { - # Stuff before - # - "amavis": { - "ENGINE" : "", - "HOST" : "", - "NAME" : "", - "USER" : "", - "PASSWORD" : "" - } - } - -Replace values between ``<>`` with yours. - -Cleanup -------- - -Storing quarantined messages to a database can quickly become a -perfomance killer. Modoboa provides a simple script to periodically -purge the quarantine database. To use it, add the following line -inside root's crontab:: - - 0 0 * * * /manage.py qcleanup - # - # Or like this if you use a virtual environment: - # 0 0 * * * /manage.py qcleanup - -Replace ``modoboa_site`` with the path of your Modoboa instance. - -By default, messages older than 14 days are automatically purged. You -can modify this value by changing the ``MAX_MESSAGES_AGE`` parameter -in the online panel. - -.. _amavis_release: - -Release messages -================ - -To release messages, first take a look at `this page -`_. It -explains how to configure amavisd-new to listen somewhere for the -AM.PDP protocol. This protocol is used to send requests. - -Below is an example of a working configuration:: - - $interface_policy{'SOCK'} = 'AM.PDP-SOCK'; - $interface_policy{'9998'} = 'AM.PDP-INET'; - - $policy_bank{'AM.PDP-SOCK'} = { - protocol => 'AM.PDP', - auth_required_release => 0, - }; - $policy_bank{'AM.PDP-INET'} = { - protocol => 'AM.PDP', - inet_acl => [qw( 127.0.0.1 [::1] )], - }; - -Don't forget to update the ``inet_acl`` list if you plan to release from -the network. - -Once amavisd-new is configured, just tell Modoboa where it can find -the *release server* by modifying the following parameters in the -online panel: - -+--------------------+--------------------+------------------------+ -|Name |Description |Default value | -+====================+====================+========================+ -|Amavis connection |Mode used to access |unix | -|mode |the PDP server | | -+--------------------+--------------------+------------------------+ -|PDP server address |PDP server address |localhost | -| |(if inet mode) | | -+--------------------+--------------------+------------------------+ -|PDP server port |PDP server port (if | | -| |inet mode) 9998 | | -+--------------------+--------------------+------------------------+ -|PDP server socket |Path to the PDP |/var/amavis/amavisd.sock| -| |server socket (if | | -| |unix mode) | | -+--------------------+--------------------+------------------------+ - -Deferred release ----------------- - -By default, simple users are not allowed to release messages -themselves. They are only allowed to send release requests to -administrators. - -As administrators are not always available or logged into Modoboa, a -notification tool is available. It sends reminder e-mails to every -administrators or domain administrators. To use it, add the following -example line to root's crontab:: - - 0 12 * * * /manage.py amnotify --baseurl='' - # - # Or like this if you use a virtual environment: - # 0 12 * * * /manage.py amnotify --baseurl='' - -You are free to change the frequency. - -.. note:: - - If you want to let users release their messages alone (not - recommended), go to the admin panel. - -The following parameters are available to let you customize this -feature: - -+--------------------+--------------------+------------------------+ -|Name |Description |Default value | -+====================+====================+========================+ -|Check requests |Interval between two|30 | -|interval |release requests | | -| |checks | | -+--------------------+--------------------+------------------------+ -|Allow direct release|Allow users to |no | -| |directly release | | -| |their messages | | -+--------------------+--------------------+------------------------+ -|Notifications sender|The e-mail address |notification@modoboa.org| -| |used to send | | -| |notitications | | -+--------------------+--------------------+------------------------+ - -.. _selfservice: - -Self-service mode -================= - -The *self-service* mode lets users act on quarantined messages without -beeing authenticated. They can: - -* View messages -* Remove messages -* Release messages (or send release requests) - -To access a specific message, they only need the following information: - -* Message's unique identifier -* Message's secret identifier - -This information is controlled by *amavis*, which is in charge of -notifying users when new messages are put into quarantine. Each -notification (one per message) must embark a direct link containing -the required identifiers. - -To activate this feature, go the administration panel and set the -**Enable self-service mode** parameter to yes. - -The last step is to customize the notification messages amavis -sends. The most important is to embark a direct link. Take a look at -the `README.customize `_ file to -learn what you're allowed to do. - -Here is a link example:: - - https:///user/selfquarantine/%i/%R?secret_id=[:secret_id] - -.. _sa_manual_learning: - -Manual SpamAssassin learning -============================ - -It is possible to manually train `SpamAssassin -`_ using the quarantine's content. By -train, we mean: - -* Mark message(s) as spam (false negative(s)) - -* Mark message(s) as non-spam (false positive(s)) - -This feature is available to all users (from super administrators to -simple users) but not enabled by default. - -SpamAssassin configuration --------------------------- - -For better performance and to enable the per-user level, SpamAssassin -must store bayes information into a SQL database. - -Create a new database and a new user/password (using your favorite -database server) and edit the default configuration file -(:file:`/etc/spamassassin/local.cf`) to add the following lines -inside: - -.. sourcecode:: perl - - bayes_store_module Mail::SpamAssassin::BayesStore:: - bayes_sql_dsn - bayes_sql_username - bayes_sql_password - -Replace values between ``<>`` by yours. Possible values for ``Driver`` -are ``PgSQL`` or ``MySQL`` (non exhaustive list). The syntax for -``DSN`` depends on the driver you choose. Please consult the official -documentation. - -Enable the feature through Modoboa ----------------------------------- - -Manual learning is disabled by default. You can activate it through -the administration panel (*Modoboa > Paremeters > Amavis*). There two -learning levels: - -#. Global: available to administrators only. A single (global) bayes - database is shared between everyone. - -#. Per domain: available to administrators and domain - administrators. Each domain can have a dedicated database. - -#. Per user: each user can create its own database to customize the - way SpamAssassin will detect spam. - -The domain and user levels are not activated by default, dedicated -parameters are available through the panel. - -.. note:: - - Domain and user databases are only created the first time someone - calls the learning feature through the quarantine. - -.. warning:: - - A bayes database needs to reach pre-defined thresholds before it - can be used by SpamAssassin. The default values are **200** spams - and **200** hams. - -You will find other paramaters related to this feature. You won't need -to change them most of the time, unless SpamAssassin is hosted on a -different machine than Modoboa. (in this case, ``spamc`` will be used -instead of ``sa-learn``). diff --git a/doc/manual_installation/dovecot.rst b/doc/manual_installation/dovecot.rst deleted file mode 100644 index 7b8d2f290..000000000 --- a/doc/manual_installation/dovecot.rst +++ /dev/null @@ -1,602 +0,0 @@ -.. _dovecot: - -####### -Dovecot -####### - -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. - -You can find configuration documentation `here `_. - -This proposed configuration is the one you can find with modoboa-installer. For up to date configuration, `take a look here `_ - -Packages -======== - -For debian and derivative, recommended packages are:: - - apt install dovecot-imapd dovecot-lmtpd dovecot-managesieved dovecot-sieve - -Mailboxes -========= - -First, edit the :file:`conf.d/10-mail.conf` and set the ``mail_location`` -variable:: - - # maildir - mail_location = maildir:~/Maildir - -Then, edit the ``inbox`` namespace and add the following line:: - - inbox = yes - -In order for dovecot to automaticaly create usual folders on account creation, edit the ``inbox`` namespace of :file:`15-mailboxes.conf`:: - - mailbox Drafts { - auto = subscribe - special_use = \Drafts - } - mailbox Junk { - auto = subscribe - special_use = \Junk - } - mailbox Sent { - auto = subscribe - special_use = \Sent - } - mailbox Trash { - auto = subscribe - special_use = \Trash - } - -Starting dovecot 2.2.20+, you can add ``autoexpunge`` parameter to delete older message, for instance:: - - mailbox Trash { - auto = subscribe - special_use = \Trash - autoexpunge=30d - } - -With dovecot 2.1+, it ensures all the special mailboxes will be -automaticaly created for new accounts. - -For dovecot 2.0 and older, use the `autocreate -`_ plugin. - -.. _fs_operations: - -Operations on the file system ------------------------------ - -.. warning:: - - Modoboa needs to access the ``dovecot`` binary to check its - version. To find the binary path, we use the ``which`` command - first and then try known locations (:file:`/usr/sbin/dovecot` and - :file:`/usr/local/sbin/dovecot`). If you installed dovecot in a - custom location, please tell us where the binary is by using the - ``DOVECOT_LOOKUP_PATH`` setting (see :file:`settings.py`). - -Three operation types are considered: - -#. Mailbox creation -#. Mailbox renaming -#. Mailbox deletion - -The first one is managed by Dovecot. The last two ones may be managed -by Modoboa if it can access the file system where the mailboxes are -stored (see :ref:`admin-params` to activate this feature). - -Those operations are treated asynchronously by a cron script. For -example, when you rename an e-mail address through the web UI, the -associated mailbox on the file system is not modified -directly. Instead of that, a *rename* order is created for this -mailbox. The mailbox will be considered unavailable until the order is -executed (see :ref:`Postfix configuration `). - -Edit the crontab of the user who owns the mailboxes on the file system:: - - $ crontab -u -e - -And add the following line inside:: - - * * * * * python /manage.py handle_mailbox_operations - -.. warning:: - - The cron script must be executed by the system user owning the mailboxes. - -.. warning:: - - The user running the cron script must have access to the - :file:`settings.py` file of the modoboa instance. - -The result of each order is recorded into Modoboa's log. Go to -*Modoboa > Logs* to consult them. - -.. _dovecot_authentication: - -Authentication -============== - -To make the authentication work, edit the :file:`conf.d/10-auth.conf` and -uncomment the following line at the end:: - - #!include auth-system.conf.ext - !include auth-sql.conf.ext - #!include auth-ldap.conf.ext - #!include auth-passwdfile.conf.ext - #!include auth-checkpassword.conf.ext - #!include auth-vpopmail.conf.ext - #!include auth-static.conf.ext - - -Then, edit the :file:`conf.d/auth-sql.conf.ext` file and add the following -content inside:: - - passdb sql { - driver = sql - # Path for SQL configuration file, see example-config/dovecot-sql.conf.ext - args = /etc/dovecot/dovecot-sql.conf.ext - } - - userdb sql { - driver = sql - args = /etc/dovecot/dovecot-sql.conf.ext - } - -Make sure to activate only one backend (per type) inside your configuration -(just comment the other ones). - -Edit the :file:`dovecot-sql.conf.ext` and modify the configuration according -to your database engine. - -.. _dovecot_mysql_queries: - -MySQL users ------------ - -For debian and derivative, you need to install mysql connector for dovecot:: - sudo apt install dovecot-mysql - -:: - - driver = mysql - - connect = host= dbname= user= password= - - default_pass_scheme = CRYPT - - user_query = \ - SELECT '%{home_dir}/%%d/%%n' AS home, %mailboxes_owner_uid as uid, \ - %mailboxes_owner_gid as gid, \ - CONCAT('*:bytes=', mb.quota, 'M') AS quota_rule \ - FROM admin_mailbox mb \ - INNER JOIN admin_domain dom ON mb.domain_id=dom.id \ - INNER JOIN core_user u ON u.id=mb.user_id \ - WHERE (mb.is_send_only=0 OR '%s' NOT IN ('imap', 'pop3', 'lmtp')) \ - AND mb.address='%%n' AND dom.name='%%d' - - password_query = \ - SELECT email AS user, password, '%{home_dir}/%%d/%%n' AS userdb_home, \ - %mailboxes_owner_uid AS userdb_uid, %mailboxes_owner_gid AS userdb_gid, \ - CONCAT('*:bytes=', mb.quota, 'M') AS userdb_quota_rule \ - FROM core_user u \ - INNER JOIN admin_mailbox mb ON u.id=mb.user_id \ - INNER JOIN admin_domain dom ON mb.domain_id=dom.id \ - WHERE (mb.is_send_only=0 OR '%s' NOT IN ('imap', 'pop3')) \ - AND u.email='%%u' AND u.is_active=1 AND dom.enabled=1 - - iterate_query = SELECT email AS user FROM core_user WHERE is_active - -.. _dovecot_pg_queries: - -PostgreSQL users ----------------- - -For debian and derivative, you need to install postgres connector for dovecot:: - sudo apt install dovecot-pgsql - -:: - - driver = pgsql - - connect = host= dbname= user= password= - - default_pass_scheme = CRYPT - - user_query = \ - SELECT '%{home_dir}/%%d/%%n' AS home, %mailboxes_owner_uid as uid, \ - %mailboxes_owner_gid as gid, '*:bytes=' || mb.quota || 'M' AS quota_rule \ - FROM admin_mailbox mb \ - INNER JOIN admin_domain dom ON mb.domain_id=dom.id \ - INNER JOIN core_user u ON u.id=mb.user_id \ - WHERE (mb.is_send_only IS NOT TRUE OR '%s' NOT IN ('imap', 'pop3', 'lmtp')) \ - AND mb.address='%%n' AND dom.name='%%d' - - password_query = \ - SELECT email AS user, password, '%{home_dir}/%%d/%%n' AS userdb_home, \ - %mailboxes_owner_uid AS userdb_uid, %mailboxes_owner_gid AS userdb_gid, \ - CONCAT('*:bytes=', mb.quota, 'M') AS userdb_quota_rule \ - FROM core_user u \ - INNER JOIN admin_mailbox mb ON u.id=mb.user_id \ - INNER JOIN admin_domain dom ON mb.domain_id=dom.id \ - WHERE (mb.is_send_only IS NOT TRUE OR '%s' NOT IN ('imap', 'pop3'))\ - AND email='%%u' AND is_active AND dom.enabled - - iterate_query = SELECT email AS user FROM core_user WHERE is_active - -SQLite users ------------- - -For debian and derivative, you need to install sqlite connector for dovecot:: - sudo apt install dovecot-sqlite - -:: - - driver = sqlite - - connect = - - default_pass_scheme = CRYPT - - password_query = SELECT email AS user, password FROM core_user u INNER JOIN admin_mailbox mb ON u.id=mb.user_id INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE u.email='%Lu' AND u.is_active=1 AND dom.enabled=1 - - user_query = SELECT '/%Ld/%Ln' AS home, as uid, as gid, ('*:bytes=' || mb.quota || 'M') AS quota_rule FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE mb.address='%Ln' AND dom.name='%Ld' - - iterate_query = SELECT email AS user FROM core_user - -.. note:: - - Replace values between ``<>`` with yours. - -.. _dovecot_oauth2: - -OAuth 2 authentication -====================== - -You first need to register Dovecot as an authorized consumer of the -OAuth2 authentication service provided by Modoboa. To do so, create an -application with the following commands: - -.. sourcecode:: bash - - > cd - > python manage.py createapplication --name=Dovecot --skip-authorization --client-id=dovecot confidential client-credentials - -On success, you should see an output similar to:: - - New application Dovecot created successfully. - client_secret: XXXX - -To enable OAuth2 authentication in Dovecot, edit the :file:`conf.d/10-auth.conf` -file and update the auth_mechanisms line as follows:: - - auth_mechanisms = plain login oauthbearer xoauth2 - -Then, add the following line at the end:: - - !include auth-oauth2.conf.ext - -Then, create a file named :file:`conf.d/auth-oauth2.conf.ext` with the -following content:: - - passdb { - driver = oauth2 - mechanisms = xoauth2 oauthbearer - args = /etc/dovecot/conf.d/dovecot-oauth2.conf.ext - } - -Finally, create a file named :file:`conf.d/dovecot-oauth2.conf.ext` with the -following content:: - - introspection_mode = post - introspection_url = https://dovecot:@/api/o/introspect/ - username_attribute = username - tls_ca_cert_file = /etc/ssl/certs/ca-certificates.crt - active_attribute = active - active_value = true - -Replace ```` with the value you obtained earlier. - -LDAP -==== -To make the LDAP authentication work, edit the :file:`conf.d/10-auth.conf` and -uncomment the following line at the end:: - - !include auth-ldap.conf.ext - -Then edit the :file:`conf.d/auth-ldap.conf.ext` and edit the passdb section as following. -You should comment the userdb section, which will be managed by SQL with modoboa database.:: - - passdb { - driver = ldap - - # Path for LDAP configuration file, see example-config/dovecot-ldap.conf.ext - args = /etc/dovecot/dovecot-ldap.conf.ext - } - - #userdb { - #driver = ldap - #args = /etc/dovecot/dovecot-ldap.conf.ext - - # Default fields can be used to specify defaults that LDAP may override - #default_fields = home=/home/virtual/%u - #} - -Your own dovecot LDAP configuration file is now :file:`/etc/dovecot/dovecot-ldap.conf.ext`. -You can add your default LDAP conf in it, following the `official documentation `_. - -Synchronize dovecot LDAP conf with modoboa LDAP conf ----------------------------------------------------- - -To make dovecot LDAP configuration synchronized with modoboa LDAP configuration, you should create a dedicated dovecot conf file. -At the end of your dovecot configuration file (:file:`dovecot-ldap.conf.ext`), add the following line:: - - !include_try dovecot-modoboa.conf.ext - -Then, set modoboa parameter *Enable Dovecot LDAP sync* to *Yes*. -Then set the *Dovecot LDAP config file* following the previous step (*/etc/dovecot/dovecot-modoboa.conf.ext* in the example) - -The last step is to add the command **update_dovecot_conf** to the cron job of modoboa. -Then, each time your modoboa LDAP configuration is updated, your dovecot LDAP configuration will also be. - -LMTP -==== - -`Local Mail Transport Protocol -`_ is used -to let Postfix deliver messages to Dovecot. - -First, make sure the protocol is activated by looking at the -``protocols`` setting (generally inside -:file:`dovecot.conf`). It should be similar to the following example:: - - protocols = imap pop3 lmtp - -Then, open the :file:`conf.d/10-master.conf`, look for ``lmtp`` -service definition and add the following content inside:: - - service lmtp { - # stuff before - unix_listener /var/spool/postfix/private/dovecot-lmtp { - mode = 0600 - user = postfix - group = postfix - } - # stuff after - } - -We assume here that Postfix is *chrooted* within -:file:`/var/spool/postfix`. - -Finally, open the :file:`conf.d/20-lmtp.conf` and modify it as follows:: - - protocol lmtp { - postmaster_address = postmaster@ - mail_plugins = $mail_plugins quota sieve - } - -Replace ```` by the appropriate value. - -.. note:: - - If you don't plan to apply quota or to use filters, just adapt the - content of the ``mail_plugins`` setting. - -.. _dovecot_quota: - -Quota -===== - -Modoboa lets adminstrators define per-domain and/or per-account limits -(quota). It also lists the current quota usage of each account. Those -features require Dovecot to be configured in a specific way. - -Inside :file:`conf.d/10-mail.conf`, add the ``quota`` plugin to the default -activated ones:: - - mail_plugins = quota - -Inside :file:`conf.d/10-master.conf`, update the ``dict`` service to set -proper permissions:: - - service dict { - # If dict proxy is used, mail processes should have access to its socket. - # For example: mode=0660, group=vmail and global mail_access_groups=vmail - unix_listener dict { - mode = 0600 - user = - #group = - } - } - -Inside :file:`conf.d/20-imap.conf`, activate the ``imap_quota`` plugin:: - - protocol imap { - # ... - - mail_plugins = $mail_plugins imap_quota - - # ... - } - -Inside :file:`dovecot.conf`, activate the quota SQL dictionary backend:: - - dict { - quota = :/etc/dovecot/dovecot-dict-sql.conf.ext - } - -Inside :file:`conf.d/90-quota.conf`, activate the *quota dictionary* backend:: - - plugin { - quota = dict:User quota::proxy::quota - } - -It will tell Dovecot to keep quota usage in the SQL dictionary. - -Finally, edit the :file:`dovecot-dict-sql.conf.ext` file and put the -following content inside:: - - connect = host= dbname= user= password= - # SQLite users - # connect = /path/to/the/database.db - - map { - pattern = priv/quota/storage - table = admin_quota - username_field = username - value_field = bytes - } - map { - pattern = priv/quota/messages - table = admin_quota - username_field = username - value_field = messages - } - -*PostgreSQL* users ------------------- - -Database schema update -^^^^^^^^^^^^^^^^^^^^^^ - -The ``admin_quota`` table is created by Django but unfortunately it -doesn't support ``DEFAULT`` constraints (it only simulates them when the -ORM is used). As PostgreSQL is a bit strict about constraint -violations, you must execute the following query manually:: - - db=> ALTER TABLE admin_quota ALTER COLUMN bytes SET DEFAULT 0; - db=> ALTER TABLE admin_quota ALTER COLUMN messages SET DEFAULT 0; - -Trigger -^^^^^^^ - -As indicated on `Dovecot's wiki -`_, you need a trigger to -properly update the quota. - -A working copy of this trigger is available on `Github `_. - -Download this file and copy it on the server running postgres. Then, -execute the following commands:: - - $ su - postgres - $ psql [modoboa database] < /path/to/modoboa_postgres_trigger.sql - $ exit - -Replace ``[modoboa database]`` by the appropriate value. - -Forcing recalculation ---------------------- - -For existing installations, *Dovecot* (> 2) offers a command to -recalculate the current quota usages. For example, if you want to -update all usages, run the following command:: - - $ doveadm quota recalc -A - -Be carefull, it can take a while to execute. - -ManageSieve/Sieve -================= - -Modoboa lets users define filtering rules from the web interface. To -do so, it requires *ManageSieve* to be activated on your server. - -Inside :file:`conf.d/20-managesieve.conf`, make sure the following lines are -uncommented:: - - protocols = $protocols sieve - - service managesieve-login { - # ... - } - - service managesieve { - # ... - } - - protocol sieve { - # ... - } - -Finally, configure the ``sieve`` plugin by editing the -:file:`conf.d/90-sieve.conf` file. Put the follwing caontent inside:: - - plugin { - # Location of the active script. When ManageSieve is used this is actually - # a symlink pointing to the active script in the sieve storage directory. - sieve = ~/.dovecot.sieve - - # - # The path to the directory where the personal Sieve scripts are stored. For - # ManageSieve this is where the uploaded scripts are stored. - sieve_dir = ~/sieve - } - -Restart Dovecot. - -Now, you can go to the :ref:`postfix` section to finish the installation. - -.. _lastlogin: - -Last-login tracking -=================== - -To update the ``last_login`` attribute of an account after a succesful -IMAP or POP3 login, you can configure a `post-login script -`_. - -Open :file:`conf.d/10-master.conf` add the following configuration -(``imap`` and ``pop3`` services are already defined, you just need to -update them):: - - service imap { - executable = imap postlogin - } - - service pop3 { - executable = pop3 postlogin - } - - service postlogin { - executable = script-login /usr/local/bin/postlogin.sh - user = modoboa - unix_listener postlogin { - } - } - -Then, you must create a script named -:file:`/usr/local/bin/postlogin.sh`. According to your database -engine, the content will differ. - -PostgreSQL ----------- - -.. sourcecode:: bash - - #!/bin/sh - - psql -c "UPDATE core_user SET last_login=now() WHERE username='$USER'" > /dev/null - - exec "$@" - -MySQL ------ - -.. sourcecode:: bash - - #!/bin/sh - - DBNAME=XXX - DBUSER=XXX - DBPASSWORD=XXX - - echo "UPDATE core_user SET last_login=now() WHERE username='$USER'" | mysql -u $DBUSER -p$DBPASSWORD $DBNAME - - exec "$@" diff --git a/doc/manual_installation/modoboa.rst b/doc/manual_installation/modoboa.rst deleted file mode 100644 index a691af193..000000000 --- a/doc/manual_installation/modoboa.rst +++ /dev/null @@ -1,326 +0,0 @@ -.. _modoboa_manual_install: - -####### -Modoboa -####### - -This section describes the installation of the web interface (a -`Django `_ project). - -This proposed configuration is the one you can find with modoboa-installer. For up to date configuration, `take a look here `_ - - -Prepare the system ------------------- - -First of all, we recommend the following context: - -* A dedicated system user -* A `virtual environment - `_ - 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 on Debian-based -distributions using `virtualenv `_: - -.. code-block:: console - - # apt-get install virtualenv python3-pip - # useradd modoboa # create a dedicated user - # sudo -u modoboa -i bash # log in as the newly created user - $ virtualenv --python python3 ./env # create the virtual environment - $ source ./env/bin/activate # activate the virtual environment - -Modoboa depends on external tools and some of them require compilation -so you need a compiler and a few C libraries. Make sure to install the -following system packages according to your distribution: - -+-------------------------------+ -| Debian / Ubuntu | -+===============================+ -| build-essential python3-dev | -| libxml2-dev libxslt-dev | -| libjpeg-dev librrd-dev | -| rrdtool libffi-dev libssl-dev | -| pkg-config libcairo2-dev | -+-------------------------------+ - -+-----------------------------+ -| CentOS | -+=============================+ -| gcc gcc-c++ python3-devel | -| libxml2-devel libxslt-devel | -| libjpeg-turbo-devel | -| rrdtool-devel rrdtool | -| libffi-devel | -+-----------------------------+ - -.. note:: - - Alternatively, you could rely on your distribution packages for the Modoboa - dependencies which require compilation - e.g. ``rrdtool`` - if the version - is compatible. In this case, you have to create your virtual environment - with the ``--system-site-packages`` option, and the required system - packages will be: - - +---------------------------------------+ - | python3-wheel python3-rrdtool rrdtool | - +---------------------------------------+ - -Then, install Modoboa by running: - -.. code-block:: console - - (env)$ pip install modoboa - -.. _database: - -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. You should also read the notes for those database -backends on the `official Django documentation -`_. - -PostgreSQL -********** - -Install the corresponding Python binding: - -.. code-block:: console - - (env)$ pip install psycopg[binary]>=3.1 - -.. note:: - Ubuntu and Debian repositories contain python-psycopgX package - but starting modoboa 2.2.0 minimum version required is 3.1 and - it has not yet it these distro yet - Prior modoboa version can run with ``python3-psycopg2``. - -Then, create a user and a database. For example, to create the ``modoboa`` -database owned by a ``modoboa`` user, run the following commands on your -PostgreSQL server: - -.. code-block:: console - - # sudo -l -u postgres createuser --no-createdb modoboa - # sudo -l -u postgres createdb --owner=modoboa modoboa - -MySQL / MariaDB -*************** - -Install the corresponding Python binding: - -.. code-block:: console - - (env)$ pip install mysqlclient - -.. note:: - - Alternatively, you can install the ``python3-mysqldb`` package instead on - Debian-based distributions if your virtual environment was created with - ``--system-site-packages`` option. - -.. note:: - - MariaDB 10.2 (and newer) require mysqlclient 1.3.11 (or newer). - -Then, create a user and a database. For example, to create the ``modoboa`` -database owned by a ``modoboa`` user, run the following SQL commands: - -.. code-block:: mysql - - CREATE DATABASE modoboa; - CREATE USER 'modoboa'@'localhost' IDENTIFIED BY 'my-strong-password-here'; - GRANT ALL PRIVILEGES ON modoboa.* TO 'modoboa'@'localhost'; - -.. _deployment: - -Deploy an instance ------------------- - -``modoboa-admin.py`` is a command line tool that lets you deploy a -*ready-to-use* Modoboa site. To create a new instance into ``./instance``, -you just have to run the following command: - -.. code-block:: console - - (env)$ modoboa-admin.py deploy instance --collectstatic \ - --domain --dburl default: - -.. 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 and possibly perform more steps. Check the - documentation/readme of each extensions for specific Instructions. - - 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``. - - Fox example, if you were using postgres, you could setup your command like this: - ``modoboa-admin.py deploy instance_name --collectstatic --domain example.com --dburl default:postgres://user:pass@[localhost]/modoboa`` - -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 command line arguments. - -You can consult the complete option list by running the following -command: - -.. code-block:: console - - (env)$ modoboa-admin.py help deploy - -Cron jobs ---------- - -A few recurring jobs must be configured to make Modoboa works as -expected. - -Create a new file, for example :file:`/etc/cron.d/modoboa` and put the -following content inside: - -.. sourcecode:: bash - - # - # Modoboa specific cron jobs - # - PYTHON= - INSTANCE= - - # Operations on mailboxes - * * * * * $PYTHON $INSTANCE/manage.py handle_mailbox_operations - - # Generate DKIM keys (they will belong to the user running this job) - * * * * * root umask 077 && $PYTHON $INSTANCE/manage.py modo manage_dkim_keys - - # Sessions table cleanup - 0 0 * * * root $PYTHON $INSTANCE/manage.py clearsessions - # Logs table cleanup - 0 0 * * * root $PYTHON $INSTANCE/manage.py cleanlogs - # Logs parsing - */15 * * * * root $PYTHON $INSTANCE/manage.py logparser &> /dev/null - 0 * * * * modoboa $PYTHON $INSTANCE/manage.py update_statistics - # DNSBL checks - */30 * * * * modoboa $PYTHON $INSTANCE/manage.py modo check_mx - # Public API communication - 0 * * * * modoboa $PYTHON $INSTANCE/manage.py communicate_with_public_api - -.. hint:: **🥵 potential high load configuration** - - Please note that above crontab might not be ideal on high load systems. - If you receive a fairly high amount of emails per day, you may want to - run modoboas logparser tasks *once per night*. - - This has the down side that the statistic graph and message log within - the UI are updated once per day only. - -.. _policy_daemon: - -Policy daemon -------------- - -Modoboa comes with a built-in `Policy Daemon for Postfix `_. Current features are: - -* Define daily sending limits for domains and/or accounts - -A `redis server `_ is required to run this new daemon. - -You can launch it manually using the following command: - -.. sourcecode:: bash - - (env)> python manage.py policy_daemon - -But we recommend an automatic start using ``systemd`` or -``supervisor``. Here is a configuration example for ``supervisor``: - -.. sourcecode:: ini - - [program:policyd] - autostart=true - autorestart=true - command= /manage.py policy_daemon - directory= - redirect_stderr=true - user=modoboa - numprocs=1 - -It will listen by default on ``127.0.0.1`` and port ``9999``. The -policy daemon won't do anything unless you tell :ref:`postfix ` to use it. - - -RQ daemon ---------- - -Modoboa uses `RQ `_ as a job handler for async task. - -A `redis server `_ is required to run this new daemon. - -A worker needs to be launched in the venv. - -You can launch it manually using the following command: - -.. sourcecode:: bash - - (env)> rq worker high default low - -But we recommend an automatic start using ``systemd`` or -``supervisor``. Here is a configuration example for ``supervisor``: - -.. sourcecode:: ini - - [program:modoboa-dkim-worker] - autostart=true - autorestart=true - command= /manage.py rqworker dkim - directory= - user= - redirect_stderr=true - numprocs=1 - stopsignal=TERM - - -Now you can continue to the :ref:`webserver` section. diff --git a/doc/manual_installation/opendkim.rst b/doc/manual_installation/opendkim.rst deleted file mode 100644 index b57381e18..000000000 --- a/doc/manual_installation/opendkim.rst +++ /dev/null @@ -1,81 +0,0 @@ -######## -OpenDKIM -######## - -Modoboa can generate `DKIM -`_ keys for -the hosted domains but it won't sign or check messages. To do that, -you need a dedicated software like `OpenDKIM `_. - -.. note:: - - The cron job in charge of creating DKIM keys must be run using the - same user than OpenDKIM (ie. opendkim in most cases). - -Database -======== - -Since keys related information is stored in Modoboa's database, you -need to tell OpenDKIM how it can access it. - -First, make sure to install the required additional packages on your -system (``libopendbx1-*`` on debian based distributions or ``opendbx-*`` -on CentOS, the complete name depends on your database engine). - -Then, insert the following SQL view into Modoboa's database: - -PostgreSQL ----------- - -:: - - CREATE OR REPLACE VIEW dkim AS ( - SELECT id, name as domain_name, dkim_private_key_path AS private_key_path, - dkim_key_selector AS selector - FROM admin_domain WHERE enable_dkim - ); - -MySQL/MariaDB -------------- - -:: - - CREATE OR REPLACE VIEW dkim AS ( - SELECT id, name as domain_name, dkim_private_key_path AS private_key_path, - dkim_key_selector AS selector - FROM admin_domain WHERE enable_dkim=1 - ); - -Configuration -============= - -You should find OpenDKIM's configuration file at :file:`/etc/opendkim.conf`. - -Add the following content to it:: - - KeyTable dsn:://:@//table=dkim?keycol=id?datacol=domain_name,selector,private_key_path - SigningTable dsn:://:@//table=dkim?keycol=domain_name?datacol=id - Socket inet:12345@localhost - -Replace values between ``<>`` by yours. Accepted values for ``driver`` -are ``pgsql`` or ``mysql``. Make sure the user you specify has read -permission on the view created previously. - -If you run a debian based system, make sure to adjust the following -setting in the :file:`/etc/default/opendkim` file:: - - SOCKET=inet:12345@localhost - -Eventually, reload OpenDKIM. - -Postfix integration -=================== - -Add the following lines to the :file:`/etc/postfix/main.cf` file:: - - smtpd_milters = inet:127.0.0.1:12345 - non_smtpd_milters = inet:127.0.0.1:12345 - milter_default_action = accept - milter_content_timeout = 30s - -and reload postfix. diff --git a/doc/manual_installation/postfix.rst b/doc/manual_installation/postfix.rst deleted file mode 100644 index f9bf3a0e3..000000000 --- a/doc/manual_installation/postfix.rst +++ /dev/null @@ -1,109 +0,0 @@ -.. _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: - -.. sourcecode:: bash - - > cd - > python manage.py generate_postfix_maps --destdir - -```` 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. For TLS configuration, you can look at the -`used configuration `_ -for `modoboa installer `_. -(this is just one possible configuration):: - - # Stuff before - unknown_local_recipient_reject_code = 550 - unverified_recipient_reject_code = 550 - - # appending .domain is the MUA's job. - append_dot_mydomain = no - - ## Proxy maps - proxy_read_maps = - proxy:unix:passwd.byname - proxy::/etc/postfix/sql-domains.cf - proxy::/etc/postfix/sql-domain-aliases.cf - proxy::/etc/postfix/sql-aliases.cf - proxy::/etc/postfix/sql-relaydomains.cf - proxy::/etc/postfix/sql-maintain.cf - proxy::/etc/postfix/sql-relay-recipient-verification.cf - proxy::/etc/postfix/sql-sender-login-map.cf - proxy::/etc/postfix/sql-spliteddomains-transport.cf - proxy::/etc/postfix/sql-transport.cf - - ## Virtual transport settings - virtual_transport = lmtp:unix:private/dovecot-lmtp - - virtual_mailbox_domains = proxy::/etc/postfix/sql-domains.cf - virtual_alias_domains = proxy::/etc/postfix/sql-domain-aliases.cf - virtual_alias_maps = proxy::/etc/postfix/sql-aliases.cf - - ## Relay domains - relay_domains = proxy::/etc/postfix/sql-relaydomains.cf - transport_maps = - proxy::/etc/postfix/sql-transport.cf - proxy::/etc/postfix/sql-spliteddomains-transport.cf - - smtpd_recipient_restrictions = - permit_mynetworks - permit_sasl_authenticated - check_recipient_access - proxy::/etc/postfix/sql-maintain.cf - proxy::/etc/postfix/sql-relay-recipient-verification.cf - reject_unverified_recipient - reject_unauth_destination - reject_non_fqdn_sender - reject_non_fqdn_recipient - reject_non_fqdn_helo_hostname - - smtpd_sender_login_maps = proxy::/etc/postfix/sql-sender-login-map.cf - - # Stuff after - -Replace ```` by the name of the database you use. - -Restart Postfix. - -.. _policyd_config: - -Policy daemon -------------- - -If you want to enable the built-in policy daemon, add the following -content to the :file:`/etc/postfix/main.cf` file:: - - smtpd_recipient_restrictions = - # ... - check_policy_service inet:localhost:9999 - # ... - -And reload postfix. - -.. note:: - - The ``check_policy_service`` line must be placed before the - ``permit_mynetworks`` one, otherwise the daemon won't be called. diff --git a/doc/manual_installation/radicale.rst b/doc/manual_installation/radicale.rst deleted file mode 100644 index 912fbb2e8..000000000 --- a/doc/manual_installation/radicale.rst +++ /dev/null @@ -1,127 +0,0 @@ -.. _radicale: - -####### -Radicale -####### - -This page is displaying how to install and use radicale when either having installed modoboa manually or with the dedicated installer. - -.. _radicale_oauth2: - -OAuth 2 authentication -====================== - -.. note:: - - These steps are automatic if you use an up-to-date modoboa-installer to install/upgrade. - -Preparing the usage of radicale (manual install only) ------------------------------------------------------ - -It is assumed you have not installed in the past radicale from your package manager and your modoboa installation is working correctly. If so, you may skip this section and proceed to the next one. -You will need to create directories for the radicale user, needed files and set-up the account (location may change depending on your OS and initial set-up). - -.. sourcecode:: bash - - > sudo mkdir /var/lib/radicale /etc/radicale - > sudo touch /etc/radicale/{rights,config} - > sudo adduser --system --home /var/lib/radicale/ --no-create-home --gecos "Radicale CalDAV server" --group --disabled-password --quiet radicale - > sudo chown -R radicale /etc/radicale - > sudo chown /var/lib/radicale - -Creation of the virtual environment (manual install only) ---------------------------------------------------------- - -.. sourcecode:: bash - - > sudo -u radicale virtualenv /var/lib/radicale/env - -Installing radicale oauth plugin --------------------------------- - -You need to install ``radicale-modoboa-auth-oauth2`` python package inside radicale venv. -If you used the installer you can use the following commands: - -.. sourcecode:: bash - - > sudo -u radicale -i bash - > cd ~ - > env/bin/pip install radicale-modoboa-auth-oauth2 - -For manual installations, this will do the job: - -.. sourcecode:: bash - - > sudo -u radicale /var/lib/radicale/env/bin/pip install radicale-modoboa-auth-oauth2 - -Please note because the plugin offered by modoboa's team is listing radicale as a dependency you do not need to explicitely install radicale. - -Oauth application creation --------------------------- - -You first need to register Radicale as an authorized consumer of the -OAuth2 authentication service provided by Modoboa. To do so, create an -application with the following commands: - -.. sourcecode:: bash - - > cd - > python manage.py createapplication --name=Radicale --skip-authorization --client-id=radicale confidential client-credentials - -On success, you should see an output similar to:: - - New application Radicale created successfully. - client_secret: XXXX - -To enable OAuth2 authentication in Radicale, edit the :file:`/etc/radicale/config` -file and update the `type` in `[auth]` to:: - - type = radicale_modoboa_auth_oauth2 - -Then, add the following line in `[auth]`:: - - oauth2_introspection_endpoint = https://radicale:@/api/o/introspect/ - - -Replace ```` with the value you obtained earlier. - -Your :file:`/etc/radicale/config` should look like this (listening address and port may vary):: - - [server] - hosts = 0.0.0.0:5232,[::]:5232 - - [auth] - type = radicale_modoboa_auth_oauth2 - oauth2_introspection_endpoint = https://radicale:@/api/o/introspect/ - - [rights] - type = from_file - file = /etc/radicale/rights - - [storage] - filesystem_folder = /var/lib/radicale/collections - -With that set-up, radicale should be working when managing calendars through modoboa's web interface but _not_ when using other clients like Thunderbird. - -Modifications for using external clients (optional) ---------------------------------------------------- - -To ensure other clients can identify, you need to modify radicale by adding in the config file under the [auth] section:: - - dovecot_socket = /run/dovecot/auth-radicale - -and in 10-master.conf for dovecot:: - - unix_listener auth-radicale { - mode = 0660 - user = radicale - group = dovecot - } - -Then, restart both modoboa and radicale to enjoy managing calendars (ICS type) with your favorite client. - -Reverse proxy for radicale (optional) -------------------------------------- - -At this stage, no encryption is provided, and you may use a reverse proxy as described in `Radicale's documentation -`_. diff --git a/doc/manual_installation/webserver.rst b/doc/manual_installation/webserver.rst deleted file mode 100644 index 47f8bd581..000000000 --- a/doc/manual_installation/webserver.rst +++ /dev/null @@ -1,354 +0,0 @@ -.. _webserver: - -########## -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:: - - WSGIPythonHome /var/www/modoboa/env - WSGIPythonPath /var/www/modoboa/instance - - - ServerName - - DocumentRoot - - Alias /media/ /media/ - /media/> - Options FollowSymLinks - Require all granted - - - Alias /sitestatic/ /sitestatic/ - /sitestatic/> - Options FollowSymLinks - Require all granted - - - WSGIScriptAliasMatch ^/(api|accounts) /instance/wsgi.py - WSGIApplicationGroup %{GLOBAL} - - # Pass Authorization header to enable API usage: - WSGIPassAuthorization On - - Alias / /frontend - /frontend> - Options FollowSymLinks - Require all granted - - - LogLevel info - - -This is just one possible configuration. - -Replace values between ``<>`` with yours. If you don't use a -`virtualenv `_, just -remove the last part of the ``WSGIDaemonProcess`` directive. -.. note:: - - You may need to add:: - import sys - - sys.path.append('') - sys.path.append('/bin') - sys.path.append('/lib/python3.X/site-packages') - - in :file:`/instance/wsgi.py`. - -.. 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 -***** - -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 -`_. - -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:: - - 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 -`_. - -Recommend packages for debian and derivatives:: - - apt install uwsgi uwsgi-plugin-python3 - -Here is a sample nginx configuration:: - - upstream modoboa { - server unix: fail_timeout=0; - } - - server { - listen 80; - listen [::]:80; - server_name ; - rewrite ^ https://$server_name$request_uri? permanent; - } - - server { - listen 443 ssl http2; - listen [::]:443 ssl http2; - server_name ; - root ; - - ssl_certificate ; - ssl_certificate_key ; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384"; - ssl_prefer_server_ciphers on; - ssl_session_cache shared:SSL:10m; - ssl_verify_depth 3; - ssl_dhparam /etc/nginx/dhparam.pem; - - client_max_body_size 10M; - - access_log /var/log/nginx/modoboa-access.log; - error_log /var/log/nginx/modoboa-error.log; - - location /sitestatic/ { - try_files $uri $uri/ =404; - } - - location /media/ { - try_files $uri $uri/ =404; - } - - location ~ ^/(api|accounts|autodiscover) { - include uwsgi_params; - uwsgi_param UWSGI_SCRIPT instance.wsgi:application; - uwsgi_pass modoboa; - } - - location / { - alias /frontend/; - index index.html; - - expires -1; - add_header Pragma "no-cache"; - add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"; - - try_files $uri $uri/ /index.html = 404; - } - } - -````, ````, ````, -```` and ```` must be replaced by the -value you used when :ref:`you deployed your instance `. - -In case you want to use enable auto-configuration functionality, -create a second virtualhost configuration (the hostname should look -like ``autoconfig.``):: - - server { - listen 80; - listen [::]:80; - server_name autoconfig.; - root ; - - access_log /var/log/nginx/autoconfig-access.log; - error_log /var/log/nginx/autoconfig-error.log; - - location ~ ^/(mail/config-v1.1.xml|mobileconfig) { - include uwsgi_params; - uwsgi_param UWSGI_SCRIPT instance.wsgi:application; - uwsgi_pass modoboa; - } -} - -```` and ```` 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: - -```` - 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 - buffer-size = 8192 - max-requests = 5000 - single-interpreter = 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, usually ``instance``. - -Now, you can go the :ref:`dovecot` section to continue the installation. - -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. - -Now, you can go the :ref:`dovecot` section to continue the installation. diff --git a/doc/moving.rst b/doc/moving.rst deleted file mode 100644 index 12c62a683..000000000 --- a/doc/moving.rst +++ /dev/null @@ -1,159 +0,0 @@ -################# -Moving to Modoboa -################# - -You have an existing platform and you'd like to move to Modoboa, the -following tools could help you. - -Using IMAP protocol -=================== - -.. _imap: - -`Modoboa `_ provides a way to transfer accounts -hosted on a different platform/provider to your personal server using -the IMAP protocol and a tool called `OfflineIMAP -`_. - -It works as follows: - -* You first declare what needs to be migrated, basically the domain(s) you own and where they can be found. By doing that, you'll allow accounts hosted on the platform/provider you're migrating from to log into your Modoboa server -* The first time an old account (one coming from your previous provider) successfuly log into Modoboa, a dedicated migration task is created -* On a regular basis (every hour generally), a cron job is responsible for generating an OfflineIMAP configuration file including instructions to migrate all declared migrations and lauching OfflineIMAP to start/continue migrations - -.. warning:: - - As you probably already understood, you can't migrate all your - accounts at the same time since you don't know their corresponding - password (most of the time). Every account migration must be - started by the account's owner. - -Configuration -------------- - -Modoboa won'thandle the installation of OfflineIMAP so you -need to do it on your own. The following `instructions -`_ will help you. - -Once done, *the new admin interface (v2)* will let you: - -* define the neccessary information to `connect to your old platform/provider `_ -* define `what is to be migrated `_ (ie. the accounts) -* customize the behaviour of OfflineIMAP : go to 'Parameters > Imap Migration' from the left menu - -.. warning:: - - **Auto create domain** option must be enabled to make this feature - work. Go to 'Parameters > Administration > Mailboxes' and check if - it's the case. - -To generate an OfflineIMAP configuration file, run the following command: - -.. sourcecode:: bash - - > python manage.py generate_offlineimap_config - -The synchronization script must be configured to run periodically on -your new server. Since it will copy mailboxes content to its final -destination, filesystem permissions must be respected. To do that, it -must be executed by the user which owns mailboxes (generally -``vmail``). - -Here is a configuration example where the script is executed every -hours. You can copy it inside the ``/etc/cron.d/modoboa`` file: - -.. sourcecode:: shell - - PYTHON=/srv/modoboa/env/bin/python - INSTANCE=/srv/modoboa/instance - - 0 */1 * * * vmail cd /srv/vmail && $PYTHON $INSTANCE/manage.py generate_offlineimap_config --output .offlineimaprc && /usr/local/bin/offlineimap > /dev/null 2>&1 - -Feel free to adapt it. - -This will sync back-and-forth user mailbox. - -.. _providers: - -Providers ---------- - -A provider represents an IMAP server that hosts one or several domains -you own. It includes connection information (network address, port, -etc.) and a list of hosted domain. - -For each domain you declare, you must provide its name. Modoboa will -then create a local domain with the exact same name if needed (ie. if -it does not exist yet) the first time it migrates an account. - -Optionaly, you have the possibility to rename a domain (for example: -domain.com -> domain.net) by providing a value to the 'Local domain' -field. - -.. _migrations: - -Migrations ----------- - -Migrations are automatically created, you don't need to do it. - -The first time an account of your old platform successfuly log into -Modoboa (using old credentials), a local account and a migration task -will be created. - -.. warning:: - - In case of domain renaming as described in `Providers `_, - users must use the new email address as username for next connection - attempts. - -SuperAdmins can monitor running migrations and stop/delete them from -the `IMAP Migration` section (left menu). - - -From postfixadmin -================= - -A dedicated command allows you to convert an existing `postfixadmin -`_ database to a Modoboa -one. Consult the `documentation -`_ to know more -about the process. - -Using CSV files -=============== - -Modoboa allows you to import any object (domain, domain alias, mailbox -and alias) using a simple CSV file encoded using **UTF8**. Each line -corresponds to a single object and must respect one of the following -format:: - - domain; ; ; ; - domainalias; ; ; - relaydomain; ; ; ; ; ; - account; ; ; ; ; ; ; ; ; [, ...] - alias; ; ; ; ... - -Boolean fields accept the following values: ``true``, ``1``, ``yes``, -``y`` (case insensitive). Any other value will be evaluated as false. - -.. warning:: - - The order does matter. Objects are created sequencially so a - domain must be created before its mailboxes and aliases and a - mailbox must created before its alias(es). - -To actually import such a file: - -.. sourcecode:: bash - - > sudo -u -i bash - > source /bin/activate - > cd - > python manage.py modo import - -Available options can be listed using the following command: - -.. sourcecode:: bash - - > python manage.py modo import -h diff --git a/doc/rebuild_virtual_env.rst b/doc/rebuild_virtual_env.rst deleted file mode 100644 index 1b47c43df..000000000 --- a/doc/rebuild_virtual_env.rst +++ /dev/null @@ -1,76 +0,0 @@ -Sometimes when upgrading your Operating System (eg from Ubuntu 17.04 -to Ubuntu 17.10) your virtual environment running modoboa can get -corrupted. Your first response will be to panic but fear not! The -solution is in this document. - -First things first: - -Recover your database password -============================== - -You will need to recover your database password (if using mysql or -postgresql). You will find this in ``/etc/postfix/sql-aliases.cf`` or -any file with ``sql-*.cf`` in the ``/etc/postfix`` directory. - -Make note of this as you will need it when reconfiguring modoboa. - -Reinstall Modoboa -================= - -Start out by backup up your modoboa settings file located in the -``modoboa instance`` directory -(``/srv/modoboa/instance/instance/settings.py`` if you used the -default installer configuration). This contains your current -configuration. - -Next, you want to remove all current modoboa files. - -After doing this, follow the manual installation instructions for :ref:`modoboa_manual_install` **only** as everything should be working properly. - -After this completes, simply restore your backed up settings file to -``/srv/instance/instance/settings.py`` (if you used installer default -configuration). You will then need to reinstall your `extensions -`_. - -You can find which plugins you had in your ``settings.py`` file under -the ``MODOBOA_APPS`` variable. - -Instructions to install extensions can also be `found here -`_. - -Once you have completed this step, you will need to run the following -commands: - -.. sourcecode:: bash - - > (env) $ cd - > (env) $ python manage.py migrate - > (env) $ python manage.py collectstatic - -You will then see a message similar to: - -.. sourcecode:: text - - You have requested to collect static files at the destination - location as specified in your settings: - - /srv/modoboa/instance/sitestatic - - This will overwrite existing files! - Are you sure you want to do this? - - Type 'yes' to continue, or 'no' to cancel: - -You will want to answer ``yes`` here then simply restart the ``uwsgi`` -process with ``service uwsgi restart`` and you should be up and -running again. - -Simply log into your modoboa web panel and verify that your extensions -and webmail box is working. - -Information -=========== - -Rebuild instructions from: -`https://help.pythonanywhere.com/pages/RebuildingVirtualenvs/ -`_ diff --git a/doc/requirements.txt b/doc/requirements.txt deleted file mode 100644 index eb55621b6..000000000 --- a/doc/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -docutils<0.23 -sphinx_rtd_theme diff --git a/doc/rest_api.rst b/doc/rest_api.rst deleted file mode 100644 index e6471b19e..000000000 --- a/doc/rest_api.rst +++ /dev/null @@ -1,39 +0,0 @@ -######## -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:** - -* New API+Docs: *https:///api/schema-v2/swagger/* -* Old API: *http:///api/v1/* - -.. note:: - You need to be logged in for the API docs to show. - -**Examples:** - -* `new example `_ - -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 deleted file mode 100644 index 27aae3c93..000000000 --- a/doc/upgrade.rst +++ /dev/null @@ -1,2157 +0,0 @@ -####### -Upgrade -####### - -Modoboa -******* - -.. note:: - In this doc, ``by default`` means that you used `modoboa installer - `_ to install modoboa - and that your didn't change your configuration. - -.. 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 every case, you will need to -apply the specific actions if the version you are installing requires it, -and then apply the general ones. - -In case you use a dedicated user and/or a virtualenv, do not forget to -use them: - -.. sourcecode:: bash - - > sudo -u -i bash - > source /bin/activate - - -.. _post_upgrade_commands: - -.. note:: - - Check the :ref:`specific_upgrade_instructions` before running the following commands. - -Then, run the following commands: - -.. sourcecode:: bash - - > pip install modoboa== - > cd - > python manage.py migrate - > python manage.py collectstatic - > python manage.py check --deploy - > python manage.py load_initial_data - -Then when everything has been updated, -restart modoboa's services: - -.. sourcecode:: bash - - # sudo systemctl restart uwsgi - # sudo systemctl restart supervisor - -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. - - -Modoboa installer -***************** - -It is important to keep the installer updated because it works on rolling release. -To do that, go to modoboa-installer directory then: - -.. sourcecode:: bash - - > git fetch && git pull - -If some error appears, you may try this: - -.. sourcecode:: bash - - > git reset --hard origin/master - -Extensions -********** - -.. warning:: - Do not open an issue after an upgrade if you have not updated your extensions. - -If a new version is available for an extension you're using, it is -recommanded to install it. It may even be required. -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 -u -i bash - > source /bin/activate - -Then, run the following commands: - -.. sourcecode:: bash - - > pip install == - > cd - > python manage.py migrate - > python manage.py collectstatic - > python manage.py check --deploy - -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. - -Rebuild Virtual Environment -*************************** - -.. include:: rebuild_virtual_env.rst - -.. _specific_upgrade_instructions: - -Specific instructions -********************* - -Version 2.6.1 -============= - -Required changes to :file:`settings.py` ---------------------------------------- - -- Add the following lines to ``LOGGING`` variable: - - .. sourcecode:: python - - 'handlers': { - ... - 'syslog': { - 'class': 'logging.handlers.SysLogHandler', - 'facility': SysLogHandler.LOG_SYSLOG, - 'formatter': 'syslog' - }, - ... - }, - 'loggers': { - ... - 'modoboa.dns': { - 'handlers': ['syslog'], - 'level': 'INFO', - 'propagate': False - }, - ... - } - - -Version 2.6.0 -============= - -New built-in auto-configuration service. - -Required changes to :file:`settings.py` ---------------------------------------- - -- Add the following line to ``MODOBOA_APPS`` variable: - - .. sourcecode:: python - - 'modoboa.autoconfig' - -- Add the following hostnames to ``ALLOWED_HOSTS`` variable: - - .. sourcecode:: python - - 'autoconfig.', - 'autodiscover.', - -- Add the following variable: - - .. sourcecode:: python - - EMAIL_CLIENT_CONNECTION_SETTINGS = { - "imap": { - "HOSTNAME": "", - "SOCKET_TYPE": "SSL", - "PORT": 993, - }, - "smtp": {"HOSTNAME": "", "SOCKET_TYPE": "STARTTLS", "PORT": 587}, - } - -- Remove ``rest_framework.authentication.SessionAuthentication`` from ``REST_FRAMEWORK`` variable: - - .. sourcecode:: python - - REST_FRAMEWORK = { - # Stuff before... - "DEFAULT_AUTHENTICATION_CLASSES": ( - "oauth2_provider.contrib.rest_framework.OAuth2Authentication", - "rest_framework.authentication.TokenAuthentication", - ), - # Stuff after... - } - -Version 2.5.0 -============= - -Amavis plugin integrated into Modoboa core repository. If you are -using Amavis content filter and the quarantine plugin, the following -upgrade instructions, otherwise proceed with regular upgrade -instructions. - -Pre update ----------- - -- If you are using Postegresql (default option with the installer), - run as a root user: - - .. sourcecode:: bash - - > sudo -u postgres -i psql -d "modoboa" -c "UPDATE django_content_type SET app_label='amavis' WHERE app_label='modoboa_amavis'" - > sudo -u postgres -i psql -d "modoboa" -c "UPDATE django_migrations SET app='amavis' WHERE app='modoboa_amavis'" - -- If you are using Mysql, run as a root user: - - .. sourcecode:: bash - - > echo "UPDATE django_content_type SET app_label='amavis' WHERE app_label='modoboa_amavis'" | mysql -u root -p modoboa - > echo "UPDATE django_migrations SET app='amavis' WHERE app='modoboa_amavis'" | mysql -u root -p modoboa - -Required changes to :file:`settings.py` ---------------------------------------- - -- Rename the following extensions in the ``MODOBOA_APPS`` variable: - - - ``modoboa_amavis`` -> ``modoboa.amavis`` - -- Add the following variables: - - .. sourcecode:: python - - DATABASE_ROUTERS = ["modoboa.amavis.dbrouter.AmavisRouter"] - - AMAVIS_DEFAULT_DATABASE_ENCODING = "LATIN1" # or any value matching your database config - -- Remove configuration block related to ``modoboa_amavis`` plugin (these should be at the end of the file) - -Post update ------------ - -- Run the following command:: - - $ pip uninstall modoboa_amavis - -Version 2.4.2 -============= - -Changes to :file:`settings.py` ------------------------------- - -- Make sure ``MODOBOA_APPS`` variable contains the following line: - - .. sourcecode:: python - - 'modoboa.webmail' - - -Version 2.4.0 -============= - -.. warning:: - - The ``modoboa-amavis`` extension has not been migrated into the - core Modoboa package yet. If you are using it, **you cannot install - version 2.4.0 yet**. - -Legacy web interface has been removed and almost all extensions have been -integrated to the core Modoboa package. - -Pre update ----------- - -- If you are using Postegresql (default option with the installer), - run as a root user: - - .. sourcecode:: bash - - > sudo -u postgres -i psql -d "modoboa" -c "UPDATE django_content_type SET app_label='autoreply' WHERE app_label='postfix_autoreply'" - > sudo -u postgres -i psql -d "modoboa" -c "UPDATE django_migrations SET app='autoreply' WHERE app='postfix_autoreply'" - > sudo -u postgres -i psql -d "modoboa" -c "UPDATE django_content_type SET app_label='contacts' WHERE app_label='modoboa_contacts'" - > sudo -u postgres -i psql -d "modoboa" -c "UPDATE django_migrations SET app='contacts' WHERE app='modoboa_contacts'" - > sudo -u postgres -i psql -d "modoboa" -c "UPDATE django_content_type SET app_label='calendars' WHERE app_label='modoboa_radicale'" - > sudo -u postgres -i psql -d "modoboa" -c "UPDATE django_migrations SET app='calendars' WHERE app='modoboa_radicale'" - -- If you are using Mysql, run as a root user: - - .. sourcecode:: bash - - > echo "UPDATE django_content_type SET app_label='autoreply' WHERE app_label='postfix_autoreply'" | mysql -u root -p modoboa - > echo "UPDATE django_migrations SET app='autoreply' WHERE app='postfix_autoreply'" | mysql -u root -p modoboa - > echo "UPDATE django_content_type SET app_label='contacts' WHERE app_label='modoboa_contacts'" | mysql -u root -p modoboa - > echo "UPDATE django_migrations SET app='contacts' WHERE app='modoboa_contacts'" | mysql -u root -p modoboa - > echo "UPDATE django_content_type SET app_label='calendars' WHERE app_label='modoboa_radicale'" | mysql -u root -p modoboa - > echo "UPDATE django_migrations SET app='calendars' WHERE app='modoboa_radicale'" | mysql -u root -p modoboa - -.. warning:: - - MariaDB 10.7+ users might have login issues (see this `discussion `_). - For those impacted, run the followed SQL queries: - - .. sourcecode:: bash - - > echo "ALTER TABLE `oauth2_provider_idtoken` MODIFY `jti` uuid;" | mysql -u root -p modoboa - > echo "ALTER TABLE `oauth2_provider_refreshtoken` MODIFY `token_family` uuid;" | mysql -u root -p modoboa - -Required changes to :file:`settings.py` ---------------------------------------- - -- Rename the following extensions in the ``MODOBOA_APPS`` variable: - - - ``modoboa.postfix_autoreply`` -> ``modoboa.autoreply`` - - ``modoboa_contacts`` -> ``modoboa.contacts`` - - ``modoboa_radicale`` -> ``modoboa.calendars`` - - ``modoboa_webmail`` -> ``modoboa.webmail`` - - ``modoboa_rspamd`` -> ``modoboa.rspamd`` - -- Remove configuration blocks related to ``modoboa_contacts`` and ``modoboa_radicale`` plugins (these should be at the end of the file) - -- Remove ``AjaxLoginRedirect`` from ``MIDDLEWARE`` variable: - - .. sourcecode:: python - - MIDDLEWARE = ( - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.locale.LocaleMiddleware', - 'x_forwarded_for.middleware.XForwardedForMiddleware', - 'corsheaders.middleware.CorsMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'modoboa.core.middleware.LocalConfigMiddleware', - 'modoboa.lib.middleware.CommonExceptionCatcher', - 'modoboa.lib.middleware.RequestCatcherMiddleware', - ) - -- Remove ``NEW_ADMIN_URL`` variable if found - -- Remove ``new_admin_url`` and ``top_notifications`` context processors - -- Remove ``ckeditor`` related apps from ``INSTALLED_APPS`` variable and ``CKEDITOR_*`` settings - -- Remove ``STATICFILE_DIRS`` variable - -Radicale configuration changes ------------------------------ - -You must enable oauth2 authentication in Radicale to make the calendar -and contact feature work. Follow this :ref:`guide `. - -Post update ------------ - -- Run the following command:: - - $ python manage.py load_initial_data - -- Update your :ref:`webserver ` configuration - -- Remove ``autoreply`` service definition from postfix`s :file:`master.cf` file if you were using it - -- Make sure :file:`/etc/uwsgi/sites-enabled/` contains `max-requests=5000` and that `process` is superior or equal to 4. Don't forget to restart uwsgi service after the configuration change. - -- Then proceed with regular upgrade instructions - -Version 2.3.3 -============= - -.. warning:: - - The ``crypt ({CRYPT})`` password scheme has been marked as - deprecated and will be removed from Modoboa starting with version - **2.4.0**. If you are still using this weak scheme, you must change - to something safer **ASAP**. Installations still using this scheme - won't be able to install Modoboa 2.4 and upper... - -Update your :file:`settings.py` file with following content: - -.. sourcecode:: python - - SILENCED_SYSTEM_CHECKS = [ - "security.W019", # modoboa uses iframes to display e-mails - "ckeditor.W001", # CKEditor 4.22.1 warning - ] - -This will silence a `warning sent by django-ckeditor `_. - -Version 2.3.0 -============= - -.. warning:: - - For this particular version, it is really important that you apply - new migrations **AFTER** the following instructions. If you don't, - you'll get into trouble... - -Pre update ----------- - -.. note:: - - To check that you were actually using modoboa-postfix-autoreply - you can check if this command returns something: - - .. sourcecode:: bash - - cat /srv/modoboa/instance/instance/settings.py | grep "modoboa_postfix_autoreply" - -If you were using -`modoboa-postfix-autoreply `_ -extension, you need to perfome a few commands: - -- If you are using Postegresql (default option with the installer), - run as a root user: - - .. sourcecode:: bash - - > sudo -u postgres -i psql -d "modoboa" -c "UPDATE django_content_type SET app_label='postfix_autoreply' WHERE app_label='modoboa_postfix_autoreply'" - > sudo -u postgres -i psql -d "modoboa" -c "UPDATE django_migrations SET app='postfix_autoreply' WHERE app='modoboa_postfix_autoreply'" - -- If you are using Mysql, run as a root user: - - .. sourcecode:: bash - - > echo "UPDATE django_content_type SET app_label='postfix_autoreply' WHERE app_label='modoboa_postfix_autoreply'" | mysql -u root -p modoboa - > echo "UPDATE django_migrations SET app='postfix_autoreply' WHERE app='modoboa_postfix_autoreply'" | mysql -u root -p modoboa - -Required changes to :file:`settings.py` ---------------------------------------- - -Some changes are required to your :file:`settings.py` file. -These changes will not be performed by the installer. -The location of this file is ``/srv/modoboa/instance/instance`` -by default. - -- Append ``'import environ'`` after ``'import os'``: - - .. sourcecode:: python - - import os - import environ - -- Append the following lines after the line starting - with ``'BASE_DIR'``: - - .. sourcecode:: python - - # Build paths inside the project like this: os.path.join(BASE_DIR, ...) - BASE_DIR = os.path.realpath(os.path.dirname(os.path.dirname(__file__))) - env = environ.Env() - environ.Env.read_env(os.path.join(BASE_DIR, '.env')) - -- Add ``oauth2_provider`` and ``corsheaders`` to the ``INSTALLED_APPS`` list: - - .. sourcecode:: python - - INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.sites', - 'django.contrib.staticfiles', - 'reversion', - 'ckeditor', - 'ckeditor_uploader', - 'oauth2_provider', - 'corsheaders', - 'rest_framework', - 'rest_framework.authtoken', - 'drf_spectacular', - 'phonenumber_field', - 'django_otp', - 'django_otp.plugins.otp_totp', - 'django_otp.plugins.otp_static', - 'django_rename_app', - 'django_rq', - ) - -- The ``modoboa-postfix-autoreply`` and ``modoboa-sievefilters`` - plugins have been merged into the core. - - Add ``'modoboa.postfix_autoreply'`` and - ``modoboa.sievefilters`` to ``MODOBOA_APPS``: - - .. sourcecode:: python - - MODOBOA_APPS = ( - 'modoboa', - 'modoboa.core', - 'modoboa.lib', - 'modoboa.admin', - 'modoboa.transport', - 'modoboa.relaydomains', - 'modoboa.limits', - 'modoboa.parameters', - 'modoboa.dnstools', - 'modoboa.policyd', - 'modoboa.maillog', - 'modoboa.dmarc', - 'modoboa.pdfcredentials', - 'modoboa.imap_migration', - 'modoboa.postfix_autoreply', - 'modoboa.sievefilters', - ) - - .. warning:: - Remove any reference to ``'modoboa_postfix_autoreply'`` AND - ``modoboa_sievefilters`` in this same variable. - -- Due to the changes to the authentication flow, you need to replace MIDDLEWARE - with the following: - - .. sourcecode:: python - - MIDDLEWARE = ( - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.locale.LocaleMiddleware', - 'x_forwarded_for.middleware.XForwardedForMiddleware', - 'corsheaders.middleware.CorsMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'modoboa.core.middleware.LocalConfigMiddleware', - 'modoboa.lib.middleware.AjaxLoginRedirect', - 'modoboa.lib.middleware.CommonExceptionCatcher', - 'modoboa.lib.middleware.RequestCatcherMiddleware', - ) - -- Replace - ``'modoboa.core.drf_authentication.JWTAuthenticationWith2FA'`` by - ``'oauth2_provider.contrib.rest_framework.OAuth2Authentication'`` - at the top of the list of ``DEFAULT_AUTHENTICATION_CLASSES`` - (inside ``REST_FRAMEWORK`` section): - - .. sourcecode:: python - - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', - 'rest_framework.authentication.TokenAuthentication', - 'rest_framework.authentication.SessionAuthentication', - ), - -Save your modifications at this point and run the :ref:`post upgrade -commands ` now. - -Then, apply this last modification to your settings: - -- Run the commands indicated :ref:`in the first section ` - then add the following content after ``MEDIA_ROOT``: - - .. sourcecode:: python - - # oAuth2 settings - - OAUTH2_PROVIDER = { - 'OIDC_ENABLED': True, - 'OIDC_RP_INITIATED_LOGOUT_ENABLED': True, - 'OIDC_RP_INITIATED_LOGOUT_ALWAYS_PROMPT': True, - 'OIDC_RSA_PRIVATE_KEY': env.str('OIDC_RSA_PRIVATE_KEY', multiline=True), - 'SCOPES': { - 'openid': 'OpenID Connect scope', - 'read': 'Read scope', - 'write': 'Write scope', - 'introspection': 'Introspect token scope', - }, - 'DEFAULT_SCOPES': ['openid', 'read', 'write'], - } - - # If CORS fail, you might want to try to set it to True - #CORS_ORIGIN_ALLOW_ALL = False - -Docevot configuration changes ------------------------------ - -You must enable oauth2 authentication in Dovecot to make the filters -editor work in the new UI. Follow this :ref:`guide `. - -Post update ------------ - -Run this command to be sure to have everything set. - -.. sourcecode:: bash - - python manage.py modo repair - -You need to set the ``buffer-size`` to ``8192`` in uwsgi config. -Edit the value in ``/etc/uwsgi/apps-available/automx_instance.ini`` -to match at least 8192 or add it if it was not set: - -.. sourcecode:: bash - - buffer-size = 8192 - - -SORBS DNS ---------- - - .. note:: - The installer will take care of that if you use it to upgrade. - - - `SORBS DNS has been deprecated `_. - If you were using them with postfix, you need to update your - configuration by removing any reference to it. For example:: - - # Use some DNSBL - postscreen_dnsbl_sites = - zen.spamhaus.org=127.0.0.[2..11]*3 - bl.spameatingmonkey.net=127.0.0.2*2 - bl.spamcop.net=127.0.0.2 - -Version 2.2.3 -============= - -* Reduced the number of call to doveadm - -You need to setup a new worker : - -1. Create a new supervisord config (``/etc/supervisor/conf.d/modoboa-base-worker.conf`` by default) : - -.. sourcecode:: ini - - [program:modoboa-base-worker] - autostart=true - autorestart=true - command={%python env path%} {% manage.py instance path%} rqworker modoboa - directory={%modoboa home dir%} - user=%{modoboa user} - numprocs=1 - stopsignal=TERM - -``python env path`` : Python executable located in your virtual environment created for modoboa. -You will find it here ``/srv/modoboa/venv/bin/python`` by default. -``manage.py instance path``: Path to manage.py of your modoboa instance. -You will find it here : ``/srv/modoboa/instance/manage.py``by default. -``Modoboa home dir``: Home dir of the user running modooba. -You will find it here ``/srv/modoboa/`` by default. -``modoboa user`` : User managing dkim signing (modoboa by default). - -You can help you with ``/etc/supervisor/conf.d/policyd.conf`` (by default). - -Then restart supervisor. ``#> supervisorctl reread && supervisorctl update`` on Debian. - -2. Update the RQ_QUEUES section bellow the ``#REDIS`` section: - -.. sourcecode:: python - - # RQ - RQ_QUEUES = { - ... - }, - 'modoboa': { - 'HOST': REDIS_HOST, - 'PORT': REDIS_PORT, - 'DB': 0, - }, - } - -3. Add the CACHE section bellow the ``# RQ`` one: - -.. sourcecode:: python - - # CACHE - CACHES = { - "default": { - "BACKEND": 'django.core.cache.backends.redis.RedisCache', - "LOCATION": REDIS_URL - } - } - - -Version 2.2.0 -============= - -.. note:: - If you use the installer to perform the upgrade, you NEED to update it. - See above for instructions. - After updating the installer and modoboa with it, - you only need to edit ``urls.py`` and ``settings.py`` - -* Django has been updated to 4.2LTS. Please upgrade all your extensions alongside modoboa -* Support for Python 3.7 has been dropped, minimum Python version is now 3.8 -* Support for Postgres 11 has been dropped, minimum Postgres version is now 12 - -You need to change the first line in ``urls.py`` and replace `url` with `path` (in -``/srv/modoboa/instance/instance/urls.py`` by default): - -.. sourcecode:: python - - # from django.conf.urls import include, url - from django.urls import include, path - - urlpatterns = [ - path(r'', include('modoboa.urls')), - ] - - -If you use Postgresql, you need to install pyscopg3+: - -.. sourcecode:: bash - - pip install psycopg[binary]>=3.1 - -RQ has been added. This should replace the use of cron jobs in the future. -For now, only ``manage_dkim_keys`` has been migrated. This will make the dkim -key generation asynchronous but the task will be started as soon as the generation -is required. - -Follow these instructions to perform the update in case you used supervisord for the -installation (this apply if you used ``modoboa-installer``): - -1. Edit settings.py (``/srv/modoboa/instance/instance/settings.py`` by default) and add: - -.. sourcecode:: python - - INSTALLED_APPS = ( - ..., - 'django_rq', - ) - -and add the RQ section bellow the ``#REDIS`` section: - -.. sourcecode:: python - - # RQ - RQ_QUEUES = { - 'dkim': { - 'HOST': REDIS_HOST, - 'PORT': REDIS_PORT, - 'DB': 0, - }, - } - -Then by default you will need to restart ``uwsgi`` service (``systemctl restart uwsgi`` on Debian). - -2. Create a new supervisord config (``/etc/supervisor/conf.d/modoboa-worker.conf`` by default) : - -.. sourcecode:: ini - - [program:modoboa-worker] - autostart=true - autorestart=true - command={%python env path%} {% manage.py instance path%} rqworker dkim - directory={%modoboa home dir%} - user=%{dkim manager user} - numprocs=1 - stopsignal=TERM - -``python env path`` : Python executable located in your virtual environment created for modoboa. -You will find it here ``/srv/modoboa/venv/bin/python`` by default. -``manage.py instance path``: Path to manage.py of your modoboa instance. -You will find it here : ``/srv/modoboa/instance/manage.py``by default. -``Modoboa home dir``: Home dir of the user running modooba. -You will find it here ``/srv/modoboa/`` by default. -``dkim manager user`` : User managing dkim signing (opendkim by default). - -You can help you with ``/etc/supervisor/conf.d/policyd.conf`` (by default). - -Then restart supervisor. ``#> supervisorctl reread && supervisorctl update`` on Debian. - -Admins now have the option to setup a send-only mailbox. - -Send-only mailboxes do not have access to IMAP. -You need to change your dovecot configuration to enable it. - -.. note:: - - modoboa-webmail may not work with send-only user for now. - -If you use ``Postgres``: -Change ``user_query`` and ``password_query`` in ``/etc/dovecot/dovecot-sql.conf.ext``:: - - user_query = SELECT '%{home_dir}/%%d/%%n' AS home, %mailboxes_owner_uid as uid, %mailboxes_owner_gid as gid, '*:bytes=' || mb.quota || 'M' AS quota_rule FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id INNER JOIN core_user u ON u.id=mb.user_id WHERE (mb.is_send_only IS NOT TRUE OR '%s' NOT IN ('imap', 'pop3', 'lmtp')) AND mb.address='%%n' AND dom.name='%%d' - - password_query = SELECT email AS user, password, '%{home_dir}/%%d/%%n' AS userdb_home, %mailboxes_owner_uid AS userdb_uid, %mailboxes_owner_gid AS userdb_gid, CONCAT('*:bytes=', mb.quota, 'M') AS userdb_quota_rule FROM core_user u INNER JOIN admin_mailbox mb ON u.id=mb.user_id INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE (mb.is_send_only IS NOT TRUE OR '%s' NOT IN ('imap', 'pop3')) AND email='%%u' AND is_active AND dom.enabled - - -You basically simply need to add ``(mb.is_send_only IS NOT TRUE OR '%s' NOT IN ('imap', 'pop3', 'lmtp')) AND`` for ``user_query`` after ``WHERE`` and ``(mb.is_send_only IS NOT TRUE OR '%s' NOT IN ('imap', 'pop3')) AND`` for ``password_query`` after ``WHERE``. - - -If you use ``MySQL``: -Change ``user_query`` and ``password_query`` in ``/etc/dovecot/dovecot-sql-master.ext``:: - - user_query = SELECT '%{home_dir}/%%d/%%n' AS home, %mailboxes_owner_uid as uid, %mailboxes_owner_gid as gid, CONCAT('*:bytes=', mb.quota, 'M') AS quota_rule FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id INNER JOIN core_user u ON u.id=mb.user_id WHERE (mb.is_send_only=0 OR '%s' NOT IN ('imap', 'pop3', 'lmtp')) AND mb.address='%%n' AND dom.name='%%d' - - password_query = SELECT email AS user, password, '%{home_dir}/%%d/%%n' AS userdb_home, %mailboxes_owner_uid AS userdb_uid, %mailboxes_owner_gid AS userdb_gid, CONCAT('*:bytes=', mb.quota, 'M') AS userdb_quota_rule FROM core_user u INNER JOIN admin_mailbox mb ON u.id=mb.user_id INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE (mb.is_send_only=0 OR '%s' NOT IN ('imap', 'pop3')) AND u.email='%%u' AND u.is_active=1 AND dom.enabled=1 - -You basically simply need to add ``(mb.is_send_only=0 OR '%s' NOT IN ('imap', 'pop3', 'lmtp')) AND`` for ``user_query`` after ``WHERE`` and ``(mb.is_send_only=0 OR '%s' NOT IN ('imap', 'pop3'))`` for ``password_query`` after ``WHERE``. - -Version 2.1.0 -============= - -.. warning:: - - For this particular version, it is really important that you apply - new migrations **AFTER** the following instructions. If you don't, - you'll get into trouble... - -The ``modoboa-dmarc``, ``modoboa-pdfcredentials`` and ``modoboa-imapmigration`` -plugins have been merged into the core. - -Add ``'django_rename_app,'`` To ``INSTALLED_APPS``: - -.. sourcecode:: python - - INSTALLED_APPS = ( - ..., - 'django_rename_app', - ) - -Add ``'modoboa.dmarc'``, ``'modoboa.pdfcredentials'`` and ``'modoboa.imap_migration'`` -to ``MODOBOA_APPS``: - -.. sourcecode:: python - - MODOBOA_APPS = ( - 'modoboa', - 'modoboa.core', - 'modoboa.lib', - 'modoboa.admin', - 'modoboa.transport', - 'modoboa.relaydomains', - 'modoboa.limits', - 'modoboa.parameters', - 'modoboa.dnstools', - 'modoboa.policyd', - 'modoboa.maillog', - 'modoboa.dmarc', - 'modoboa.pdfcredentials', - 'modoboa.imap_migration', - ) - -And remove any reference to ``'modoboa_dmarc'``, ``'modoboa_pdfcredentials'`` or ``'modoboa_imap_migration'`` -in this same variable. - -You need to add ``'modoboa.imap_migration.auth_backends.IMAPBackend',`` at the end of ``AUTHENTICATION_BACKENDS``: - -.. sourcecode:: python - - AUTHENTICATION_BACKENDS = ( - 'django.contrib.auth.backends.ModelBackend', - 'modoboa.imap_migration.auth_backends.IMAPBackend', - ) - -.. note:: - It won't affect login if you don't use ``imap_migration`` feature. - It is therefor highly recommended to add this authentication backend. - -After upgrading modoboa, run the following commands from your virtual environment: - -.. sourcecode:: bash - - > python manage.py rename_app modoboa_dmarc dmarc - > python manage.py rename_app modoboa_imap_migration imap_migration - - -Version 2.0.4 -============= - -The following modifications must be applied to the :file:`settings.py` file: - -* Add ``'modoboa.core.context_processors.new_admin_url',`` at the end of `context_processors` list: - -.. sourcecode:: python - - TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.template.context_processors.i18n', - 'django.template.context_processors.media', - 'django.template.context_processors.static', - 'django.template.context_processors.tz', - 'django.contrib.messages.context_processors.messages', - 'modoboa.core.context_processors.top_notifications', - 'modoboa.core.context_processors.new_admin_url', - ], - 'debug': False, - }, - }, - ] - - -* Add the following variable: - -.. sourcecode:: python - - PID_FILE_STORAGE_PATH = '/var/run' - -* Update ``LOGGING`` variable to define an address for ``syslog-auth`` handler: - -.. sourcecode:: python - - 'syslog-auth': { - 'class': 'logging.handlers.SysLogHandler', - 'facility': SysLogHandler.LOG_AUTH, - 'formatter': 'syslog', - 'address': '/dev/log' - }, - - -* You now have the possibility to customize the url of the new-admin interface. - To do so please head up to :ref:`the custom configuration chapter ` (advanced user). - -* Add ``DEFAULT_THROTTLE_RATES`` to ``REST_FRAMEWORK``: - -.. sourcecode:: python - - REST_FRAMEWORK = { - 'DEFAULT_THROTTLE_RATES': { - 'user': '300/minute', - 'ddos': '5/second', - 'ddos_lesser': '200/minute', - 'login': '10/minute', - 'password_recovery_request': '12/hour', - 'password_recovery_totp_check': '25/hour', - 'password_recovery_apply': '25/hour' - }, - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'modoboa.core.drf_authentication.JWTAuthenticationWith2FA', - 'rest_framework.authentication.TokenAuthentication', - 'rest_framework.authentication.SessionAuthentication', - ), - 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', - 'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning', - } - -* You can edit the ``DEFAULT_THROTTLE_RATES`` to whatever value suits you. - - `user` is for every endpoint, it is per user or per ip if not logged. - - `ddos` is per api endpoint and per user or per ip if not logged. - - `ddos_lesser` is for per api endpoint and per user or per ip if not logged. This is for api endpoint that are lighter. - - `login` the number of time an ip can attempt to log. The counter will reset on login success. - - `password_` is for the recovery, it is divided per step in the recovery process. - - -Version 2.0.3 -============= - -Update the new following setting in the :file:`settings.py` file: - -.. sourcecode:: python - - DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' - - -Version 2.0.0 -============= - -Add ``drf_spectacular`` and ``phonenumber_field`` to ``INSTALLED_APPS`` -in the :file:`settings.py` file, as follows: - -.. sourcecode:: python - - INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.sites', - 'django.contrib.staticfiles', - 'reversion', - 'ckeditor', - 'ckeditor_uploader', - 'rest_framework', - 'rest_framework.authtoken', - 'drf_spectacular', - 'phonenumber_field', - 'django_otp', - 'django_otp.plugins.otp_totp', - 'django_otp.plugins.otp_static', - ) - -Modify the ``REST_FRAMEWORK`` setting as follows: - -.. sourcecode:: python - - REST_FRAMEWORK = { - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'modoboa.core.drf_authentication.JWTAuthenticationWith2FA', - 'rest_framework.authentication.TokenAuthentication', - 'rest_framework.authentication.SessionAuthentication', - ), - 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', - 'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning', - } - -Add the new following settings: - -.. sourcecode:: python - - SPECTACULAR_SETTINGS = { - 'SCHEMA_PATH_PREFIX': r'/api/v[0-9]', - 'TITLE': 'Modoboa API', - 'VERSION': None, - 'SERVE_PERMISSIONS': ['rest_framework.permissions.IsAuthenticated'], - } - - PHONENUMBER_DB_FORMAT = 'INTERNATIONAL' - - DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' - -Migration issue for Postgres/OpenDKIM users -------------------------------------------- - -The `migration will probably fail `_ because of the -additional view created for OpenDKIM. - -To make it work, you first need to drop the view: - -.. sourcecode:: bash - - $ sudo su - postgres - $ psql - psql (12.10 (Ubuntu 12.10-0ubuntu0.20.04.1)) - Type "help" for help. - - postgres=# \c modoboa - You are now connected to database "modoboa" as user "postgres". - modoboa-# \d+ dkim - View "public.dkim" - Column | Type | Collation | Nullable | Default | Storage | Description - ------------------+------------------------+-----------+----------+---------+----------+------------- - id | integer | | | | plain | - domain_name | character varying(100) | | | | extended | - private_key_path | character varying(254) | | | | extended | - selector | character varying(30) | | | | extended | - View definition: - SELECT admin_domain.id, - admin_domain.name AS domain_name, - admin_domain.dkim_private_key_path AS private_key_path, - admin_domain.dkim_key_selector AS selector - FROM admin_domain - WHERE admin_domain.enable_dkim; - - modoboa=# drop view dkim; - DROP VIEW - -Then, run the migration as usual: - -.. sourcecode:: bash - - python manage.py migrate - -Finally, recreate the view: - -.. sourcecode:: bash - - modoboa=# CREATE OR REPLACE VIEW dkim AS - modoboa-# SELECT admin_domain.id, - modoboa-# admin_domain.name AS domain_name, - modoboa-# admin_domain.dkim_private_key_path AS private_key_path, - modoboa-# admin_domain.dkim_key_selector AS selector - modoboa-# FROM admin_domain - modoboa-# WHERE admin_domain.enable_dkim; - CREATE VIEW - modoboa=# grant select on dkim to opendkim; - GRANT - -New admin interface -------------------- - -This new release brings a new admin interface written with Vue.js framework. -It is a work in progress and all features are not yet implemented - i.e. -extensions integration - but you could give it a try. It uses a new API -version but the old one is still available. - -You will need to copy the frontend files in the folder you specified in your -web server configuration. If you used the installer, the folder should be -``/srv/modoboa/instance/frontend``: - -.. sourcecode:: bash - - mkdir /srv/modoboa/instance/frontend - cp -r /srv/modoboa/env/lib/pythonX.X/site-packages/modoboa/frontend_dist/* /srv/modoboa/instance/frontend - -Then, edit the :file:`/srv/modoboa/instance/frontend/config.json` -and update the ``API_BASE_URL`` setting according to the hostname of your server: - -.. sourcecode:: json - - { - "API_BASE_URL": "https:///api/v2" - } - -Finally, update the configuration of your web server to serve the frontend -files. For NGINX, you should add the following in the ``server`` block: - -.. sourcecode:: nginx - - location ^~ /new-admin { - alias /srv/modoboa/instance/frontend/; - index index.html; - - expires -1; - add_header Pragma "no-cache"; - add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"; - - try_files $uri $uri/ /index.html = 404; - } - -Version 1.17.0 -============== - -Modoboa now supports Two-Factor authentication using TOTP -applications. - -To enable it, install the following new requirement in your -virtualenv: - -.. sourcecode:: bash - - (env)> pip install django-otp qrcode - -Then, open the :file:`settings.py` file and add ``django_otp`` -packages to ``INSTALLED_APPS``: - -.. sourcecode:: python - - INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.sites', - 'django.contrib.staticfiles', - 'reversion', - 'ckeditor', - 'ckeditor_uploader', - 'rest_framework', - 'rest_framework.authtoken', - 'django_otp', - 'django_otp.plugins.otp_totp', - 'django_otp.plugins.otp_static', - ) - -Add new middlewares to ``MIDDLEWARE``. It has to be after the SessionMiddleware and before the CommonMiddleware: - -.. sourcecode:: python - - MIDDLEWARE = ( - 'x_forwarded_for.middleware.XForwardedForMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.locale.LocaleMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django_otp.middleware.OTPMiddleware', - 'modoboa.core.middleware.TwoFAMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'modoboa.core.middleware.LocalConfigMiddleware', - 'modoboa.lib.middleware.AjaxLoginRedirect', - 'modoboa.lib.middleware.CommonExceptionCatcher', - 'modoboa.lib.middleware.RequestCatcherMiddleware', - ) - -And add the following new setting: - -.. sourcecode:: python - - # 2FA - - OTP_TOTP_ISSUER = "" - - -Version 1.16.0 -============== - -A new :ref:`policy daemon ` has been added. - -Make sure to have a Redis instance running on your server. - -Add ``'modoboa.policyd'`` to ``MODOBOA_APPS``: - -.. sourcecode:: python - - MODOBOA_APPS = ( - 'modoboa', - 'modoboa.core', - 'modoboa.lib', - 'modoboa.admin', - 'modoboa.transport', - 'modoboa.relaydomains', - 'modoboa.limits', - 'modoboa.parameters', - 'modoboa.dnstools', - 'modoboa.policyd' - ) - -Add the following settings to your ``settings.py`` file: - -.. sourcecode:: python - - REDIS_HOST = '' - REDIS_PORT = 6379 - REDIS_QUOTA_DB = 0 - REDIS_URL = 'redis://{}:{}/{}'.format(REDIS_HOST, REDIS_PORT, REDIS_QUOTA_DB) - -Or, if Redis listen on unix socket and you are not using the Modoboa installer: - -.. sourcecode:: python - - REDIS_HOST = '/path/to/redis/socket' - REDIS_PORT = 6379 - REDIS_QUOTA_DB = 0 - REDIS_URL = 'unix://{}?db={}'.format(REDIS_HOST, REDIS_QUOTA_DB) - -Once done, you can start the policy daemon using the following commands: - -.. sourcecode:: bash - - > python manage.py policy_daemon - -Don't forget to configure :ref:`_policyd_config ` if you want -to use this feature. - -The ``modoboa-stats`` plugin has been merged into the core. - -Add ``'modoboa.maillog'`` to ``MODOBOA_APPS``: - -.. sourcecode:: python - - MODOBOA_APPS = ( - 'modoboa', - 'modoboa.core', - 'modoboa.lib', - 'modoboa.admin', - 'modoboa.transport', - 'modoboa.relaydomains', - 'modoboa.limits', - 'modoboa.parameters', - 'modoboa.dnstools', - 'modoboa.policyd', - 'modoboa.maillog', - ) - -And remove any reference to ``modoboa_stats`` in this same variable. - -Version 1.15.0 -============== - -This version drops Python 2 support so don't forget to update all the -extensions you use. - -.. warning:: - - If you upgrade an existing python 2 installation, you will need to - create a new Python 3 virtual environment. You can remove the - existing virtual environment and replace it by the new one so you - won't have to modify your configuration files. - -Add the following new setting: - -.. sourcecode:: python - - DISABLE_DASHBOARD_EXTERNAL_QUERIES = False - -Reload uwsgi/gunicorn/apache depending on your setup. - -Finally, Make sure to use root privileges and run the following -command: - -.. sourcecode:: bash - - > python manage.py generate_postfix_maps --destdir - -Then, reload postfix. - - -Version 1.14.0 -============== - -This release introduces an optional LDAP synchronization process. If -you want to use it, please follow the :ref:`dedicated procedure `. - -Version 1.13.1 -============== - -Upgrade postfix maps files as follows: - -.. sourcecode:: bash - - > python manage.py generate_postfix_maps --destdir --force-overwrite - - -Version 1.13.0 -============== - -Add ``'modoboa.dnstools'`` to ``MODOBOA_APPS``: - -.. sourcecode:: python - - MODOBOA_APPS = ( - 'modoboa', - 'modoboa.core', - 'modoboa.lib', - 'modoboa.admin', - 'modoboa.transport', - 'modoboa.relaydomains', - 'modoboa.limits', - 'modoboa.parameters', - 'modoboa.dnstools', - ) - -Add the following new settings: - -.. sourcecode:: python - - CSRF_COOKIE_SECURE = True - SESSION_COOKIE_SECURE = True - -modoboa-postfix-autoreply 1.5.0 -=============================== - -Edit the :file:`/etc/postfix/main.cf` file and remove the -``sql-autoreplies-transport.cf`` map from the ``transport_maps`` if -present. Remove the corresponding ``proxy_read_maps`` entry if relevant. - -Reload postfix. - -Version 1.10.0 -============== - -.. warning:: - - Upgrade installed extensions BEFORE running ``check`` or - ``migrate`` commands. - -Upgrade all your installed plugins to the following versions: - -.. warning:: - - If you use the amavis plugin, make sure to include its - configuration as follows into :file:`settings.py`: - - .. sourcecode:: python - - from modoboa_amavis import settings as modoboa_amavis_settings - modoboa_amavis_settings.apply(globals()) - -+------------------------------+------------------------------+ -|Name |Version | -+==============================+==============================+ -|modoboa-amavis |1.2.0 | -+------------------------------+------------------------------+ -|modoboa-contacts |0.5.0 | -+------------------------------+------------------------------+ -|modoboa-dmarc |1.1.0 | -+------------------------------+------------------------------+ -|modoboa-imap-migration |1.2.0 | -+------------------------------+------------------------------+ -|modoboa-pdfcredentials |1.3.0 | -+------------------------------+------------------------------+ -|modoboa-postfix-autoreply |1.4.0 | -+------------------------------+------------------------------+ -|modoboa-radicale |1.2.0 | -+------------------------------+------------------------------+ -|modoboa-sievefilters |1.4.0 | -+------------------------------+------------------------------+ -|modoboa-stats |1.4.0 | -+------------------------------+------------------------------+ -|modoboa-webmail |1.4.0 | -+------------------------------+------------------------------+ - -Edit the :file:`settings.py` file and apply the following modifications. - -Add ``'modoboa.transport'`` to ``MODOBOA_APPS``: - -.. sourcecode:: python - - MODOBOA_APPS = ( - 'modoboa', - 'modoboa.core', - 'modoboa.lib', - 'modoboa.admin', - 'modoboa.transport', - 'modoboa.relaydomains', - 'modoboa.limits', - 'modoboa.parameters', - ) - -Replace the following line: - -.. sourcecode:: python - - MIDDLEWARE_CLASSES = ( - -by: - -.. sourcecode:: python - - MIDDLEWARE = ( - -Update postfix map files as follows: - -.. sourcecode:: bash - - > rm -f /modoboa-postfix-maps.chk - > python manage.py generate_postfix_maps --force --destdir - -Then, modify postfix's configuration as follows:: - - smtpd_sender_login_maps = - :/sql-sender-login-map.cf - - transport_maps = - :/sql-transport.cf - :/sql-spliteddomains-transport.cf - # other map files... - -Replace ```` and ```` by your values. - -If ``transport_maps`` contains ``sql-relaydomains-transport.cf``, remove it. - -.. warning:: - - If you make use of postfix's `proxymap server - `_, you must also update - the ``proxy_read_maps`` setting. - -Reload postfix. - -Add the following cron job in order to generate DKIM keys:: - - # Generate DKIM keys (they will belong to the user running this job) - * * * * * root $PYTHON $INSTANCE/manage.py modo manage_dkim_keys - -Version 1.9.0 -============= - -If you want to manage inactive accounts, look at :ref:`inactive_accounts`. - -Version 1.8.3 -============= - -Edit the :file:`settings.py` file and replace the following line: - -.. sourcecode:: python - - BASE_DIR = os.path.dirname(os.path.dirname(__file__)) - -by: - -.. sourcecode:: python - - BASE_DIR = os.path.realpath(os.path.dirname(os.path.dirname(__file__))) - -Version 1.8.0 -============= - -Modoboa now relies on `Django's builtin password validation system -`_ -to validate user passwords, instead of ``django-passwords``. - -Remove ``django-passwords`` from your system: - -.. sourcecode:: bash - - > sudo -u -i bash - > source /bin/activate - > pip uninstall django-passwords - -Edit the :file:`settings.py` file and remove the following content: - -.. sourcecode:: python - - # django-passwords - - PASSWORD_MIN_LENGTH = 8 - - PASSWORD_COMPLEXITY = { - "UPPER": 1, - "LOWER": 1, - "DIGITS": 1 - } - -Add the following lines: - -.. sourcecode:: python - - # Password validation rules - AUTH_PASSWORD_VALIDATORS = [ - { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', - }, - { - 'NAME': 'modoboa.core.password_validation.ComplexityValidator', - 'OPTIONS': { - 'upper': 1, - 'lower': 1, - 'digits': 1, - 'specials': 0 - } - }, - ] - -Version 1.7.2 -============= - -API documentation has evolved (because of the upgrade to Django Rest -Framework 3.6) and CKeditor is now embedded by default (thanks to the -``django-ckeditor`` package). Some configuration changes are -required. - -Edit your :file:`settings.py` file and apply the following modifications: - -* Update the ``INSTALLED_APPS`` variable as follows: - -.. sourcecode:: python - - INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.sites', - 'django.contrib.staticfiles', - 'reversion', - 'ckeditor', - 'ckeditor_uploader', - 'rest_framework', - 'rest_framework.authtoken', - ) - -* Update the ``REST_FRAMEWORK`` variable as follows: - -.. sourcecode:: python - - REST_FRAMEWORK = { - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework.authentication.TokenAuthentication', - 'rest_framework.authentication.SessionAuthentication', - ), - } - -* Remove the ``SWAGGER_SETTINGS`` variable - -* Add the following content - -.. sourcecode:: python - - # CKeditor - - CKEDITOR_UPLOAD_PATH = "uploads/" - - CKEDITOR_IMAGE_BACKEND = "pillow" - - CKEDITOR_RESTRICT_BY_USER = True - - CKEDITOR_BROWSE_SHOW_DIRS = True - - CKEDITOR_ALLOW_NONIMAGE_FILES = False - - CKEDITOR_CONFIGS = { - 'default': { - 'allowedContent': True, - 'toolbar': 'Modoboa', - 'width': None, - 'toolbar_Modoboa': [ - ['Bold', 'Italic', 'Underline'], - ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'], - ['BidiLtr', 'BidiRtl', 'Language'], - ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent'], - ['Undo', 'Redo'], - ['Link', 'Unlink', 'Anchor', '-', 'Smiley'], - ['TextColor', 'BGColor', '-', 'Source'], - ['Font', 'FontSize'], - ['Image', ], - ['SpellChecker'] - ], - }, - } - -Don't forget to run the following command: - -.. sourcecode:: bash - - > python manage.py collectstatic - - -Version 1.7.1 -============= - -If you used 1.7.0 for a fresh installation, please run the following commands: - -.. sourcecode:: bash - - > sudo -u -i bash - > source /bin/activate - > cd - > python manage.py load_initial_data - -Version 1.7.0 -============= - -This version requires Django >= 1.10 so you need to make some -modifications. It also brings internal API changes which are not -backward compatible so installed extensions must be upgraded too. - -First of all, deactivate all installed extensions (edit the -:file:`settings.py` file and comment the corresponding lines in -``MODOBOA_APPS``). - -Edit the :file:`urls.py` file of your local instance and replace its -content by the following one: - -.. sourcecode:: python - - from django.conf.urls import include, url - - urlpatterns = [ - url(r'', include('modoboa.urls')), - ] - -Edit the :file:`settings.py` and apply the following changes: - -* Add ``'modoboa.parameters'`` to ``MODOBOA_APPS``: - -.. sourcecode:: python - - MODOBOA_APPS = ( - 'modoboa', - 'modoboa.core', - 'modoboa.lib', - 'modoboa.admin', - 'modoboa.relaydomains', - 'modoboa.limits', - 'modoboa.parameters', - # Modoboa extensions here. - ) - -* Add ``'modoboa.core.middleware.LocalConfigMiddleware'`` to ``MIDDLEWARE_CLASSES``: - -.. sourcecode:: python - - MIDDLEWARE_CLASSES = ( - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.locale.LocaleMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'modoboa.core.middleware.LocalConfigMiddleware', - 'modoboa.lib.middleware.AjaxLoginRedirect', - 'modoboa.lib.middleware.CommonExceptionCatcher', - 'modoboa.lib.middleware.RequestCatcherMiddleware', - ) - -* Modoboa used to provide a custom authentication backend - (``modoboa.lib.authbackends.SimpleBackend``) but it has been - removed. Replace it as follows: - -.. sourcecode:: python - - AUTHENTICATION_BACKENDS = ( - # Other backends before... - 'django.contrib.auth.backends.ModelBackend', - ) - -* Remove ``TEMPLATE_CONTEXT_PROCESSORS`` and replace it by: - -.. sourcecode:: python - - TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.template.context_processors.i18n', - 'django.template.context_processors.media', - 'django.template.context_processors.static', - 'django.template.context_processors.tz', - 'django.contrib.messages.context_processors.messages', - 'modoboa.core.context_processors.top_notifications', - ], - 'debug': False, - }, - }, - ] - -Run the following commands (load virtualenv if you use one): - -.. sourcecode:: bash - - > sudo -u -i bash - > source /bin/activate - > cd - > python manage.py migrate - > python manage.py collectstatic - -Finally, upgrade your extensions and reactivate them. - -+------------------------------+------------------------------+ -|Name |Version | -+==============================+==============================+ -|modoboa-amavis |1.1.0 | -+------------------------------+------------------------------+ -|modoboa-dmarc |1.0.0 | -+------------------------------+------------------------------+ -|modoboa-imap-migration |1.1.0 | -+------------------------------+------------------------------+ -|modoboa-pdfcredentials |1.1.0 | -+------------------------------+------------------------------+ -|modoboa-postfix-autoreply |1.2.0 | -+------------------------------+------------------------------+ -|modoboa-radicale |1.1.0 | -+------------------------------+------------------------------+ -|modoboa-sievefilters |1.1.0 | -+------------------------------+------------------------------+ -|modoboa-stats |1.1.0 | -+------------------------------+------------------------------+ -|modoboa-webmail |1.1.0 | -+------------------------------+------------------------------+ - -Command line shortcuts: - -.. sourcecode:: bash - - $ pip install modoboa-amavis==1.1.0 - $ pip install modoboa-dmarc==1.0.0 - $ pip install modoboa-imap-migration==1.1.0 - $ pip install modoboa-pdfcredentials==1.1.0 - $ pip install modoboa-postfix-autoreply==1.2.0 - $ pip install modoboa-radicale==1.1.0 - $ pip install modoboa-sievefilters==1.1.0 - $ pip install modoboa-stats==1.1.0 - $ pip install modoboa-webmail==1.1.0 - -And please make sure you use the latest version of the -``django-versionfield2`` package: - -.. sourcecode:: bash - - $ pip install -U django-versionfield2 - -Notes about quota changes and resellers ---------------------------------------- - -Reseller users now have a quota option in Resources tab. This is the quota -that a reseller can share between all its domains. - -There are two quotas for a domain in the new version: - -1. Quota & -2. Default mailbox quota. - -[1]. Quota: quota shared between mailboxes -This quota is shared between all the mailboxes of this domain. This -value cannot exceed reseller's quota and hence cannot be 0(unlimited) -if reseller has finite quota. - -[2]. Default mailbox quota: default quota applied to mailboxes -This quota is the default quota applied to new mailboxes. This value -cannot exceed Quota[1] and hence cannot be 0(unlimited) if Quota[1] is -finite. - -Version 1.6.1 -============= - -First of all, update postfix map files as follows: - -.. sourcecode:: bash - - > python manage.py generate_postfix_maps --destdir --force-overwrite - -Then, modify postfix's configuration as follows:: - - smtpd_sender_login_maps = - :/sql-sender-login-mailboxes.cf - :/sql-sender-login-aliases.cf - :/sql-sender-login-mailboxes-extra.cf - -Replace ```` and ```` by your values. - -Finally, reload postfix. - -This release also deprecates some internal functions. As a result, -several extensions has been updated to maintain the compatibility. If -you enabled the notification service, you'll find the list of -available updates directly in your Modoboa console. - -For the others, here is the list: - -+------------------------------+------------------------------+ -|Name |Version | -+==============================+==============================+ -|modoboa-amavis |1.0.10 | -+------------------------------+------------------------------+ -|modoboa-postfix-autoreply |1.1.7 | -+------------------------------+------------------------------+ -|modoboa-radicale |1.0.5 | -+------------------------------+------------------------------+ -|modoboa-stats |1.0.9 | -+------------------------------+------------------------------+ - -Command line shortcut: - -.. sourcecode:: bash - - $ pip install modoboa-amavis==1.0.10 - $ pip install modoboa-postfix-autoreply==1.1.7 - $ pip install modoboa-radicale==1.0.5 - $ pip install modoboa-stats==1.0.9 - - -Version 1.6.0 -============= - -.. warning:: - - You have to upgrade extensions due to `core.User` model attribute change (`user.group` to `user.role`). - Otherwise, you will have an internal error after upgrade. - In particular: `modoboa-amavisd `_, `modoboa-stats `_, `modoboa-postfix-autoreply `_ are concerned. - -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 know if one the -domains you manage is listed or not. To activate it, add the -following line to your crontab:: - - */30 * * * * python /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 * * * * python /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/' - -Finally, it is now possible to declare additional sender addresses on -a per-account basis. You need to update your postfix configuration in -order to use this functionality. Just edit the :file:`main.cf` file -and change the following parameter:: - - smtpd_sender_login_maps = - :/etc/postfix/sql-sender-login-mailboxes.cf - :/etc/postfix/sql-sender-login-aliases.cf - :/etc/postfix/sql-sender-login-mailboxes-extra.cf - -Version 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', - ] - -Version 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 - -Version 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 - } - - -Version 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 - } - } - -Version 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 - -Version 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.