Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: Full Usage Guide w/ Working Examples #149

Open
coolaj86 opened this issue Jan 27, 2024 · 4 comments
Open

doc: Full Usage Guide w/ Working Examples #149

coolaj86 opened this issue Jan 27, 2024 · 4 comments

Comments

@coolaj86
Copy link

coolaj86 commented Jan 27, 2024

I just set this up for a client. This is the config we ended up going with.

  • Directory Structure
  • TLS Config via Let's Encrypt / Caddy
  • SMTP Relay Config

Directory Structure

  • caddy (for automated TLS certificates via Let's Encrypt)
  • smtprelay
/home/app/
├── .config/
│   ├── caddy/
│   │   ├── caddy.env
│   │   └── Caddyfile
│   └── smtprelay/
│       ├── allowed_users.txt
│       └── smtprelay.ini
└── .local/
    └── share/
        └── caddy/
            └── certificates/
                └── acme-v02.api.letsencrypt.org-directory/
                    └── smtp.example.com/
                        ├── smtp.example.com.crt
                        ├── smtp.example.com.json
                        └── smtp.example.com.key

Let's Encrypt TLS Certs via caddy

caddy run --config ~/.config/caddy/Caddyfile --envfile ~/.config/caddy/caddy.env
  1. Install go, xcaddy, and (optional) serviceman via https://webinstall.dev
    curl https://webi.sh/ | sh
    source ~/.config/envman/PATH.env
    
    webi go xcaddy serviceman
    source ~/.config/envman/PATH.env
  2. Build caddy with DNS support (no webserver required). Example w/ DNSimple:
    #!/bin/sh
    
    g_caddy_version='v2.7.6'
    CGO_ENABLED=0 xcaddy build "${g_caddy_version}" \
        --with github.com/caddy-dns/lego-deprecated \
        --output ~/bin/caddy-"${g_caddy_version}"-dnsimple
    
    ln -sf caddy-"${g_caddy_version}"-dnsimple ~/bin/caddy
  3. Configure caddy via ~/.config/caddy/Caddyfile:
    mkdir -p ~/.config/caddy
    touch ~/.config/caddy/caddy.env
    chmod 0600 ~/.config/caddy/caddy.env
    # note: to keep ports 80 and 443 free, use "https://smtp.example.com:1234" 
    # instead of just the hostname here
    smtp.example.com {
            tls {
                   dns lego_deprecated dnsimple
            }
    }
    
  4. Add DNSimple's ENVs to ~/.config/caddy/caddy.env:
    DNSIMPLE_OAUTH_TOKEN='dnsimple_a_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  5. Test the configuration
    caddy run --config ~/.config/caddy/Caddyfile --envfile ~/.config/caddy/caddy.env
  6. Start caddy as a service with serviceman (Linux, macOS, & Windows)
    my_app_user="$(id -u -n)"
    sudo env PATH="${PATH}" \
        serviceman add --system --cap-net-bind \
            --username "${my_app_user}" --name caddy -- \
            caddy run --config ~/.config/caddy/Caddyfile --envfile ~/.config/caddy/caddy.env
    (--cap-net-bind is only necessary if using default ports 80 & 443)

smtprelay config

smtprelay --config ~/.config/smtprelay/smtprelay.ini
  1. Create the config file ~/.config/smtprelay/smtprelay.ini:
    mkdir -p ~/.config/smtprelay/
    touch ~/.config/smtprelay/smtprelay.ini
    chmod 0600 ~/.config/smtprelay/smtprelay.ini
    ; Hostname for this SMTP server
    hostname = smtp.example.com
    
    ; File which contains username and password used for
    ; authentication before they can send mail.
    allowed_users = /home/app/.config/smtprelay/allowed_users.txt
    
    ; Networks that are allowed to send mails to us
    ; Defaults to localhost. If set to "", then any address is allowed.
    ;allowed_nets = 0.0.0.0/0 ::/0
    allowed_nets = 0.0.0.0/0
    
    ; STARTTLS and TLS are also supported but need a
    ; SSL certificate and key.
    ;listen = starttls://0.0.0.0:587 starttls://[::]:587 tls://0.0.0.0:465 tls://[::]:465
    listen = starttls://0.0.0.0:587 tls://0.0.0.0:465
    local_cert = /home/app/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/smtp.example.com/smtp.example.com.crt
    local_key  = /home/app/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/smtp.example.com/smtp.example.com.key
    
    ; Enforce encrypted connection on STARTTLS ports before
    ; accepting mails from client.
    local_forcetls = true
    
    ; Relay Config (ex: Mailgun)
    remotes = starttls://user:[email protected]:587
  2. Set permissions via ~/.config/smtprelay/allowed_users.txt:
    # go run ./smtprelay/cmd/hasher.go 'my-password'
    # <username> <bcrypt-hash> <email,list>
    my-username $2a$10$uZntKVdnFmAZiswYLTl8auUUxeH4wOnAU5C4zz3rGWvMf2iOmhcDy @account.example.com,[email protected]
    
  3. Test the config
    smtprelay --config ~/.config/smtprelay/smtprelay.ini
  4. Test with Curl
    my_smtprelay_host=smtp.example.com
    my_smtprelay_auth='my-user:my-pass'
    
    my_from="[email protected]"
    my_to="[email protected]"
    my_subject='Hello, World!'
    my_ts="$(date '+%F %H:%M:%S')"
    my_text="It's ${my_ts}. Do you know where your emails are?"
    
    my_file="$(mktemp)"
    printf 'From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s\r\n' \
            "${my_from}" \
            "${my_to}" \
            "${my_subject}" \
            "${my_text}" \
            > "${my_file}"
    # requires tls on 465
    curl -v --url "smtps://${my_smtprelay_host}" \
      --ssl-reqd \
      --user "${my_smtprelay_auth}" \
      --mail-from "${my_from}" \
      --mail-rcpt "${my_to}" \
      --upload-file "${my_file}"
  5. Start as a system service with serviceman:
    my_app_user="$( id -u -n )"
    sudo env PATH="${PATH}" \
     serviceman add --system --cap-net-bind \
         --username "${my_app_user}" --name smtprelay -- \
         smtprelay --config ~/.config/smtprelay/smtprelay.ini
@joshuataylor
Copy link

This is great, thanks!

Also, if you want to test SMTP directly, swaks is a great tool for this, comes in most distro repositories I believe.

When using startls (port 587 etc), you need to add --tls:

swaks --to [email protected] --from [email protected] --port 587 --tls

When testing user authentication:

swaks --to [email protected] --from [email protected] --auth-user yourusername --auth-password yourpassword --port 587 --tls

When testing a specific IP/interface, add --server 127.0.0.1, where 127.0.0.1 is the IP.

@airbornelamb
Copy link

@coolaj86 How are you shipping logs? This is the first time i've used serviceman and journalctl -xef --unit smtprelay.service is showing great output but strangely /var/log/smtprelay is an empty folder.

@joshuataylor
Copy link

If it works with systemd you could just use StandardOutput/Standard error in your service file to log to file.

Depending what you mean by shipping logs but depending what you're trying to do it might be easier to hook into joirnalctl vs writing to file.

@airbornelamb
Copy link

Thanks! Here's what I did if it helps other people:
sudo vi /etc/systemd/system/smtprelay.service

[Service]
StandardOutput=append:/var/log/smtprelay/service.log
StandardError=append:/var/log/smtprelay/service_error.log

touch /var/log/smtprelay/service.log
touch /var/log/smtprelay/service_error.log
sudo systemctl reload smtprelay.service

Then added /var/log/smtprelay/*.log as a folder to look for in my collector configuration and it started picking it up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants