docs: migrate documentation from sphinx to vitepress

This commit is contained in:
Christophe Chauvet
2026-01-13 17:41:31 +01:00
parent 062d2ccb62
commit d7b0a149a8
30 changed files with 9390 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
on:
push:
branches: [ master ]
paths-ignore:
- 'modoboa/**'
- 'frontend/**'
- 'doc/**'
pull_request:
branches: [ master ]
paths-ignore:
- 'modoboa/**'
- 'frontend/**'
- 'doc/**'
jobs:
cache-and-install:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
version: 10
cache: true
- name: Install dependencies
run: pnpm install
- name: Build documentation
run: pnpm run build
+2
View File
@@ -10,12 +10,14 @@ on:
- 'modoboa/**.po'
- 'frontend/**'
- 'doc/**'
- 'doc-ng/**'
pull_request:
branches: [ master ]
paths-ignore:
- 'modoboa/**.po'
- 'frontend/**'
- 'doc/**'
- 'doc-ng/**'
release:
branches: [ master ]
types: [ published ]
+1
View File
@@ -24,6 +24,7 @@ node_modules
/frontend/webpack-stats.json
/frontend/src/translations.json
/frontend/.__mf__temp/
.vitepress/
# TOX stuff
test_project/modoboa.db
+466
View File
@@ -0,0 +1,466 @@
# 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.
## General parameters {#admin-params}
The *admin* application exposes several parameters, they are presented
below:
| Name | Tab | Description | Default Value |
| :-: | :-: | :-- | :-: |
| Authentication type | General | The backend used for authentication | Local |
| Default password scheme | General passwords | Scheme used to crypt mailbox | sha512crypt |
| Rounds | General | Number of rounds (only used by [sha256crypt] and [sha512crypt]). Must be between 1000 and 999999999, inclusive. | 70000 |
| Secret key | General | A key used to encrypt users password in sessions | random value |
| Sender address | General | Email address used to send notifications. | |
| Enable communication | General | Enable communication with Modoboa public API | yes |
| Check new versions | General | Automatically checks if a newer version is available | yes |
| Send statistics | General | Send statistics to Modoboa public API (counters and used extensions) | yes |
| Top notifications check interval | General | Interval between two top notification checks (in seconds) | 30 |
| Maximum log record age | General | The maximum age in days of a log record | 365 |
| Items per page | General | Number of displayed items per page | 30 |
| Default top redirection | General | The default redirection used when no application is specified | userprefs |
| Enable MX checks | Admin | Check that every domain has a valid MX record | yes |
| 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 major DNSBL providers | yes |
| DKIM keys storage directory | Admin | Path to a directory where DKIM generated keys will be stored | |
| Default DKIM key length | Admin | The default size (in bits) for new keys | 2048 |
| Handle mailboxes on filesystem | Admin | Rename or remove mailboxes on the filesystem when they get renamed or removed within Modoboa | no |
| Mailboxes owner | Admin | The UNIX account who owns mailboxes on the filesystem | vmail |
| Default domain quota | Admin | Default quota (in MB) applied to freshly created domains with no value specified. A value of 0 means no quota. | 0 |
| Automatic account removal | Admin | When a mailbox is removed, also remove the associated account | no |
| Automatic domain/mailbox creation | Admin | Create a domain and a mailbox when an account is automatically created | yes |
::: 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 `settings.py` file and add a `DOVECOT_SUPPORTED_SCHEMES`
variable with the output of the command:
```shell
$ doveadm pw -l
```
:::
::: info
If you are not familiar with virtual domain hosting, you should take a look at
[postfix's documentation](http://www.postfix.org/VIRTUAL_README.html).
This [How to](https://help.ubuntu.com/community/PostfixVirtualMailBoxClamSmtpHowto)
also contains useful information.
:::
::: tip
A random secret key will be generated each time the *Parameters* page is
refreshed and until you save parameters at least once.
:::
::: info
Specific LDAP parameters are also available, see `LDAP
authentication <ldap_auth>`.
:::
### 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
## 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 `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:
``` python
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 `config.json` file located in this very same directory and add the following variables:
```json
{
"MENU_LOGO_PATH": "/cusrtom_logo.png", // [!code focus]
"CREATION_FORM_LOGO_PATH": "/custom_logo2.png" // [!code focus]
}
```
### Host configuration
::: tip
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 `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 `/etc/sudoers` file and add the following inside:
```txt
<user_that_runs_modoboa> ALL=(<mailboxes owner>) NOPASSWD: ALL
```
Replace values between `<>` by the ones you use.
### Time zone and language {#timezone_lang}
Modoboa is available in many languages.
To specify the default language to use, edit the `settings.py` file
and modify the `LANGUAGE_CODE` variable:
```python
LANGUAGE_CODE = 'fr' # or 'en' for english, etc.
```
::: tip
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:
```python
TIME_ZONE = 'Europe/Paris'
```
### Sessions management
Modoboa uses [Django's session framework](https://docs.djangoproject.com/en/dev/topics/http/sessions/?from=olddocs)
to store per-user information.
Few parameters need to be set in the `settings.py` configuration file to make Modoboa behave as expected:
```python
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](https://docs.python.org/3/library/logging.handlers.html#logging.handlers.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 `settings.py` file and add
['address': \'/dev/log\'] to the logging section:
```python
'syslog-auth': {
'class': 'logging.handlers.SysLogHandler',
'facility': SysLogHandler.LOG_AUTH,
'address': '/dev/log',
'formatter': 'syslog'
},
```
### External authentication
## LDAP {#ldap_auth}
Modoboa supports external LDAP authentication using the following extra components:
* [Python LDAP client](http://www.python-ldap.org/)
* [Django LDAP authentication backend](http://pypi.python.org/pypi/django-auth-ldap)
If you want to use this feature, you must first install those components:
```shell
$ pip install python-ldap django-auth-ldap
```
Then, all you have to do is to modify the `settings.py` file.
Add a new authentication backend to the [AUTHENTICATION_BACKENDS] variable, like this:
```python
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 the DNS name of the LDAP server |localhost |
| Server port | The TCP port number used by the LDAP server | 389 |
| Use a secure connection | Use an SSL/TLS connection to access the LDAP server | no |
| Authentication method | Choose the authentication method to use | Direct bind |
| User DN template (direct bind mode)| The template used to 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 (e.g. \'(objectClass=person)\'). In order to be valid, it must be enclosed in parentheses. | (mail=%(user)s) |
| Password attribute | The attribute used to store user passwords | userPassword |
| Active Directory | Tell if the LDAP server is an no 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 creation | Automatically create a domain and 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 | yes |
::: tip
If you need additional parameters, you will find a detailed
documentation [here](http://packages.python.org/django-auth-ldap/).
:::
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.
::: warning
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 {#smtp_auth}
It is possible to use an existing SMTP server as an authentication
source.
To enable this feature, edit the `settings.py` file and change the following setting:
``` python
AUTHENTICATION_BACKENDS = (
'modoboa.lib.authbackends.SMTPBackend',
'django.contrib.auth.backends.ModelBackend',
)
```
SMTP server location can be customized using the following settings:
``` python
AUTH_SMTP_SERVER_ADDRESS = 'localhost'
AUTH_SMTP_SERVER_PORT = 25
AUTH_SMTP_SECURED_MODE = None # 'ssl' or 'starttls' are accepted
```
### LDAP synchronization {#ldap-sync}
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 `settings.py` file:
```python
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 `requirements <ldap_auth>`
otherwise it won't work.
:::
The following parameters are available and must be filled:
| Name | Description | Default Value |
| :-: | :-- | :-: |
| Enable LDAP synchronization | Control LDAP synchronization state | no |
| 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:
```txt
0 0 * * * <modoboa_site>/manage.py cleanlogs
#
# Or like this if you use a virtual environment:
# 0 0 * * * <virtualenv path/bin/python> <modoboa_site>/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:
```txt
0 0 * * * <modoboa_site>/manage.py clearsessions
#
# Or like this if you use a virtual environment:
# 0 0 * * * <virtualenv path/bin/python> <modoboa_site>/manage.py clearsessions
```
### Cleaning inactive accounts {#inactive_accounts}
Thanks to `lastlogin`{.interpreted-text role="ref"}, 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:
```txt
0 0 * * * <modoboa_site>/manage.py clean_inactive_accounts
#
# Or like this if you use a virtual environment:
# 0 0 * * * <virtualenv path/bin/python> <modoboa_site>/manage.py clean_inactive_accounts
```
The default behaviour is to disable accounts. You can delete them using the `--delete` option.
## DMARC reports
::: warning
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
::: info
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`:
```txt
dmarc-rua-parser unix - n n - - pipe
flags= user=vmail:vmail argv=<path to python> <path to modoboa instance>/manage.py import_aggregated_report --pipe
```
Define a new transport table inside `/etc/postfix/main.cf`:
```txt
transport_maps =
hash:/etc/postfix/dmarc_transport
# other transport maps...
```
Create a file called `/etc/postfix/dmarc_transport` with the following content:
```txt
<email address your declared in your DNS record> dmarc-rua-parser:
```
::: warning
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:
```shell
$ postmap /etc/postfix/dmarc_transport
```
Finally, reload postfix:
```shell
$ service postfix reload
```
+141
View File
@@ -0,0 +1,141 @@
# 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
* [docker](https://docs.docker.com/install/) and
* [docker-compose](https://docs.docker.com/compose/install/) first.
If not already done, clone the repo and open it:
```shell
$ git clone https://github.com/modoboa/modoboa.git
$ cd modoboa
```
Then, just run the following command:
```shell
$ 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:
``` 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](https://docs.python.org/fr/3/library/venv.html)
is a good way to setup a development environment on your machine.
To do so, run the following commands:
```shell
$ python3 -m venv <path>
$ source <path>/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 `create a database <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:
```shell
$ cd <path>
$ modoboa-admin.py deploy --dburl default:<database url> --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](https://vuejs.org/) framework.
The source files are located in the `frontend/`{.interpreted-text role="file"} directory.
To set it up, you will need to install NodeJS and Yarn - to manage the
dependencies.
Then, navigate to the `frontend/` directory and run:
```shell
$ yarn install
```
You can now build it and serve it - while running your instance too to
serve the API - with:
```shell
$ yarn serve
```
## Tests
If you deployed an instance for development, you can launch the tests from it with:
```shell
$ python manage.py test modoboa
```
You could also test just some them, i.e.:
```shell
$ python manage.py test modoboa.core.tests.test_authentication
```
Alternatively, you can use [tox](https://tox.readthedocs.io)
from the repository to run all the tests and check the coverage with:
```shell
$ tox
```
You could limit the environment to a specific Python version with the `-e py<version>` argument.
Note that it is also possible to quickly run a test instance without any deployment - e.g. to preview some changes - by running:
```shell
$ tox -e serve
```
## Documentation
The source files are located in the `/doc-ng/`[ folder and are
written in markdown.
They are formatted in HTML and compiled thanks to VitePress
To build it and see the result, run:
```shell
$ npm run dev
```
+193
View File
@@ -0,0 +1,193 @@
# 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
::: tip
Plugins are nothing more than Django applications with an extra piece of
code that integrates them into Modoboa.
:::
The `modo_extension.py` file will contain a complete description of the plugin:
- Admin and user parameters
- Custom menu entries
The communication between both applications is provided by
[Django signals](https://docs.djangoproject.com/en/5.2/topics/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):
```shell
$ python manage.py startapp
```
Then, you need to register this application using the provided API.
Just copy/paste the following example into the `modo_extension.py` file of the future extension:
```python
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 `settings.py`.
Finally, run the following commands:
```shell
$ 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](https://docs.djangoproject.com/en/1.9/topics/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:
```python
from modoboa.parameters import tools as param_tools
param_tools.registry.add(LEVEL, YourForm, ugettext_lazy("Title"))
```
Replace:
* `LEVEL` (str): `"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:
``` 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:
``` 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:
``` 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}
```
+20
View File
@@ -0,0 +1,20 @@
# 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](https://app.transifex.com/tonio/modoboa/dashboard/)
## 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:
```shell
$ make makemessages
```
+7
View File
@@ -0,0 +1,7 @@
# Contributors
- [Antidot](http://antidot.com)
- [Bearstech](http://bearstech.com)
- [CAP-REL](https://cap-rel.fr/)
- [Dalnix](https://www.dalnix.se/)
- [Mirounga](https://mirounga.fr)
+41
View File
@@ -0,0 +1,41 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: "Modoboa"
text: "Mail hosting and management platform"
tagline: "simplified Web User Interface designed to work with Postfix and Dovecot"
image:
src: modoboa_logo.png
alt: Modoboa Logo
actions:
- theme: brand
text: QuickStart
link: /installation/modoboa
- theme: alt
text: Contribute
link: /contributing/getting_start
- theme: alt
text: Translate
link: /contributing/translation
- theme: alt
text: Demo
link: https://demo.modoboa.org
features:
- title: Sovereignty
details: Take back control of your emails to guarantee your security
- title: DKIM, DMARC, SPF
details: increase the deliverability of your emails
- title: API
details: To ease the integration with external sources (software or other), Modoboa provides a REST API
---
## Admin Dashboard
![Admin dashboard](/admin_dashboard.png "Admin dashboard")
## Webmail
![User Webmail](/user_webmail.png "User Webmail")
+272
View File
@@ -0,0 +1,272 @@
# 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](http://www.amavis.org/README.sql-mysql.txt) and one for
[PostgreSQL](http://www.amavis.org/README.sql-pg.txt).
Then, you must tell amavis to use this database for lookups and
quarantined messages storing. Here is a working configuration sample:
```ini [amavis]
@lookup_sql_dsn =
(['DBI:<driver>:database=<database>;host=<dbhost>;port=<dbport>', '<dbuser>', '<password>]']);
@storage_sql_dsn =
(['DBI:<driver>:database=<database>;host=<dbhost>;port=<dbport>', '<dbuser>', '<password>]']);
# 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 `section
<amavis_release>`{.interpreted-text role="ref"}.
::: info
Amavis configuration allows for separate lookup and storage databases
but Modoboa doesn\'t support it yet.
:::
::: info
`$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
`settings.py`{.interpreted-text role="file"}, add a new connection to
the `DATABASES` variable like this:
```python{5-9} [settings.py]
DATABASES = {
# Stuff before
#
"amavis": {
"ENGINE" : "<your value>",
"HOST" : "<your value>",
"NAME" : "<your value>",
"USER" : "<your value>",
"PASSWORD" : "<your value>"
}
}
```
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:
```txt
0 0 * * * <modoboa_site>/manage.py qcleanup
#
# Or like this if you use a virtual environment:
# 0 0 * * * <virtualenv path/bin/python> <modoboa_site>/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.
## Release messages {#amavis_release}
To release messages, first take a look at [this
page](http://www.ijs.si/software/amavisd/amavisd-new-docs.html#quar-release).
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:
```txt{1,2,10}
$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 | Mode used to access the PDP server | unix |
| PDP server address | PDP server address (if inet mode) | localhost |
| PDP server port | PDP server port (if inet mode) | 9998 |
| PDP server socket | Path to the PDP server socket (if unix mode) | /var/amavis/amavisd.sock |
### 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:
```txt
0 12 * * * <modoboa_site>/manage.py amnotify --baseurl='<modoboa_url>'
#
# Or like this if you use a virtual environment:
# 0 12 * * * <virtualenv path/bin/python> <modoboa_site>/manage.py amnotify --baseurl='<modoboa_url>'
````
You are free to change the frequency.
::: info
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 | Interval between two release requests checks | 30 |
| Allow direct release release | Allow users to directly release their messages | no |
| Notifications sender | The e-mail address used to send notitications | <notification@modoboa.org> |
## Self-service mode {#selfservice}
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](http://amavis.org/README.customize.txt) file to learn
what you're allowed to do.
Here is a link example:
https://<modoboa_url>/user/selfquarantine/%i/%R?secret_id=[:secret_id]
## Manual SpamAssassin learning {#sa_manual_learning}
It is possible to manually train [SpamAssassin](http://spamassassin.apache.org/)
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
(`/etc/spamassassin/local.cf`{.interpreted-text role="file"})
to add the following lines inside:
::: code-group
``` perl [PostgreSQL]
bayes_store_module Mail::SpamAssassin::BayesStore::PgSQL
bayes_sql_dsn <DSN>
bayes_sql_username <db username>
bayes_sql_password <db password>
```
``` perl [MySQL]
bayes_store_module Mail::SpamAssassin::BayesStore::MySQL
bayes_sql_dsn <DSN>
bayes_sql_username <db username>
bayes_sql_password <db 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:
1. Global: available to administrators only. A single (global) bayes
database is shared between everyone.
2. Per domain: available to administrators and domain administrators.
Each domain can have a dedicated database.
3. 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.
::: info
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`).
+656
View File
@@ -0,0 +1,656 @@
# Dovecot
## introduction
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
`/etc/dovecot`, all pathes will be relative to this directory.
You can find configuration documentation [here](https://doc.dovecot.org/configuration_manual/).
This proposed configuration is the one you can find with modoboa-installer.
For up to date configuration,
[take a look here](https://github.com/modoboa/modoboa-installer/tree/master/modoboa_installer/scripts/files/dovecot/conf.d)
## Packages
For debian and derivative, recommended packages are:
```shell
apt install dovecot-imapd dovecot-lmtpd dovecot-managesieved dovecot-sieve
```
## Mailboxes
First, edit the `conf.d/10-mail.conf` and
set the `mail_location` variable:
```txt{2}
# maildir
mail_location = maildir:~/Maildir
```
Then, edit the `inbox` namespace and add the following line:
```txt
inbox = yes
```
In order for dovecot to automaticaly create usual folders on account
creation, edit the `inbox` namespace of `15-mailboxes.conf`:
```txt
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:
```txt
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](http://wiki2.dovecot.org/Plugins/Autocreate) plugin.
### Operations on the file system {#fs_operations}
::: 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 (`/usr/sbin/dovecot` and
`/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
`settings.py` ).
:::
Three operation types are considered:
1. Mailbox creation
2. Mailbox renaming
3. 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 `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
`Postfix configuration <postfix_config>`).
Edit the crontab of the user who owns the mailboxes on the file system:
```shell
$ crontab -u <vmail_user> -e
```
And add the following line inside:
```txt
* * * * * python <modoboa_instance>/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
`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.
## Authentication
To make the authentication work, edit the
`conf.d/10-auth.conf` and uncomment the
following line at the end:
```txt{2}
#!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 `conf.d/auth-sql.conf.ext`
file and add the following content inside:
```txt
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 `dovecot-sql.conf.ext` and modify the configuration according to your database engine.
::: code-group
``` shell [PostgreSQL]
# For debian and derivative, you need to install postgres connector for dovecot::
sudo apt install dovecot-pgsql
```
``` shell [MySQL]
# For debian and derivative, you need to install mysql connector for dovecot::
sudo apt install dovecot-mysql
```
``` shell [SQLite]
# For debian and derivative, you need to install sqlite connector for dovecot::
sudo apt install dovecot-sqlite
```
:::
::: code-group
``` txt [PostgreSQL]
driver = pgsql
connect = host=<postgres socket> dbname=<database> user=<user> password=<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
```
``` txt [MySQL]
driver = mysql
connect = host=<mysqld socket> dbname=<database> user=<user> password=<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
```
```txt [SQLite]
driver = sqlite
connect = <path to the sqlite db file>
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 '<mailboxes storage directory>/%Ld/%Ln' AS home, <uid> as uid, <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 WHERE mb.address='%Ln' AND dom.name='%Ld'
iterate_query = SELECT email AS user FROM core_user
```
:::
::: info
Replace values between `<>` with yours.
:::
## 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:
``` shell
cd <modoboa_instance_path>
python manage.py createapplication --name=Dovecot --skip-authorization --client-id=dovecot confidential client-credentials
```
On success, you should see an output similar to:
``` txt
New application Dovecot created successfully.
client_secret: XXXX
```
To enable OAuth2 authentication in Dovecot, edit the `conf.d/10-auth.conf`
file and update the auth_mechanisms line as follows:
``` txt
auth_mechanisms = plain login oauthbearer xoauth2
```
Then, add the following line at the end:
``` txt
!include auth-oauth2.conf.ext
```
Then, create a file named `conf.d/auth-oauth2.conf.ext` with the following content:
``` txt
passdb {
driver = oauth2
mechanisms = xoauth2 oauthbearer
args = /etc/dovecot/conf.d/dovecot-oauth2.conf.ext
}
```
Finally, create a file named `conf.d/dovecot-oauth2.conf.ext` with the following content:
``` txt
introspection_mode = post
introspection_url = https://dovecot:<client_secret>@<hostname of your server>/api/o/introspect/
username_attribute = username
tls_ca_cert_file = /etc/ssl/certs/ca-certificates.crt
active_attribute = active
active_value = true
```
Replace `<client_secret>` with the value you obtained earlier.
## LDAP
To make the LDAP authentication work, edit the `conf.d/10-auth.conf`
and uncomment the following line at the end:
``` txt
!include auth-ldap.conf.ext
```
Then edit the `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:
``` txt
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 `/etc/dovecot/dovecot-ldap.conf.ext`.
You can add your default LDAP conf in it, following the
[official documentation](https://doc.dovecot.org/configuration_manual/authentication/ldap/).
### 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 (`dovecot-ldap.conf.ext` ), add the following line:
``` txt
!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](http://en.wikipedia.org/wiki/Local_Mail_Transfer_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 `dovecot.conf`).
It should be similar to the following example:
```txt
protocols = imap pop3 lmtp
```
Then, open the `conf.d/10-master.conf` ,
look for `lmtp` service definition and add the following content inside:
```txt
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
`/var/spool/postfix` .
Finally, open the `conf.d/20-lmtp.conf` and modify it as follows:
```txt
protocol lmtp {
postmaster_address = postmaster@<domain>
mail_plugins = $mail_plugins quota sieve
}
```
Replace `<domain>` by the appropriate value.
::: info
If you don't plan to apply quota or to use filters, just adapt the
content of the `mail_plugins` setting.
:::
## 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 `conf.d/10-mail.conf` ,
add the `quota` plugin to the default activated ones:
```txt
mail_plugins = quota
```
Inside `conf.d/10-master.conf` , update
the `dict` service to set proper permissions:
```txt
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 = <user owning mailboxes>
#group =
}
}
```
Inside `conf.d/20-imap.conf` , activate
the `imap_quota` plugin:
```txt{4}
protocol imap {
# ...
mail_plugins = $mail_plugins imap_quota
# ...
}
```
Inside `dovecot.conf` , activate the quota
SQL dictionary backend:
```txt{2}
dict {
quota = <driver>:/etc/dovecot/dovecot-dict-sql.conf.ext
}
```
Inside `conf.d/90-quota.conf` , activate
the *quota dictionary* backend:
```txt
plugin {
quota = dict:User quota::proxy::quota
}
```
It will tell Dovecot to keep quota usage in the SQL dictionary.
Finally, edit the `dovecot-dict-sql.conf.ext`{.interpreted-text
role="file"} file and put the following content inside:
```txt
connect = host=<db host> dbname=<db name> user=<db user> password=<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:
```sql
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 doc](https://doc.dovecot.org/2.4.2/core/plugins/quota.html#quota-plugin-quota),
you need a trigger to properly update the quota.
A working copy of this trigger is available on
[Github](https://raw.githubusercontent.com/modoboa/modoboa-installer/master/modoboa_installer/scripts/files/dovecot/install_modoboa_postgres_trigger.sql).
Download this file and copy it on the server running postgres.
Then, execute the following commands:
```shell
$ 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:
```shell
$ 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 `conf.d/20-managesieve.conf`, make sure the following lines are uncommented:
```txt
protocols = $protocols sieve
service managesieve-login {
# ...
}
service managesieve {
# ...
}
protocol sieve {
# ...
}
```
Finally, configure the `sieve` plugin by editing the `conf.d/90-sieve.conf` file.
Put the follwing caontent inside:
```txt
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 `postfix` section to finish the installation.
## 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](https://wiki.dovecot.org/PostLoginScripting).
Open `conf.d/10-master.conf` add the following configuration
(`imap` and `pop3` services are already defined,
you just need to update them):
```txt
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
`/usr/local/bin/postlogin.sh` .
According to your database engine, the content will differ.
::: code-group
``` bash [PostgreSQL]
#!/bin/sh
psql -c "UPDATE core_user SET last_login=now() WHERE username='$USER'" > /dev/null
exec "$@"
```
``` bash [MySQL]
#!/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 "$@"
```
:::
+54
View File
@@ -0,0 +1,54 @@
# Automatic Installer
## Introduction
If you start from scratch and want to deploy a complete mail server,
you will love the [modoboa installer](https://github.com/modoboa/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.
## How to start
::: 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 `manually <by_hand>`.
:::
To use it, just run the following commands in your terminal:
``` shell
$ git clone https://github.com/modoboa/modoboa-installer
$ cd modoboa-installer
$ sudo ./run.py <your domain>
```
::: warning
if you get this warning
```console
'/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, check the `PATH` variable for the current user.
Then run this command first.
``` shell
$ 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 and point to the python3 runtime.
Wait a few minutes and you're done 😎
+13
View File
@@ -0,0 +1,13 @@
# 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:
* [Modoboa](modoboa)
* [Web Server](webserver)
* [Dovecot](dovecot)
* [Postfix](postfix)
* [OpenDKIM](opendkim)
* [Radicale](radicale)
* [Amavis](amavis)
+317
View File
@@ -0,0 +1,317 @@
# Modoboa
This section describes the installation of the web interface (a [Django](https://www.djangoproject.com/) project).
This proposed configuration is the one you can find with `modoboa-installer`.
For up to date configuration, [take a look here](https://github.com/modoboa/modoboa-installer/tree/master/modoboa_installer/scripts/files/modoboa/)
## Prepare the system
First of all, we recommend the following context:
* A dedicated system user
* A [virtual environment](https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments)
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](https://virtualenv.pypa.io/en/stable/):
``` shell
$ sudo apt-get install virtualenv python3-pip
$ sudo 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
```
::: warning
Modoboa depends on external tools and some of them require compilation
so you need a compiler and a few C libraries.
:::
::: tip INFORMATION
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 / Redhat
* gcc
* gcc-c++
* python3-devel
* libxml2-devel
* libxslt-devel
* libjpeg-turbo-devel
* rrdtool-devel rrdtool
* libffi-devel
:::
::: info
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:
``` console
(env)$ pip install modoboa
```
## Database
::: warning
This documentation does not cover the installation of a database server
but only the setup of a functional database that Modoboa will use.
:::
Thanks to Django, Modoboa is compatible with the following databases:
- PostgreSQL
- MySQL / MariaDB
- SQLite
Since the last one does not require particular actions, only the first
two ones are described.
You should also read the notes for those database backends on the
[official Django documentation](https://docs.djangoproject.com/en/stable/ref/databases/).
### PostgreSQL
Install the corresponding Python binding:
``` shell
(env)$ pip install psycopg[binary]>=3.1
```
::: info
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 as `root` or admin user:
``` bash
$ sudo -l -u postgres createuser --no-createdb modoboa
$ sudo -l -u postgres createdb --owner=modoboa modoboa
```
### MySQL / MariaDB
Install the corresponding Python binding:
``` console
(env)$ pip install mysqlclient
```
::: tip
Alternatively, you can install the `python3-mysqldb` package instead on
Debian-based distributions if your virtual environment was created with
`--system-site-packages` option.
:::
:::: info 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:
``` sql
CREATE DATABASE modoboa;
CREATE USER 'modoboa'@'localhost' IDENTIFIED BY 'my-strong-password-here';
GRANT ALL PRIVILEGES ON modoboa.* TO 'modoboa'@'localhost';
```
## Deploy an instance {#deployment}
`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:
``` shell
(env)$ modoboa-admin.py deploy instance --collectstatic \
--domain <hostname of your server> --dburl default:<database url>
```
::: info
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 `index
page <../index>`{.interpreted-text role="doc"}. Instructions to install
them are available on each extensions page.
:::
::: tip TIPS
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](http://modoboa-amavis.readthedocs.org)
extension, use the `amavis:` prefix. For example:
`--dburl default:<database url> amavis:<database url>`.
A database url should meet the following syntax
`<mysql|postgres>://[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:
``` shell
(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 `/etc/cron.d/modoboa` and put the following content inside:
``` shell
#
# Modoboa specific cron jobs
#
PYTHON=<path to Python binary inside the virtual environment>
INSTANCE=<path to Modoboa instance>
# Operations on mailboxes
* * * * * <mailbox user> $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
```
::: tip TIPS
**🥵 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](http://www.postfix.org/SMTPD_POLICY_README.html).
Current features are:
* Define daily sending limits for domains and/or accounts
A [redis server](https://redis.io/) is required to run this new daemon.
You can launch it manually using the following command:
``` shell
(env) $ python manage.py policy_daemon
```
But we recommend an automatic start using `systemd` or `supervisor`.
Here is a configuration example for `supervisor`:
``` ini
[program:policyd]
autostart=true
autorestart=true
command=<path to Python binary inside the virtual environment> <path to Modoboa instance>/manage.py policy_daemon
directory=<modoboa user home dir>
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
`postfix <policyd_config>` to use it.
## RQ daemon
Modoboa uses [RQ](https://python-rq.org) as a job handler for async task.
A [redis server](https://redis.io/) 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:
``` shell
(env)> rq worker high default low
```
But we recommend an automatic start using `systemd` or `supervisor`.
Here is a configuration example for `supervisor`:
``` ini
[program:modoboa-dkim-worker]
autostart=true
autorestart=true
command=<path to Python binary inside the virtual environment> <path to Modoboa instance>/manage.py rqworker dkim
directory=<modoboa user home dir>
user=<opendkim user>
redirect_stderr=true
numprocs=1
stopsignal=TERM
```
Now you can continue to the [webserver](webserver) section.
+79
View File
@@ -0,0 +1,79 @@
# OpenDKIM
Modoboa can generate [DKIM](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail) keys
for the hosted domains but it won't sign or check messages.
To do that, you need a dedicated software like [OpenDKIM](http://opendkim.org/).
::: warning
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:
::: code-group
```sql [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
);
```
```sql [MySQL]
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 `/etc/opendkim.conf`.
Add the following content to it:
``` txt
KeyTable dsn:<driver>://<user>:<password>@<db host>/<db name>/table=dkim?keycol=id?datacol=domain_name,selector,private_key_path
SigningTable dsn:<driver>://<user>:<password>@<db host>/<db name>/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 `/etc/default/opendkim` file:
``` txt
SOCKET=inet:12345@127.0.0.1
```
Eventually, `reload OpenDKIM`.
## Postfix integration
Add the following lines to the `/etc/postfix/main.cf` file:
``` txt{1,2}
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`.
+103
View File
@@ -0,0 +1,103 @@
# Postfix
This section gives an example about building a simple virtual hosting
configuration with *Postfix*.
Refer to the [official documentation](http://www.postfix.org/VIRTUAL_README.html)
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:
``` bash
$ cd <modoboa_instance_path>
$ python manage.py generate_postfix_maps --destdir <directory>
```
`<directory>` is the directory where the files will be stored. Answer
the few questions and you\'re done.
## Configuration
Use the following configuration in the `/etc/postfix/main.cf` file.
For TLS configuration, you can look at the
[used configuration](https://github.com/modoboa/modoboa-installer/blob/master/modoboa_installer/scripts/files/postfix/main.cf.tpl)
for [modoboa installer](https://github.com/modoboa/modoboa-installer). (this is just one possible configuration):
```txt
# 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:<driver>:/etc/postfix/sql-domains.cf
proxy:<driver>:/etc/postfix/sql-domain-aliases.cf
proxy:<driver>:/etc/postfix/sql-aliases.cf
proxy:<driver>:/etc/postfix/sql-relaydomains.cf
proxy:<driver>:/etc/postfix/sql-maintain.cf
proxy:<driver>:/etc/postfix/sql-relay-recipient-verification.cf
proxy:<driver>:/etc/postfix/sql-sender-login-map.cf
proxy:<driver>:/etc/postfix/sql-spliteddomains-transport.cf
proxy:<driver>:/etc/postfix/sql-transport.cf
## Virtual transport settings
virtual_transport = lmtp:unix:private/dovecot-lmtp
virtual_mailbox_domains = proxy:<driver>:/etc/postfix/sql-domains.cf
virtual_alias_domains = proxy:<driver>:/etc/postfix/sql-domain-aliases.cf
virtual_alias_maps = proxy:<driver>:/etc/postfix/sql-aliases.cf
## Relay domains
relay_domains = proxy:<driver>:/etc/postfix/sql-relaydomains.cf
transport_maps =
proxy:<driver>:/etc/postfix/sql-transport.cf
proxy:<driver>:/etc/postfix/sql-spliteddomains-transport.cf
smtpd_recipient_restrictions =
permit_mynetworks
permit_sasl_authenticated
check_recipient_access
proxy:<driver>:/etc/postfix/sql-maintain.cf
proxy:<driver>:/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:<driver>:/etc/postfix/sql-sender-login-map.cf
# Stuff after
```
Replace `<driver>` by the name of the database you use, and `Restart Postfix`.
## Policy daemon
If you want to enable the built-in policy daemon, add the following
content to the `/etc/postfix/main.cf` file:
```txt{3}
smtpd_recipient_restrictions =
# ...
check_policy_service inet:localhost:9999
# ...
```
And `reload postfix`.
::: warning
The `check_policy_service` line must be placed before the
`permit_mynetworks` one, otherwise the daemon won't be called.
:::
+142
View File
@@ -0,0 +1,142 @@
# Radicale
This page is displaying how to install and use radicale when either
having installed modoboa manually or with the dedicated installer.
## OAuth 2 authentication
::: tip
These steps are automatic if you use an up-to-date modoboa-installer to
install/upgrade.
:::
### Preparing the usage of radicale (manual install only)
::: warning
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).
``` shell
$ 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)
``` shell
$ 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:
``` shell
$ sudo -u radicale -i bash
$ cd ~
$ env/bin/pip install radicale-modoboa-auth-oauth2
```
For manual installations, this will do the job:
``` shell
$ 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:
``` shell
$ cd <modoboa_instance_path>
$ python manage.py createapplication --name=Radicale --skip-authorization --client-id=radicale confidential client-credentials
```
On success, you should see an output similar to:
```console
New application Radicale created successfully.
client_secret: XXXX
```
To enable OAuth2 authentication in Radicale, edit the `/etc/radicale/config` file
and update the [type] in [\[auth\]] to:
```txt
type = radicale_modoboa_auth_oauth2
````
Then, add the following line in \`\[auth\]\`:
```txt
oauth2_introspection_endpoint = https://radicale:<client_secret>@<hostname of your server>/api/o/introspect/
````
Replace `<client_secret>` with the value you obtained earlier.
Your `/etc/radicale/config`{.interpreted-text role="file"} should look
like this (listening address and port may vary):
```ini
[server]
hosts = 0.0.0.0:5232,[::]:5232
[auth]
type = radicale_modoboa_auth_oauth2
oauth2_introspection_endpoint = https://radicale:<client_secret>@<hostname of your server>/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]{#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:
```txt
dovecot_socket = /run/dovecot/auth-radicale
```
and in `10-master.conf` for dovecot:
```txt
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](https://radicale.org/v3.html#reverse-proxy).
+26
View File
@@ -0,0 +1,26 @@
# 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
::: warning
**👀 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.
You have 2 possibilities to install Modoboa
* [Manual Installation](manual)
* [Automatic Install](installer)
File diff suppressed because it is too large Load Diff
+347
View File
@@ -0,0 +1,347 @@
# Web server {#webserver}
::: info
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
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:
```txt
WSGIPythonHome /var/www/modoboa/env
WSGIPythonPath /var/www/modoboa/instance
<VirtualHost *:80>
ServerName <your value>
DocumentRoot {{ modoboa_instance_path }}
Alias /media/ {{ modoboa_instance_path }}/media/
<Directory {{ modoboa_instance_path }}/media/>
Options FollowSymLinks
Require all granted
</Directory>
Alias /sitestatic/ {{ modoboa_instance_path }}/sitestatic/
<Directory {{ modoboa_instance_path }}/sitestatic/>
Options FollowSymLinks
Require all granted
</Directory>
WSGIScriptAliasMatch ^/(api|accounts) {{ modoboa_instance_path }}/instance/wsgi.py
WSGIApplicationGroup %{GLOBAL}
# Pass Authorization header to enable API usage:
WSGIPassAuthorization On
Alias / {{ modoboa_instance_path }}/frontend
<Directory {{ modoboa_instance_path }}/frontend>
Options FollowSymLinks
Require all granted
</Directory>
LogLevel info
</VirtualHost>
```
This is just one possible configuration.
Replace values between `<>` with yours. If you don't use a [virtualenv](http://virtualenv.readthedocs.org/en/latest/),
just remove the last part of the `WSGIDaemonProcess` directive. .. note:
You may need to add:
``` python [ {{ modoboa_instance_path }}/instance/wsgi.py]
import sys
sys.path.append('{{ modoboa_instance_path }}')
sys.path.append('{{ modoboa_venv_path }}/bin')
sys.path.append('{{ modoboa_venv_path }}/lib/python3.X/site-packages')
```
in :file:` {{ modoboa_instance_path }}/instance/wsgi.py`.
::: tip
You will certainly need more configuration in order to launch Apache.
:::
Now, you can go the `dovecot` section to continue the installation.
## Nginx
This section covers two different ways of running Modoboa behind
[Nginx](http://nginx.org/) using a WSGI application server.
Choose the one you prefer between
[Green Unicorn](http://gunicorn.org/) or [uWSGI](https://github.com/unbit/uwsgi).
In both cases, you\'ll need to download and [install nginx](http://wiki.nginx.org/Install).
### 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](http://uwsgi-docs.readthedocs.org/en/latest/WSGIquickstart.html).
Recommend packages for debian and derivatives:
```shell
apt install uwsgi uwsgi-plugin-python3
```
Here is a sample nginx configuration:
``` nginx
upstream modoboa {
server unix:{{ uwsgi_socket_path }} fail_timeout=0;
}
server {
listen 80;
listen [::]:80;
server_name {{ hostname }};
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ hostname }};
root {{ modoboa_instance_path }};
ssl_certificate <ssl certificate for your site>;
ssl_certificate_key <ssl certificate key for your site>;
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 {{ modoboa_instance_path }}/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;
}
}
```
'uwsgi_socket_path', `modoboa instance name`, `hostname`,
`modoboa_instance_path` and `ssl...` must be replaced by the value
you used when `you deployed your instance deployment`
In case you want to use enable auto-configuration functionality,
create a second virtualhost configuration the hostname should look like `autoconfig.your domain here`
```txt
server {
listen 80;
listen [::]:80;
server_name autoconfig.<your_domain>;
root {{ modoboa_instance_path }};
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;
}
}
```
`{{ modoboa_instance_path }}` and `your_domain` must be replaced by the
value you used when `you deployed your instance <deployment>`{.interpreted-text role="ref"}.
If you do not plan to use SSL then change the listen directive to `listen 80;` and delete each of the following directives:
```txt
ssl on;
keepalive_timeout 70;
ssl_certificate {{ssl certificate for your site}};
ssl_certificate_key {{ssl certificate key for your site}};
uwsgi_param UWSGI_SCHEME https;
```
If you do plan to use SSL, you\'ll have to generate a certificate and a
key. [This article](http://wiki.nginx.org/HttpSslModule#Generate_Certificates)
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:
* `hostname`: 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 `hostname` 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 `hostname` is an
empty string and can be deleted from the configuration above. In
this case, you probably do not need the `alias` directives.
* `uwsgi_socket_path`: 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:
```txt
unix:/run/uwsgi/app/ app name /socket
```
where `app name` is the name of the application.
Your uwsgi configuration should be:
``` ini{3,4}
[uwsgi]
# Not needed when using uwsgi from pip
# plugins = python
chdir = <modoboa_instance_path>
module = <name>.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:
* `modoboa_instance_path`: The directory where `manage.py` resides.
This directory is the parent of `modoboa's settings dir`
* `name`: The name that you passed to `modoboa-admin.py deploy`
when you created your Modoboa instance, usually `instance`.
Now, you can go the `dovecot` section to continue the installation.
### Green Unicorn
Firstly, [Download and install gunicorn](http://gunicorn.org/install.html).
Then, use the following sample gunicorn configuration
(create a new file named `gunicorn.conf.py` inside Modoboa's root dir):
```ini gunicorn.conf.py
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:
``` shell
$ cd {{ modoboa dir }}
$ gunicorn -c gunicorn.conf.py {{ APP/INSTANCE Name }}.wsgi:application
```
Now the nginx part. Just create a new virtual host and use the following
configuration:
``` nginx
upstream modoboa {
server unix:/var/run/gunicorn/modoboa.sock fail_timeout=0;
}
server {
listen 443 ssl;
ssl on;
keepalive_timeout 70;
server_name {{ host fqdn }};
root {{ modoboa_instance_path }};
access_log /var/log/nginx/{{ host fqdn }}.access.log;
error_log /var/log/nginx/{{ host fqdn }}.error.log;
ssl_certificate {{ ssl certificate for your site }};
ssl_certificate_key {{ ssl certificate key for your site }};
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:
```txt
ssl on;
keepalive_timeout 70;
ssl_certificate <ssl certificate for your site>;
ssl_certificate_key <ssl certificate key for your site>;
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](http://wiki.nginx.org/HttpSslModule#Generate_Certificates) 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 [Dovecot](./dovecot) section to continue the installation.
+169
View File
@@ -0,0 +1,169 @@
# 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}
::: info
[Modoboa](https://modoboa.org/) 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](https://www.offlineimap.org/doc/installation.html).
:::
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
::: title
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](https://www.offlineimap.org/doc/quick_start.html) 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
::: title
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:
``` 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:
``` 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
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 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
::: title
Warning
:::
In case of domain renaming as described in Providers section, 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](http://postfixadmin.sourceforge.net/)
database to a Modoboa one.
Consult the [documentation](https://github.com/modoboa/modoboa-pfxadmin-migrate) 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:
```csv
domain; <name: string>; <quota: integer>; <default mailbox quota: integer>; <enabled: boolean>
domainalias; <name: string>; <targeted domain: string>; <enabled: boolean>
relaydomain; <name: string>; <target host: string>; <target port: integer>; <service: string>; <enabled: boolean>; <verify recipients: boolean>
account; <loginname: string>; <password: string>; <first name: string>; <last name: string>; <enabled: boolean>; <group: string>; <address: string>; <quota: integer>; [<domain: string>, ...]
alias; <address: string>; <enabled: boolean>; <recipient: string>; ...
```
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:
``` bash
$ sudo -u <modoboa_user> -i bash
$ source <virtualenv_path>/bin/activate
$ cd <modoboa_instance_dir>
$ python manage.py modo import <your file>
```
Available options can be listed using the following command:
``` bash
$ python manage.py modo import -h
```
+11
View File
@@ -0,0 +1,11 @@
{
"devDependencies": {
"vitepress": "2.0.0-alpha.15"
},
"packageManager": "pnpm@10.22.0+sha512.bf049efe995b28f527fd2b41ae0474ce29186f7edcb3bf545087bd61fbbebb2bf75362d1307fda09c2d288e1e499787ac12d4fcb617a974718a6051f2eee741c",
"scripts": {
"dev": "vitepress dev",
"build": "vitepress build",
"preview": "vitepress preview"
}
}
+1837
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

+70
View File
@@ -0,0 +1,70 @@
# Rebuild Virtualenv
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 `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](http://modoboa.readthedocs.io/en/latest/index.html).
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](http://modoboa.readthedocs.io/en/latest/installation.html#extensions).
Once you have completed this step, you will need to run the following commands:
``` bash
$ (env) $ cd <instance_dir>
$ (env) $ python manage.py migrate
$ (env) $ python manage.py collectstatic
```
You will then see a message similar to:
``` txt
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/)
+35
View File
@@ -0,0 +1,35 @@
# 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://\<hostname\>/api/schema-v2/swagger/*
- Old API: *http://\<hostname\>/api/v1/*
::: info
You need to be logged in for the API docs to show.
:::
**Examples:**
* [new example](https://demo.modoboa.org/api/schema-v2/swagger/)
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](/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 <YOUR_TOKEN>
and the content type of those requests must be `application/json`.
+2241
View File
File diff suppressed because it is too large Load Diff