|Nick Thomas 08d80cc661|
Simple self-hosted email
Not all features are implemented. See the features board for more details of current status.
- 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 firstname.lastname@example.org - 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:
- Send just this email
- Whitelist shady.net (pins certificate)
- What other interactions might we like?
- Use HTTPS links instead of emails?
- 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)
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:
(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
Probably other stuff. Email is big, and just keeps getting bigger.
Copyright (C) 2018 Nick Thomas email@example.com
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/.
Contributions are very welcome. Feel free to open a merge request against the GitLab hosted project, 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
- Indicate acceptance of the above with a
Signed-off-by:line in each commit message
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
CapabilityBoundingSet=CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_BIND_SERVICE NoNewPrivileges=true
If you're doing this, you may also want to set:
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
$ crockery \ --home <home-directory> \ init \ --domain <domain-name> \ --cert <cert-file> \ --key <key-file> \ --postmaster-password <password>
Run the server
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
Mostly non-existent, aside from that listed above.
We'll need to have a few offline commands baked into the
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,