mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
Merge pull request #3875 from modoboa/migrate-doc-vitepress
docs: migrate documentation from sphinx to vitepress
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
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: cd doc-ng && pnpm install
|
||||||
|
|
||||||
|
- name: Build documentation
|
||||||
|
run: cd doc-ng && pnpm run build
|
||||||
@@ -10,12 +10,22 @@ on:
|
|||||||
- 'modoboa/**.po'
|
- 'modoboa/**.po'
|
||||||
- 'frontend/**'
|
- 'frontend/**'
|
||||||
- 'doc/**'
|
- 'doc/**'
|
||||||
|
- 'doc-ng/**'
|
||||||
|
- '.editorconfig'
|
||||||
|
- '.readthedocs.yml'
|
||||||
|
- '.pre-commit-config.yaml'
|
||||||
|
- '.gitignore'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- 'modoboa/**.po'
|
- 'modoboa/**.po'
|
||||||
- 'frontend/**'
|
- 'frontend/**'
|
||||||
- 'doc/**'
|
- 'doc/**'
|
||||||
|
- 'doc-ng/**'
|
||||||
|
- '.editorconfig'
|
||||||
|
- '.readthedocs.yml'
|
||||||
|
- '.pre-commit-config.yaml'
|
||||||
|
- '.gitignore'
|
||||||
release:
|
release:
|
||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
types: [ published ]
|
types: [ published ]
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ node_modules
|
|||||||
/frontend/webpack-stats.json
|
/frontend/webpack-stats.json
|
||||||
/frontend/src/translations.json
|
/frontend/src/translations.json
|
||||||
/frontend/.__mf__temp/
|
/frontend/.__mf__temp/
|
||||||
|
doc-ng/.vitepress/cache/
|
||||||
|
doc-ng/.vitepress/dist/
|
||||||
|
|
||||||
# TOX stuff
|
# TOX stuff
|
||||||
test_project/modoboa.db
|
test_project/modoboa.db
|
||||||
|
|||||||
+14
-7
@@ -1,10 +1,17 @@
|
|||||||
version: 2
|
version: 2
|
||||||
sphinx:
|
|
||||||
configuration: doc/conf.py
|
|
||||||
build:
|
build:
|
||||||
os: "ubuntu-22.04"
|
os: ubuntu-lts-latest
|
||||||
tools:
|
tools:
|
||||||
python: "3.10"
|
nodejs: "latest"
|
||||||
python:
|
jobs:
|
||||||
install:
|
install:
|
||||||
- requirements: doc/requirements.txt
|
- npm install vitepress
|
||||||
|
build:
|
||||||
|
html:
|
||||||
|
# The site was created by running `vitepress init`
|
||||||
|
# and following the official guide
|
||||||
|
# https://vitepress.dev/guide/getting-started
|
||||||
|
- ./node_modules/.bin/vitepress build doc-ng
|
||||||
|
- mkdir -p $READTHEDOCS_OUTPUT/
|
||||||
|
- mv doc-ng/dist $READTHEDOCS_OUTPUT/html
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
import { defineConfig } from 'vitepress'
|
||||||
|
|
||||||
|
// https://vitepress.dev/reference/site-config
|
||||||
|
export default defineConfig({
|
||||||
|
// Use Canonical URL, but only the path and with no trailing /
|
||||||
|
// End result is like: `/en/latest`
|
||||||
|
// https://docs.readthedocs.com/platform/stable/intro/vitepress.html#using-the-proper-base-path
|
||||||
|
base: process.env.READTHEDOCS_CANONICAL_URL
|
||||||
|
? new URL(process.env.READTHEDOCS_CANONICAL_URL).pathname.replace(/\/$/, '')
|
||||||
|
: '',
|
||||||
|
title: 'Modoboa',
|
||||||
|
titleTemplate: ':title',
|
||||||
|
description: 'Modoboa documentation',
|
||||||
|
srcExclude: ['public/**/*.md'],
|
||||||
|
ignoreDeadLinks: [/^https?:\/\/localhost:*/],
|
||||||
|
metaChunk: true,
|
||||||
|
themeConfig: {
|
||||||
|
// https://vitepress.dev/reference/default-theme-config
|
||||||
|
nav: [
|
||||||
|
{ text: 'Home', link: '/' },
|
||||||
|
{
|
||||||
|
text: 'Installation',
|
||||||
|
items: [
|
||||||
|
{ text: 'Requirements', link: '/installation/requirements' },
|
||||||
|
{ text: 'Manual Installation', link: '/installation/manual' },
|
||||||
|
{ text: 'Modoboa Installer', link: '/installation/installer' },
|
||||||
|
{ text: 'Upgrade Instance', link: '/installation/upgrade' },
|
||||||
|
{ text: 'Configuration', link: '/configuration' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Contributing',
|
||||||
|
items: [
|
||||||
|
{ text: 'Getting Started', link: '/contributing/getting_start' },
|
||||||
|
{ text: 'Write a Plugin', link: '/contributing/plugin_api' },
|
||||||
|
{ text: 'Translate', link: '/contributing/translation' },
|
||||||
|
{ text: 'REST API', link: '/rest_api' },
|
||||||
|
{ text: 'Contributors', link: '/contributors' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
sidebar: {
|
||||||
|
'/installation/': [
|
||||||
|
{
|
||||||
|
text: 'Manual',
|
||||||
|
items: [
|
||||||
|
{ text: 'Modoboa', link: '/installation/modoboa' },
|
||||||
|
{ text: 'WebServer', link: '/installation/webserver' },
|
||||||
|
{ text: 'Dovecot', link: '/installation/dovecot' },
|
||||||
|
{ text: 'Postfix', link: '/installation/postfix' },
|
||||||
|
{ text: 'OpenDKIM', link: '/installation/opendkim' },
|
||||||
|
{ text: 'Radicale', link: '/installation/radicale' },
|
||||||
|
{ text: 'Amavis', link: '/installation/amavis' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Automatic',
|
||||||
|
items: [
|
||||||
|
{ text: 'Modoboa Installer', link: '/installation/installer' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'/contributing/': [
|
||||||
|
{ text: 'Getting Started', link: '/contributing/getting_start' },
|
||||||
|
{ text: 'Write a Plugin', link: '/contributing/plugin_api' },
|
||||||
|
{ text: 'Translate', link: '/contributing/translate' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
socialLinks: [
|
||||||
|
{ icon: 'github', link: 'https://github.com/modoboa/modoboa' },
|
||||||
|
{ icon: 'discord', link: 'https://discord.gg/WuQ3v3PXGR' },
|
||||||
|
{
|
||||||
|
icon: {
|
||||||
|
svg: `<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<title>Transifex</title>
|
||||||
|
<path d="m20.073 12.851-2.758-2.757 3.722-3.659a.33.33 0 0 1 .467.003l2.27 2.309a.33.33 0 0 1-.004.468zm0 0h-.001zm-9.04-6.433 12.87 12.869c.129.13.129.34 0 .469l-2.289 2.289a.331.331 0 0 1-.468 0l-5.168-5.168-2.863 2.815c-.604.593-1.244 1.159-1.975 1.591a7.037 7.037 0 0 1-2.248.83c-2.191.42-4.557-.047-6.303-1.468A7.065 7.065 0 0 1 0 15.207V2.069a.33.33 0 0 1 .331-.33h3.237a.33.33 0 0 1 .331.33v4.125H6.65c.178 0 .323.145.323.323v3.617a.323.323 0 0 1-.323.323H3.899v4.75c0 1.272.808 2.429 1.988 2.893.753.295 1.617.321 2.397.131.852-.206 1.484-.717 2.097-1.319l2.839-2.792-4.945-4.945a.331.331 0 0 1 0-.468l2.289-2.289a.333.333 0 0 1 .469 0"/>
|
||||||
|
</svg>`,
|
||||||
|
},
|
||||||
|
link: 'https://app.transifex.com/tonio/modoboa/dashboard/',
|
||||||
|
},
|
||||||
|
{ icon: 'linkedin', link: 'https://www.linkedin.com/company/102575109' },
|
||||||
|
],
|
||||||
|
footer: {
|
||||||
|
message: 'Build with Vitepress',
|
||||||
|
copyright: `Copyright © 2010-${new Date().getUTCFullYear()} Antoine Nguyen`,
|
||||||
|
},
|
||||||
|
outline: {
|
||||||
|
label: 'Summmary',
|
||||||
|
},
|
||||||
|
docFooter: {
|
||||||
|
prev: false,
|
||||||
|
next: false,
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
provider: 'local',
|
||||||
|
},
|
||||||
|
lastUpdated: {
|
||||||
|
text: 'Update at',
|
||||||
|
formatOptions: {
|
||||||
|
dateStyle: 'full',
|
||||||
|
timeStyle: 'short',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sitemap: {
|
||||||
|
hostname: 'https://modoboa.readthedocs.io/en/latest',
|
||||||
|
},
|
||||||
|
markdown: {
|
||||||
|
lineNumbers: true,
|
||||||
|
image: {
|
||||||
|
lazyLoading: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cleanUrls: true,
|
||||||
|
outDir: './dist',
|
||||||
|
lastUpdated: true,
|
||||||
|
transformPageData(pageData) {
|
||||||
|
// console.log(pageData);
|
||||||
|
|
||||||
|
const baseUrl = process.env.READTHEDOCS_CANONICAL_URL
|
||||||
|
? new URL(process.env.READTHEDOCS_CANONICAL_URL).pathname.replace(/\/$/, '')
|
||||||
|
: ''
|
||||||
|
|
||||||
|
const canonicalUrl = baseUrl + '/' + pageData.relativePath.replace(/\.md$/, "").replace(/^index$/, "");
|
||||||
|
|
||||||
|
let updtDate = new Date();
|
||||||
|
// If no commit for a page (dev in progress), lastUpdated == NaN
|
||||||
|
// Ensure lastUpdated is defined and a number before passing it to isNaN/new Date
|
||||||
|
if (typeof pageData.lastUpdated === 'number' && !isNaN(pageData.lastUpdated)) {
|
||||||
|
updtDate = new Date(pageData.lastUpdated);
|
||||||
|
}
|
||||||
|
|
||||||
|
pageData.frontmatter.head ??= [];
|
||||||
|
pageData.frontmatter.head.push([
|
||||||
|
"link",
|
||||||
|
{ rel: "canonical", href: canonicalUrl },
|
||||||
|
]);
|
||||||
|
pageData.frontmatter.head.push([
|
||||||
|
"meta",
|
||||||
|
{ property: "og:title", content: pageData.frontmatter.title },
|
||||||
|
]);
|
||||||
|
pageData.frontmatter.head.push([
|
||||||
|
"meta",
|
||||||
|
{ property: "og:description", content: pageData.frontmatter.description },
|
||||||
|
]);
|
||||||
|
pageData.frontmatter.head.push([
|
||||||
|
"meta",
|
||||||
|
{ property: "og:type", content: 'article' },
|
||||||
|
]);
|
||||||
|
pageData.frontmatter.head.push([
|
||||||
|
"meta",
|
||||||
|
{ property: "og:url", content: canonicalUrl },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// TODO: Uncomment when modoboa image is available on the public folder
|
||||||
|
// pageData.frontmatter.head.push([
|
||||||
|
// "meta",
|
||||||
|
// { property: "og:image", content: 'https://xxxx/modoboa.png' },
|
||||||
|
// ]);
|
||||||
|
|
||||||
|
pageData.frontmatter.head.push([
|
||||||
|
"meta",
|
||||||
|
{ property: "og:locale", content: 'en_GB' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -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
|
||||||
|
```
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
---
|
||||||
|
title: Getting stated with modoboa
|
||||||
|
description: Discover how to develop and extend modoboa
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, getting started, backend, frontend, docker'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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
|
||||||
|
```
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
---
|
||||||
|
title: plugin development guide for modoboa
|
||||||
|
description: Discover how to develop a plugin for modoboa to extend functionnalities
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, plugin, extension, api, navigation, Django signals'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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, [])
|
||||||
|
```
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
title: translation guide for modoboa
|
||||||
|
description: How to help to translate modoboa for your natural language
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, i18n, translation, transifex, makemessages, backend, frontend'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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/)
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
Modoboa API code relies on Django's translation system.
|
||||||
|
|
||||||
|
To update translation files after a change to the code, execute the following commands:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ cd modoboa
|
||||||
|
$ django-admin makemessages -a
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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
|
||||||
|
$ yarn gettext:extract
|
||||||
|
```
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: "Contributors list"
|
||||||
|
description: "List of the contributor who participate to the modoboa's project"
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, contributor, project'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Contributors
|
||||||
|
|
||||||
|
- [6clones](https://www.6clones.fr/)
|
||||||
|
- [Antidot](http://antidot.com)
|
||||||
|
- [Bearstech](http://bearstech.com)
|
||||||
|
- [CAP-REL](https://cap-rel.fr/)
|
||||||
|
- [Dalnix](https://www.dalnix.se/)
|
||||||
|
- [Mirounga](https://mirounga.fr)
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
# https://vitepress.dev/reference/default-theme-home-page
|
||||||
|
layout: home
|
||||||
|
title: "Modoboa, the Mail hosting and management platform"
|
||||||
|
description: "Web User Interface designed to work with Postfix and Dovecot"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Webmail
|
||||||
|
|
||||||
|

|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
---
|
||||||
|
title: manual step to install amavis component on modoboa
|
||||||
|
description: This guide describe how to install amavis on the modoboa platform
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, installation, amavis, mysql, postgresql, quarantine'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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`).
|
||||||
@@ -0,0 +1,665 @@
|
|||||||
|
---
|
||||||
|
title: manual step to install dovecot component on modoboa
|
||||||
|
description: This guide describe how to install dovecot on the modoboa platform
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, installation, dovecot, mysql, postgresql, imapd'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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 "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
---
|
||||||
|
title: Guide to install modoboa with the automatic installer
|
||||||
|
description: This guide describe how to install modoboa with the automatic installer
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, installation, webserver, nginx, apache, wsgi'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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 😎
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
title: manual step to made modoboa installation
|
||||||
|
description: This guide describe all steps to install modoboa
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, installation, postfix, dovecot, opendkim, amavis, radicale, nginx'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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)
|
||||||
@@ -0,0 +1,326 @@
|
|||||||
|
---
|
||||||
|
title: manual step to install core component on modoboa
|
||||||
|
description: This guide describe how to install core on the modoboa platform
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, installation, core, mysql, postgresql, cron'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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.
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
---
|
||||||
|
title: manual step to install opendkim component on modoboa
|
||||||
|
description: This guide describe how to install opendkim on the modoboa platform
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, installation, opendkim, mysql, postgresql, dkim'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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`.
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
---
|
||||||
|
title: manual step to install postfix component on modoboa
|
||||||
|
description: This guide describe how to install postfix on the modoboa platform
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, installation, postfix, mysql, postgresql, smtp, alias, relay, virtual'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
---
|
||||||
|
title: manual step to install radicale component on modoboa
|
||||||
|
description: This guide describe how to install radicale on the modoboa platform
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, installation, radicale, oauth2'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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).
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
title: Requirements to install Modoboa on a server
|
||||||
|
description: Minimal requirements to install Modoboa on a server
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, installation, requirements, cpu, ram, disk, python'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
|
||||||
|
You will need a Server to perform well with at least:
|
||||||
|
|
||||||
|
- CPU: 4
|
||||||
|
- RAM: 4GB
|
||||||
|
- Disk: 10GB
|
||||||
|
- Python 3.10+
|
||||||
|
- Postgres 14+ or MariaDB 10.5+ or MySQL 8.0.11+ or sqlite3
|
||||||
|
|
||||||
|
::: 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
@@ -0,0 +1,356 @@
|
|||||||
|
---
|
||||||
|
title: manual step to install webserver component on modoboa
|
||||||
|
description: This guide describe how to install webserver on the modoboa platform
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, installation, webserver, nginx, apache, wsgi'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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.
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
---
|
||||||
|
title: Migrate to modoboa
|
||||||
|
description: Migrate from actual provider to modoboa
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, imap, migration, constraint, offlineimap'
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
```
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+1837
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 |
@@ -0,0 +1,79 @@
|
|||||||
|
---
|
||||||
|
title: How to rebuild your virtual environment
|
||||||
|
description: Procedure to repair your broken environment
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, virtualenv, broken, ubuntu'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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/)
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
title: REST API to control your Modoboa instance.
|
||||||
|
description: Guide to describe the use of the REST API to manage your modoboa instance
|
||||||
|
head:
|
||||||
|
- - meta
|
||||||
|
- name: 'keywords'
|
||||||
|
content: 'modoboa, rest api, swagger, authorization, token'
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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/*
|
||||||
|
|
||||||
|
::: warning
|
||||||
|
You need to be logged in for the API docs to show.
|
||||||
|
:::
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
|
||||||
|
* [Demo Instance](https://demo.modoboa.org/api/schema-v2/swagger/ "Demo Instance Swagger API")
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
{.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`.
|
||||||
Reference in New Issue
Block a user