- Go
- Fiber (API, middleware)
- Gorm (ORM)
- MariaDB (Database)
- Redis (Cache)
- Docker (Containerization)
- Swagger (API Documentation)
- TypeScript
- Vue.js
- Vite (Bundler)
- Tailwind (Styling)
- Docker (Containerization)
- Docker: Install Docker
- Docker Compose: Install Docker Compose
Important
Docker Mailserver officially supports Linux. If you want to run it on macOS, please read this.
cp api/.env.sample api/.env
cp app/.env.sample app/.env
cp mailserver/.env.sample mailserver/.env
mkdir -p mailserver/docker-data/dms/config/rspamd/override.d
cp mailserver/config/postfix-main.cf.sample mailserver/docker-data/dms/config/postfix-main.cf
cp mailserver/config/postfix-virtual.cf.sample mailserver/docker-data/dms/config/postfix-virtual.cf
cp mailserver/config/postfix-aliases.cf.sample mailserver/docker-data/dms/config/postfix-aliases.cf
cp mailserver/config/user-patches.sh.sample mailserver/docker-data/dms/config/user-patches.sh
cp mailserver/config/rspamd/override.d/milter_headers.conf.sample mailserver/docker-data/dms/config/rspamd/override.d/milter_headers.conf
Important
Make sure to set up the required config:
- api/.env:
DOMAINS
,SMTP_CLIENT_*
- app/src/env.json:
DOMAINS
- mailserver/.env:
HOSTNAME
- mailserver/docker-data/dms/config/postfix-virtual.cf:
@your-domain.net curl_email
cd api
docker compose up -d
cd mailserver
# localhost
docker compose up -d
# Staging|Production
docker compose -f compose.deploy.yml up -d
docker exec -it mailserver sh
# Build the db file
postmap /etc/postfix/virtual
# Update the alias table
newaliases
# Enable DKIM signing, this will output the contents of DKIM TXT DNS record (mail._domainkey.domain.com)
setup config dkim selector mail
# Restart Postfix
supervisorctl restart postfix
# Show logs
setup debug show-mail-logs
Update dkim_signing.conf:
nano docker-data/dms/config/rspamd/override.d/dkim_signing.conf
dkim_signing.conf:
# documentation: https://rspamd.com/doc/modules/dkim_signing.html
enabled = true;
sign_authenticated = true;
sign_local = true;
try_fallback = false;
use_domain = "header";
use_domain_sign_local = "header";
use_redis = false; # don't change unless Redis also provides the DKIM keys
use_esld = true;
allow_username_mismatch = true;
check_pubkey = false; # you want to use this in the beginning
domain {
domain.com {
path = "/tmp/docker-mailserver/rspamd/dkim/rsa-2048-mail-domain.com.private.txt";
selector = "mail";
}
}
Restart Mailserver:
docker compose down
docker compose up -d
Test DKIM signing with https://dkimvalidator.com:
echo "Test email" | mail -s "Test email" wyygMXeSfnzl5l@dkimvalidator.com
docker compose pull
docker compose down
docker compose up -d
nano docker-data/dms/config/postfix-virtual.cf
@domain.com curl_email
docker exec -it mailserver sh
postmap /etc/postfix/virtual
newaliases
setup config dkim selector mail domain domain.com
supervisorctl restart postfix
nano docker-data/dms/config/rspamd/override.d/dkim_signing.conf
domain.com {
path = "/tmp/docker-mailserver/rspamd/dkim/rsa-2048-mail-domain.com.private.txt";
selector = "mail";
}
docker compose down
docker compose -f compose.deploy.yml up -d
domain.com. . 14400 IN MX 10 mail.domain.com.
mail.domain.com. . 14400 IN MX 10 MAIL_SERVER_IPV4
domain.com. 3600 IN TXT "v=spf1 ip4:MAIL_SERVER_IPV4 -all"
mail.domain.com. 3600 IN TXT "v=spf1 ip4:MAIL_SERVER_IPV4 -all"
_dmarc.mail.domain.com. 3600 IN TXT v=DMARC1; p=quarantine
mail._domainkey.domain.com. 3600 IN TXT v=DKIM1;k=rsa;p=DKIM_PUBLIC_KEY
nano .env
DOMAINS=domain1.com,domain2.com
docker compose down
docker compose up -d
STAGING_VITE_DOMAINS=domain1.com,domain2.com
PROD_VITE_DOMAINS=domain1.com,domain2.com
DB backup is stored locally on the host machine in the ${HOME}/backups
directory.
cd ${HOME}/backups
gpg -o backup.tar.gz -d backup-latest.tar.gz.gpg
tar -xvf backup.tar.gz
# Stop the containers
docker compose down
# Clone the volume
docker volume create email_db_clone
docker run --rm -v email_db:/from -v email_db_clone:/to alpine sh -c "cp -a /from/. /to/"
# Remove the original volume
docker volume rm email_db
# Recreate the original volume from backup
docker run -d --name restore -v email_db:/email_db alpine
docker cp /unpacked_volume_dir/. restore:/email_db
docker stop restore && docker rm restore
# Start the containers
docker compose up -d
Run API tests:
go test ./... -v
go vet ./...
gosec ./...
Send test email:
docker exec -it mailserver sh
echo "Test email body" | mail -s "Test subject" example.alias@example.net
API docs:
http://localhost:3000/docs
Generate API docs:
cd api
swag init -g cmd/main.go
Tip
With Task, run task docs
to generate API documentation.