setting up an email server with opensmtpd+dovecot+postgresql
today, i'm going to talk on how to set up an email server with the components explained above

your requirements will be: – access to alter rDNS of ur IP (tl;dr: set it to ur domain) – a domain that you can manage via DNS – a debian/openbsd server – a public IP address – a server that can serve port 25 (important: CONSULT to your ISP/VPS provider's ToS)
what we gonna do (in order so you won't cry): – set up dns – configure spf – configure dkim – step 1: make le key – step 2: make le DNS record – configure dmarc – get the server software working – prepare le postgresql database – prepare le mailbox – configure le opensmtpd – configure le rspamd – tool for inbox (dovecot)
set up the DNS first.
this part, we will configure these two things: – [required] SPF: basically a policy that tells a mail server, what mailer IP is allowed to send as your domain – [required] DKIM: ur key for signing ur mail on your domain behalf so anyone can't spoof their mail with your domain – [optional] DMARC: final verifier after SPF and DKIM
spf: the easiest thing to setup
assuming you have the following public IP address (that's also used as an ip used to relay ur mail to other email server):
– ipv4: 203.0.113.5
– ipv6: 2001:db8::5
and then assuming your domain is waltuh.cyou,
you set a TXT record in ur domain's DNS. It should look like this:
v=spf1 mx ip4:203.0.113.5 ip6:2001:db8::5 -all
or if you only have ipv4:
v=spf1 mx ip4:203.0.113.5 -all
that's it. now let's continue
dkim: “this is my signature. i am real.”
step 1: make le key
get into ur server's shell, and go make a directory at /etc/mail/dkim.
go here, assuming ur current dir is now /etc/mail/dkim, do this:
openssl genpkey -algorithm ed25519 -outform PEM -out waltuh.cyou-ed25519.key
this will make a key under path /etc/mail/dkim/waltuh.cyou-ed25519.key. you can adjust it accordingly to ur use.
then, make the string of le dns TXT DKIM record:
printf "v=DKIM1;k=ed25519;p=%s" "$(openssl pkey -outform DER -pubout -in waltuh.cyou-ed25519.key | tail -c +13 | openssl base64)"
it should look like this:
v=DKIM1;k=ed25519;p=tM22KunOkYfEtLzvaUQQcwjUGw8c6hg/v24gIa46oSY=
step 2: make le DNS record
before we continue, you need to know this: so, in dkim, there's something called selector. you can, basically use it as a versioning of ur dkim. this will be important on both dns, and ur smtp server, especially when you're rerolling ur dkim key.
so, for dns, You must make a DNS record at <selector>._domainkey.waltuh.cyou (assuming ur domain is waltuh.cyou)
now, assuming our selector is mail2026, that would be mail2026._domainkey.waltuh.cyou.
so, make a TXT record here, put the previously generated DKIM pubkey that looked like this before:
v=DKIM1;k=ed25519;p=tM22KunOkYfEtLzvaUQQcwjUGw8c6hg/v24gIa46oSY=
now save it.
please rember the selector.
dmarc: “if spf fail, or dkim fail, what should i do?”
it's basically that.
It does stuff when SPF and DKIM are not valid,
this is optional, but i suggest you to use it.
You just put this DNS record into your domain, Specifically, _dmarc subdomain containing a TXT record that writes:
v=DMARC1; p=reject; rua=mailto:dmarc@waltuh.cyou
and then just apply it, Say, on _dmarc.waltuh.cyou
That's basically it.

get the server software working
oh?
you finished the warmup?
OMEDETOU
now, i will just be quick here. Assuming you have debian or openbsd host, You need to install these:
- opensmtpd
- opensmtpd-filter-dkimsign
- opensmtpd-filter-rspamd
- opensmtpd-table-postgres
- dovecot-core
- dovecot-imapd
- dovecot-lmtpd
- dovecot-pop3d
- dovecot-sieve
- dovecot-pgsql
or,
apt install opensmtpd{,-filter-{dkimsign,rspamd},table-postgres} dovecot-{core,imapd,lmtpd,pop3d,sieve,pgsql} postgresql{,-contrib}
prepare le postgresql database
go start the postgresql database server (haven't init ur db? go init it first), then make le db for opensmtpd:
sudo -Hu postgres psql
then
CREATE USER opensmtpd WITH PASSWORD 'thestrong9stpassw0rd!';
CREATE DATABASE opensmtpdb OWNER opensmtpd;
\c opensmtpdb
CREATE TABLE virtuals (
id SERIAL,
email VARCHAR(255) NOT NULL DEFAULT '',
destination VARCHAR(255) NOT NULL DEFAULT ''
);
CREATE TABLE credentials (
id SERIAL,
email VARCHAR(255) NOT NULL DEFAULT '',
password VARCHAR(255) NOT NULL DEFAULT ''
);
CREATE TABLE users (
id SERIAL,
username VARCHAR(255) NOT NULL DEFAULT '',
email VARCHAR(255) NOT NULL DEFAULT ''
)
yea. copy and paste w o k s
then, quit le psql by CTRL+C, open ur editor, can be nano in ur server, write this to initsetup.sql:
insert into virtuals (email, destination) values ('root', 'yonle@waltuh.cyou');
insert into virtuals (email, destination) values ('postmaster@waltuh.cyou', 'root');
insert into virtuals (email, destination) values ('webmaster@waltuh.cyou', 'root');
insert into virtuals (email, destination) values ('abuse@waltuh.cyou', 'root');
insert into virtuals (email, destination) values ('dmarc@waltuh.cyou', 'root');
insert into virtuals (email, destination) values ('yonle@waltuh.cyou', 'vmail');
insert into users (username, email) values ('yonle@waltuh.cyou', 'yonle@waltuh.cyou');
insert into users (username, email) values ('noreply@waltuh.cyou', 'noreply@waltuh.cyou');
insert into credentials (email, password) values ('yonle@waltuh.cyou', '$2b$...');
insert into credentials (email, password) values ('noreply@waltuh.cyou', '$2b$...');
the virtuals is an alias of your email address. To put it simply, If one sends an email to abuse@waltuh.cyou, It will gets delivered to yonle@waltuh.cyou. Cool right?
when the virtual address got vmail in the end, it then gets delivered to your inbox, marking the end of the alias venture. for example, if yonle@waltuh.cyou alias is vmail, that means the mail will be delivered to an mailbox specifically for yonle@waltuh.cyou.
adjust it according to your use, then
sudo -Hu postgres psql -d opensmtpd -f initsetup.sql
you wonder about password hashing? it must be in bcrypt. google how to generate a blowfish hash, coz there's so many out here.
but i don't wanna
OKAY, OKAY, YOU FUCK. GO INSTALL A GO COMPILER, MAKE A FOLDER, OPEN A EDITOR, WRITE THIS CODE:
package main
import (
"fmt"
"golang.org/x/crypto/bcrypt"
"os"
)
func main() {
if len(os.Args) != 2 {
panic("give me password.")
}
hash, _ := bcrypt.GenerateFromPassword([]byte(os.Args[1]), 12)
fmt.Println(string(hash))
}
then, compile it
go mod init a
go mod tidy
go build -o gen
and do your thing
./gen 'yourstr0ng9stp4ssw0rd!'
it will emit, like this:
$2a$12$wrhwp/F/vakmnznJvDyrfOlNzKVZYtOY05CMBcvVQi8LOmEJimLI6
prepare le mailbox
tl;dr:
useradd -m -r -u 5000 -g mail -d /var/vmail -s /sbin/nologin vmail
# Make sure the mail directory exists
sudo mkdir -p /var/vmail
sudo chown -R vmail:mail /var/vmail
sudo chmod -R 700 /var/vmail
configure le opensmtpd
in debian, the config is located at /etc/smtpd.conf.
in openbsd, it's at /etc/mail/smtpd.conf.
but the tl;dr: go use my config here.
and then, go to /etc/mail
make the following files:
– hosts: a file listing the IPs that you will use for relaying email to outside
– mailname: ur mail name
– postgresql.conf: configuration for opensmtpd to connect to ur postgresql
you can check for the examples here.
before we start our opensmtpd, first,
configure le rspamd.
just, go use my config here in ur /etc/rspamd/local.d/settings.conf.
then start ur rspamd, systemctl enable --now rspamd
before we be all good and all,
chown _dkimsign:_dkimsign /etc/mail/dkim/waltuh.cyou-ed25519.key
also, ensure that ur ssl keys are owned by root. if not, opensmtpd won't start.
finally, start ur opensmtpd. systemctl enable --now opensmtpd
if everything goes smooth, congratulations,
You just started ur first mail server!
tool for inbox (dovecot)
this is your final part, before you finally able to go to rest.
it's just 2 deadass simple config. go check my config here.
you will then just need to alter psql connection in local.conf before you start dovecot server by running systemctl enable --now dovecot
finally,
go try connect ur email server and try send email.
be note though, sending email to gmail or yahoo or outlook might make ur mail to be ended up in spam folder at first & this is normal. you just need to make ur ip & domain rep to be good and you're all good to go. The button [Report as not spam] is a thing for the purpose.
alright. hope this helps you.
bye.