1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
---
title: >-
Setting Up maddy On A VPS
description: >-
We have delivery!
tags: tech
series: selfhost
---
In the previous post I left off with being blocked by my ISP from sending
outbound emails on port 25, effectively forcing me to set up [maddy][maddy] on a
virtual private server (VPS) somewhere else.
After some research I chose [Vultr][vultr] as my VPS of choice. They apparently
don't block you from sending outbound emails on port 25, and are in general
pretty cheap. I rented their smallest VPS server for $5/month, plus an
additional $3/month to reserve an IPv4 address (though I'm not sure I really
need that, I have dDNS set up at home and could easily get that working here as
well).
## TLS
The first major hurdle was getting TLS certs for `mydomain.com` (not the real
domain) onto my Vultr box. For the time being I've opted to effectively
copy-paste my local [LetsEncrypt][le] setup to Vultr, using certbot to
periodically update my records using DNS TXT challenges.
The downside to this is that I now require my Cloudflare API key to be present
on the Vultr box, which effectively means that if the box ever gets owned
someone will have full access to all my DNS. For now I've locked down the box as
best as I can, and will look into changing the setup in the future. There's two
ways I could go about it:
* SCP the certs from my local box to the remote everytime they're renewed. This
would require setting up a new user on the remote box with very narrow
privileges. This isn't the worst thing though.
* Use a different challenge method than DNS TXT records.
But again, I'm trying to set up maddy, not LetsEncrypt, and so I needed to move
on.
## Deployment
In the previous post I talked about how I'm using nix to generate a systemd
service file which encompasses all dependencies automatically, without needing
to install anything to the global system or my nix profile.
Since that's already been set up, it's fairly trivial to use `nix-copy-closure`
to copy a service file, and _all_ of its dependencies (including configuration)
from my local box to the remote Vultr box. Simply:
```
nix-copy-closure -s <ssh host> <nix store path>
```
I whipped up some scripts around this so that I can run a single make target and
have it build the service (and all deps), do a `nix-copy-closure` to the remote
host, copy the service file into `/etc/systemd/service`, and restart the
service.
## Changes
For the most part the maddy deployment on the remote box is the same as on the
local one. Down the road I will likely change them both significantly, so that
the remote one only deals with SMTP (no need for IMAP) and the local one will
automatically forward all submitted messages to it.
Once that's done, and the remote Vultr box is set up on my [nebula][nebula]
network, there won't be a need for the remote maddy to do any SMTP
authentication, since the submission endpoint can be made entirely private.
For now, however, I've set up maddy on the remote box's public interface with
SMTP authentication enabled, to make testing easier.
## Testing
And now, to test it! I changed the SMTP credentials in my `~/.mailrc` file as
appropriate, and let a test email rip:
```
echo 'Hello! This is a cool email' | mailx -s 'Subject' -r 'Me <me@mydomain.com>' 'test.email@gmail.com'
```
This would, ideally, send an email from my SMTP server (on my domain) to a test
gmail domain. Unfortunately, it did not do that, but instead maddy spit this out
in its log:
> maddy[1547]: queue: delivery attempt failed {"msg_id":"330a1ed9","rcpt":"mediocregopher@gmail.com","reason":"[2001:19f0:5001:355a:5400:3ff:fe73:3d02] Our system has detected that\nthis message does not meet IPv6 sending guidelines regarding PTR\nrecords and authentication. Please review\n https://support.google.com/mail/?p=IPv6AuthError for more information\n. gn42si18496961ejc.717 - gsmtp","remote_server":"gmail-smtp-in.l.google.com.","smtp_code":550,"smtp_enchcode":"5.7.1","smtp_msg":"gmail-smtp-in.l.google.com. said: [2001:19f0:5001:355a:5400:3ff:fe73:3d02] Our system has detected that\nthis message does not meet IPv6 sending guidelines regarding PTR\nrecords and authentication. Please review\n https://support.google.com/mail/?p=IPv6AuthError for more information\n. gn42si18496961ejc.717 - gsmtp"}
Luckily Vultr makes setting up PTR records for reverse DNS fairly easy. They
even allowed me to do it on my box's IPv6 address which I'm not paying to
reserve (though I'm not sure what the long-term risks of that are... can it
change?).
Once done, I attempted to send my email again, and what do you know...
![Success!](/assets/maddy-vps/success.png)
Success!
So now I can send emails. There are a few next steps from here:
* Get the VPS on my nebula network and lock it down properly.
* Fix the TLS cert situation.
* Set up the remote maddy to forward submissions to my local maddy.
* Use my sick new email!
[maddy]: https://maddy.email
[le]: https://letsencrypt.org/
[vultr]: https://www.vultr.com/
[nebula]: https://github.com/slackhq/nebula
|