git » chasquid » commit 2da74c1

docs: Add some documentation and a README

author Alberto Bertogli
2016-10-27 00:46:05 UTC
committer Alberto Bertogli
2016-11-03 00:51:59 UTC
parent bcea74ca81fbfd1454c6eefc53ccaf41262539e6

docs: Add some documentation and a README

README.md +161 -0
docs/flow.md +48 -0
docs/hooks.md +45 -0

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..869e00d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,161 @@
+
+# chasquid
+
+[chasquid](https://blitiri.com.ar/p/chasquid) is an SMTP (email) server.
+
+It aims to be easy to configure and maintain for a small mail server, at the
+expense of flexibility and functionality.
+
+It's written in [Go](https://golang.org).
+
+
+## Features
+
+* Easy to configure, hard to mis-configure in ways that are harmful or
+  insecure (e.g. no open relay, clear-text authentication, etc.).
+* Tracking of per-domain TLS support, prevents connection downgrading.
+* SMTP UTF8 (international usernames).
+* IDNA (international domain names).
+* Hooks for easy integration with greylisting, anti-virus and anti-spam.
+* Multiple domains, with per-domain user database and aliases.
+* Multiple TLS certificates.
+* Suffix dropping (user+something@domain -> user@domain).
+* Easy integration with letsencrypt.
+* SPF checking.
+* Monitoring HTTP server, with exported variables and tracing to help
+  debugging.
+
+
+The following are intentionally *not* implemented:
+
+* Custom email routing and transport.
+* DKIM/DMARC checking (although the post-data hook can be used for it).
+* Different backends for domain and user configuration (Dovecot authentication
+  may be implemented in the future).
+
+
+## Status
+
+chasquid is in beta.
+
+It's functional and has had some production exposure, but some things may
+still change in backwards-incompatible way, including the configuration format.
+It should be rare and will be avoided if possible.
+
+You should subscribe to the mailing list to get notifications of such changes.
+
+
+## Contact
+
+If you have any questions, comments or patches please send them to the mailing
+list, chasquid@googlegroups.com.
+
+To subscribe, send an email to chasquid+subscribe@googlegroups.com.
+
+You can also browse the
+[archives](https://groups.google.com/forum/#!forum/chasquid).
+
+
+
+## Installation
+
+To get the code and build it, you will need a working [Go](http://golang.org)
+environment.
+
+```shell
+# Get the code and build the binaries.
+go get blitiri.com.ar/go/chasquid
+cd "$GOPATH/src/blitiri.com.ar/go/chasquid"
+make
+
+# Install the binaries to /usr/local/bin.
+sudo make install-binaries
+
+# Copy the example configuration to /etc/chasquid and /etc/systemd, and create
+# the /var/lib/chasquid directory.
+sudo make install-config-skeleton
+```
+
+## Configuration
+
+The configuration is in `/etc/chasquid/` by default, and has the following
+structure:
+
+```
+- chasquid.conf      Main config file.
+
+- domains/           Domains' data.
+  - example.com/
+    - users          User and password database for the domain.
+    - aliases        Aliases for the domain.
+  ...
+
+- certs/             Certificates to use, one dir per pair.
+  - mx.example.com/
+    - fullchain.pem  Certificate (full chain).
+    - privkey.pem    Private key.
+  ...
+```
+
+Note the certs/ directory matches certbot's structure, so if you use it you
+can just symlink to /etc/letsencrypt/live.
+
+Make sure the user you use to run chasquid under ("mail" in the example
+config) can access the certificates and private keys.
+
+
+### Adding users
+
+You can add users with:
+
+```
+chasquid-util user-add user@domain
+```
+
+This will also create the corresponding domain directory if it doesn't exist.
+
+
+### Checking your configuration
+
+Run `chasquid-util print-config` to parse your configuration and display the
+resulting values.
+
+
+### Checking your setup
+
+Run `smtp-check yourdomain.com`, it will check:
+
+* MX DNS records.
+* SPF DNS records (will just warn if not present).
+* TLS certificates.
+
+It needs to access port 25, which is often blocked by ISPs, so it's likely
+that you need to run it from your server.
+
+
+### Greylisting, anti-spam and anti-virus
+
+chasquid supports running a post-DATA hook, which can be used to perform
+greylisting, and run anti-spam and anti-virus filters.
+
+The hook should be at `/etc/chasquid/hooks/post-data`.
+
+
+The one installed by default is a bash script supporting:
+
+* greylisting using greylistd.
+* anti-spam using spamassassin.
+* anti-virus using clamav.
+
+To use them, they just need to be available in your system.
+
+For example, in Debian you can run the following to install all three:
+
+  apt install greylistd spamc clamdscan
+  usermod -a -G greylist mail
+
+
+Note that the default hook may not work in all cases, it is provided as a
+practical example but you should adjust it to your particular system if
+needed.
+
diff --git a/docs/flow.md b/docs/flow.md
new file mode 100644
index 0000000..f3d2e98
--- /dev/null
+++ b/docs/flow.md
@@ -0,0 +1,48 @@
+
+# Message flows
+
+This document explains at a high level some parts of chasquid's message
+processing, in particular how messages flow through the system.
+
+
+## Message reception
+
+- Client connects to chasquid on the smtp or submission ports, and issues
+  HELO/EHLO.
+- Client optionally performs STARTTLS.
+- Client optionally performs AUTH.
+    - Check that this is done over TLS.
+- Client sends MAIL FROM.
+    - Check SPF.
+    - Check connection security level.
+- Client sends one or more RCPT TO.
+    - If the destination is remote, then the user must have authenticated.
+    - If the destination is local, check that the user exists.
+- Client sends DATA.
+- Client sends actual data, and ends it with '.'
+    - Run the post-data hook. If the hook fails, return an error.
+    - Parse the data contents to perform loop detection.
+    - Add the required headers (Received, SPF results, post-data hook output).
+    - Put it in the queue and reply success.
+
+
+## Queue processing
+
+Before accepting a message:
+
+- Create a (pseudo) random internal ID for it.
+- For each recipient, use the alias database to expand it, add the results to
+  the list of final recipients (which may not be email).
+- Save the resulting envelope (with the final recipients) to disk.
+
+Queue processing runs asynchronously, there's a goroutine for each message
+which does, in a loop:
+
+- For each recipient which we have not delivered yet:
+    - Attempt delivery.
+    - Write to disk the results.
+- If there are mails still pending, wait for some time (incrementally).
+- When all the recipients have completed delivery, or enough time has passed:
+    - If all were successful, remove from the queue.
+    - If some failed, send a delivery status notification back to the sender.
+
diff --git a/docs/hooks.md b/docs/hooks.md
new file mode 100644
index 0000000..d84442b
--- /dev/null
+++ b/docs/hooks.md
@@ -0,0 +1,45 @@
+
+# Post-DATA hook
+
+After completion of DATA, but before accepting the mail for queueing, chasquid
+will run the command at `$config_dir/hooks/post-data`.
+
+The contents of the mail will be written to the command's stdin, and the
+environment is detailed below.
+
+If the exit status is 0, chasquid will move forward processing the command,
+and its stdout should contain headers which will be added to contents of
+the email (at the top).
+
+Otherwise, chasquid will respond with an error, and the last line of stdout
+will be passed back to the client as the error message.
+If the exit status is 20 the error code will be permanent, otherwise it will
+be temporary.
+
+
+This hook can be used to block based on contents, for example to check for
+spam or virus.  See `etc/hooks/post-data` for an example.
+
+
+## Environment
+
+This hook will run as the chasquid user, so be careful about permissions and
+privileges.
+
+The environment will contain the following variables:
+
+ - USER
+ - SHELL
+ - PATH
+ - PWD
+ - REMOTE_ADDR
+ - MAIL_FROM
+ - RCPT_TO (space separated)
+ - AUTH_AS (empty if not completed AUTH)
+ - ON_TLS (0 if not, 1 if yes)
+ - FROM_LOCAL_DOMAIN (0 if not, 1 if yes)
+ - SPF_PASS (0 if not, 1 if yes)
+
+There is a 1 minute timeout for hook execution.
+It will be run at the config directory.
+