207 lines
6.5 KiB
Markdown
207 lines
6.5 KiB
Markdown
# Crockery - simple email hosting
|
|
|
|
## What
|
|
|
|
* Email!
|
|
* Devoted to the task of being a vertically-integrated email solution for a single domain
|
|
* SMTP+IMAP email, autodiscovery, and bundled HTTP(S) webmail client
|
|
* Can get its own valid TLS certificates via LE, or use supplied ones
|
|
* Built-in anti-spam & anti-virus measures
|
|
* Built-in DKIM support
|
|
* Built-in DMARC support
|
|
* Can tell you what DNS records you need, and check them for validity
|
|
* Multiple email accounts for your domain
|
|
* A "master" wildcard account (if desired)
|
|
* Simple import from GMail, etc
|
|
* Simple export to GMail, etc
|
|
* Nice, fast search
|
|
* Interact with crockery with simple, natural-ish emails to do things
|
|
* SMTP TLS verification - enabled by default
|
|
* Try to email foo@shady.net - verification fails, email marked pending, fail in 7 days
|
|
* Crockery emails user, "Yo. We can't send this email securely. Here are your options:"
|
|
* User hits reply-to (goes to unique email address on same domain) saying what to do:
|
|
* Cancel
|
|
* Retry
|
|
* Send just this email
|
|
* Whitelist shady.net (pins certificate)
|
|
* What other interactions might we like?
|
|
* Use HTTPS links instead of emails?
|
|
|
|
## What not
|
|
|
|
* JMAP. Not today.
|
|
* Bring your own X (where X is MTA, IMAP server, database, etc, etc)
|
|
* Multiple-domain support (maaaaaaaaaaaaybe later)
|
|
* CalDAV/Carddav (yet)
|
|
* Externally sourced accounts (yet)
|
|
* Sending email without having an account
|
|
* Managesieve (for now)
|
|
|
|
## Why
|
|
|
|
Email architecture is really complicated, and setting up a mail server of your
|
|
own is painful. Various projects exist to try to make it easier, eg:
|
|
|
|
* iRedMail
|
|
* docker-mailserver
|
|
* symbiosis
|
|
* ...
|
|
|
|
(Personally, I had some ansible recipes!)
|
|
|
|
Even among people who run their own websites, it's rare to run your own email.
|
|
It's just too painful. Much of this pain is caused by ultra-configurable
|
|
components that need to be orchestrated. Each has its own (remarkably obtuse)
|
|
configuration language, and each can do far more than the common case for a
|
|
small, single-domain site.
|
|
|
|
So, let's make a single binary where all you have to do is:
|
|
|
|
* Register a domain
|
|
* Upload some DNS records
|
|
* Run the binary
|
|
|
|
and it gives you a sensible email setup without any additional configuration!
|
|
|
|
If it has to share the domain with a HTTP server (quite common), allow the
|
|
HTTP-specific parts of mail to be served via reverse proxying. This includes:
|
|
|
|
* activesync push notifications
|
|
* autodiscovery
|
|
|
|
Probably other stuff. Email is big, and just keeps getting bigger.
|
|
|
|
## Licensing
|
|
|
|
Copyright (C) 2018 Nick Thomas <crockery@ur.gs>
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of version 3 of the GNU Affero General Public License
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
## Contributing
|
|
|
|
Contributions are very welcome. Feel free to open a merge request against
|
|
[the GitLab hosted project](https://gitlab.com/lupine/crockery), or to email
|
|
patches or a link to a hosted git branch, directly to the author.
|
|
|
|
To be accepted, contributions must:
|
|
|
|
* Accept copyright assignment to the author
|
|
* Be licensed according to the foregoing terms
|
|
* Consist entirely of [signed commits](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work)
|
|
* Indicate acceptance of the above with a `Signed-off-by:` line in each commit message
|
|
|
|
## How
|
|
|
|
### Building a binary
|
|
|
|
```
|
|
$ go build ur.gs/crockery/cmd/crockery
|
|
$ sudo setcap 'cap_net_bind_service=+ep' ./crockery
|
|
```
|
|
|
|
The second step allows crockery to bind to the various low-numbered ports it
|
|
needs (25, 587, 149, 993) **without** running as root. Don't bother with it if
|
|
you're going to be running crockery as root, e.g., as a container or a single-
|
|
purpose system.
|
|
|
|
You may also provide these capabilities via systemd by using lines like these in
|
|
the `[Service]` definition:
|
|
|
|
```ini
|
|
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
|
|
|
NoNewPrivileges=true
|
|
```
|
|
|
|
If you're doing this, you may also want to set:
|
|
|
|
```ini
|
|
PrivateTmp=true
|
|
PrivateDevices=true
|
|
ProtectHome=true
|
|
ProtectSystem=full
|
|
ReadWriteDirectories=/var/lib/caddy
|
|
```
|
|
|
|
TODO: write up a .service file that can be dropped in
|
|
|
|
### Initialize a new database
|
|
|
|
```
|
|
$ crockery init \
|
|
--domain <domain-name> \
|
|
--cert <cert-file> \
|
|
--key <key-file> \
|
|
--postmaster-password <password>
|
|
```
|
|
|
|
You can also provide the postmaster password in an environment variable:
|
|
|
|
```
|
|
$ CROCKERY_POSTMASTER_PASSWORD="<password>" crockery init \
|
|
--domain <domain-name> \
|
|
--cert <cert-file> \
|
|
--key <key-file>
|
|
```
|
|
|
|
By default, crockery will initialize the current user's home directory. You can
|
|
provide a custom directory to work with by specifying `--home`, e.g.:
|
|
|
|
```
|
|
$ crockery \
|
|
--home <home-directory> \
|
|
init \
|
|
--domain <domain-name> \
|
|
--cert <cert-file> \
|
|
--key <key-file> \
|
|
--postmaster-password <password>
|
|
```
|
|
|
|
### Run the server
|
|
|
|
```
|
|
./crockery run
|
|
```
|
|
|
|
Again, you can use `--home <directory>` if the default of `$HOME` doesn't suit.
|
|
Crockery will load the configuration from the database and begin serving mail
|
|
based on it. Received emails are stored in a mailbox determined by the username,
|
|
to be found in the `<home>/mailboxes` directory
|
|
|
|
### Configuration
|
|
|
|
Mostly non-existent, aside from that listed above.
|
|
|
|
We'll need to have a few *offline* commands baked into the `crockery` binary,
|
|
apart from `init` as detailed above. Some ideas:
|
|
|
|
```
|
|
$ crockery change x y z (domain, user password, etc)
|
|
$ crockery reindex [account] (throw away existing indexes, regenerate)
|
|
$ crockery whitelist tls <domain> (allow the domain to be sent to with insecure/no TLS)
|
|
$ crockery whitelist receipt <domain> (bypass antispam for this domain)
|
|
$ crockery blacklist receipt <domain> (no emails to be permitted from this domain
|
|
```
|
|
|
|
It's inconvenient for some of these functions to require the server to be
|
|
offline, so we'll need to provide another configuration interface too.
|
|
|
|
I like sending emails to it.
|
|
|
|
Since we're going to need a HTTP server anyway, we could expose admin functions
|
|
using that, if logged in as postmaster. It could also expose an API that the
|
|
`crockery X` commands could connect to, rather than hitting the store directly.
|
|
We can use the `.well-known` integration to avoid the need to configure there,
|
|
too.
|