Home fit for a mailbox

This is a follow up (part 8) to Sent from my terminal.

Typically, you would build a mailbox to make it easier to communicate to and from your home. Here, I've build this website as a home for my mailbox.

The Minimum viable email service I have been working on now has a new home and a new name to go with it: the basic echo.ls email service (BEES). Since I went through the effort of re-deploying everything, I figured I may as well document the process. Although the instruction set below is specific to my server, it can be easily generalized for any aspiring email-preneurs.

How to deploy an email server

  1. Obtain a server that can serve on ports :25, :110, and :587 (many VPS providers block these ports to prevent spam and domain reputation harm)
  2. Replace hardcoded values (particularly echo.ls in include/config.h)
  3. Clone the repo to your server at /opt/bees/
  4. Build: make clean all
  5. (Optional) Test: make test
  6. Add local users

    Write a new line to local_users.txt for each user in the format of [username]:[password].

  7. Generate self trusted cert

    openssl req -x509 -newkey rsa:2048 \
      -keyout tls_key.pem \
      -out tls_cert.pem \
      -days 365 \
      -nodes \
      -subj "/CN=mail.echo.ls"
    
  8. Generate DKIM key

    openssl genrsa -out dkim_private.pem 2048
    openssl pkey -in dkim_private.pem -pubout -out dkim_public.pem
    
  9. Generate SPF, DKIM, and DMARC records

    sh ./scripts/print_mail_dns_records.sh
    
  10. Set SPF, DKIM, and DMARC records for your domain's DNS (from previous step)
  11. Set A and MX record for your domain's DNS

    mail.echo.ls.		60	IN	A	96.126.120.46
    

    and

    echo.ls.		600	IN	MX	10 mail.echo.ls.
    

    Make sure to use your server's public IP address for the A record.

  12. Set a PTR (rDNS) record with your hosting provider
  13. Setup systemd service to run the server

    Put this file in /etc/systemd/system/bees.service:

    [Unit]
    Description=BEES service
    
    # wait for networking
    Wants=network-online.target
    After=network-online.target
    
    [Service]
    Type=simple
    
    # working directory and executable path
    WorkingDirectory=/opt/bees
    ExecStart=/opt/bees/build/bees
    
    # restarts
    Restart=on-failure
    RestartSec=5
    
    [Install]
    # start on boot
    WantedBy=multi-user.target
    
  14. Reload systemctl: systemctl daemon-reload
  15. Restart BEES: systemctl restart bees
  16. (Optional) Check service status: systemctl status bees
  17. (Optional) Check logs: journalctl -u bees -f
  18. (Optional) Setup mpop as a POP3 client

    Write config to ~/.mpoprc:

    defaults
    tls on
    tls_trust_file [local path to tls_cert.pem, required for TLS with self-signed cert]
    auth user
    
    account [username]
    host mail.echo.ls
    port 110
    user [username]
    password [password]
    delivery maildir ~/Maildir
    keep on
    
    account default : [username]
    
  19. (Optional) Setup msmtp as a SMTP client

    Write config to ~/.msmtprc:

    account [username]
    host mail.echo.ls
    port 587
    from [username]@echo.ls
    auth on
    user [username]
    password [password]
    tls on
    tls_starttls on
    tls_trust_file [local path to tls_cert.perm]
    
    account default : [username]
    
  20. (Optional) Setup client cron job to autofetch mail

    Open cron job editor (crontab -e) then add the following to run mpop once ever five minutes:

    */5 * * * * /usr/bin/mpop >/dev/null 2>&1
    
  21. (Optional) Send an email

    echo "Subject: Test\n\nHello world" | msmtp alice@echo.ls
    

Last updated May 16, 2026