Frequently Asked Questions

ulaknode

  • 🔗 What is ulaknode and how does it differ from hosted email services? â–¼

    ulaknode is a free, self-hosted email server for Linux distributed as a single Docker container. It bundles four production-grade components into one cohesive package:

    • Postfix — SMTP mail transfer
    • Dovecot — IMAP mailbox access
    • Rspamd — spam filtering, DKIM signing, and DMARC enforcement
    • ClamAV — antivirus scanning of attachments

    Unlike hosted services such as Google Workspace or Microsoft 365, ulaknode gives you complete control over your data. There are no per-user or per-mailbox fees, and you are not subject to a third-party provider's terms of service, storage limits, or data-residency policies. The trade-off is that you are responsible for operating the Linux host it runs on.

  • 🔗 What are the system requirements for running ulaknode? â–¼

    ulaknode requires a Linux server (physical, VM, or VPS) with Docker installed. Minimum recommended specifications for a small organisation:

    • CPU: 2 vCPUs
    • RAM: 2 GB (4 GB recommended — ClamAV alone loads ~1 GB of virus definitions into memory)
    • Disk: 20 GB for the OS and container image, plus mailbox storage as needed
    • Network: A static public IP address and a fully-qualified domain name (FQDN) with a matching reverse DNS (PTR) record

    Port 25 (SMTP) must be open outbound. Many cloud providers block port 25 by default — check with your hosting provider before deploying.

  • 🔗 How do I start ulaknode? â–¼

    ulaknode ships with a docker-compose.yml. Set the MAIL_HOSTNAME environment variable to your mail server's FQDN, then start the container:

    MAIL_HOSTNAME=mail.yourdomain.com docker compose up -d

    On first boot the container seeds all configuration volumes from the image defaults and applies your hostname automatically. Services start in dependency order: ClamAV → Redis → Rspamd → Postfix → Dovecot.

    ClamAV loads its full signature database (~1 GB) during startup. Wait about a minute before testing mail flow after a fresh start or restart.

    To check the version of all bundled components:

    docker exec ulaknode ulaknode-version
  • 🔗 What DNS records do I need to set up before going live? â–¼

    Correct DNS configuration is essential for mail deliverability. You need at minimum:

    • MX record — points your domain to your mail server hostname, e.g. mail.yourdomain.com
    • A record — resolves mail.yourdomain.com to your server's public IP
    • PTR record (reverse DNS) — resolves your public IP back to mail.yourdomain.com; configured with your hosting or ISP provider
    • SPF TXT record — use ulaknode-spf generate to produce the correct value (see the SPF FAQ below)
    • DKIM TXT record — use ulaknode-dkim show to retrieve the value to publish (see the DKIM FAQ below)
    • DMARC TXT record — use ulaknode-dmarc generate to produce the correct value (see the DMARC FAQ below)

    Missing or incorrect PTR and SPF records are the most common reason legitimate mail is rejected by major providers. Verify all records with a tool such as MXToolbox after deployment.

  • 🔗 How do I configure DKIM signing? â–¼

    ulaknode includes the ulaknode-dkim tool that manages DKIM keys and updates Rspamd's signing configuration automatically.

    1. Generate a 2048-bit RSA key pair for your domain:

    docker exec ulaknode ulaknode-dkim generate yourdomain.com

    The default selector is mail. You can pass a custom selector as a second argument.

    2. Retrieve the DNS TXT record to publish:

    docker exec ulaknode ulaknode-dkim show yourdomain.com

    The output shows the exact TXT record to add to your DNS zone, in the form:

    mail._domainkey.yourdomain.com  IN TXT  "v=DKIM1; k=rsa; p=<public-key>"

    3. Restart Rspamd to apply the new key:

    docker exec ulaknode ulaknode-service restart rspamd

    Other useful commands:

    # List all DKIM keys
    docker exec ulaknode ulaknode-dkim list
    
    # Remove a key
    docker exec ulaknode ulaknode-dkim remove yourdomain.com mail

    After DNS propagation, verify signing with mail-tester.com — look for DKIM=pass in the received headers.

  • 🔗 How do I generate an SPF record? â–¼

    The ulaknode-spf tool generates a ready-to-publish SPF TXT record and can also look up what is currently published in DNS.

    Basic SPF using the domain's own MX hosts (recommended starting point):

    docker exec ulaknode ulaknode-spf generate yourdomain.com --mx

    Add a specific IP address and use a strict fail policy:

    docker exec ulaknode ulaknode-spf generate yourdomain.com --mx --ip4 203.0.113.10 --all fail

    Authorize an external sending service:

    docker exec ulaknode ulaknode-spf generate yourdomain.com --mx --include sendgrid.net --all softfail

    Available --all policies:

    • softfail (~all) — unauthorized senders are flagged but not rejected; recommended when starting out
    • fail (-all) — unauthorized senders are rejected outright
    • neutral (?all) — no assertion about unauthorized senders

    Look up the currently published SPF record:

    docker exec ulaknode ulaknode-spf show yourdomain.com

    Copy the output into a DNS TXT record for yourdomain.com.

  • 🔗 How do I set up a DMARC policy? â–¼

    The ulaknode-dmarc tool generates a ready-to-publish DMARC TXT record.

    Start in monitoring mode (no action on failures, collect aggregate reports):

    docker exec ulaknode ulaknode-dmarc generate yourdomain.com \
      --policy none \
      --rua mailto:dmarc@yourdomain.com

    Move to quarantine once you are confident in DKIM and SPF:

    docker exec ulaknode ulaknode-dmarc generate yourdomain.com \
      --policy quarantine \
      --rua mailto:dmarc@yourdomain.com

    Strict reject mode:

    docker exec ulaknode ulaknode-dmarc generate yourdomain.com \
      --policy reject \
      --rua mailto:dmarc@yourdomain.com \
      --pct 100

    The output is the exact TXT record value to publish under _dmarc.yourdomain.com.

    Look up the currently published DMARC record:

    docker exec ulaknode ulaknode-dmarc show yourdomain.com

    The recommended rollout sequence is: none → quarantine → reject, advancing only after reviewing aggregate reports to ensure no legitimate mail is failing.

  • 🔗 How do I add or remove email domains? â–¼

    Use the ulaknode-domain tool to manage virtual domains hosted on your server.

    # Add a domain
    docker exec ulaknode ulaknode-domain add yourdomain.com
    
    # List all hosted domains
    docker exec ulaknode ulaknode-domain list
    
    # Show all mailboxes and aliases for a domain
    docker exec ulaknode ulaknode-domain show yourdomain.com
    
    # Remove a domain and all its associated mailboxes and aliases
    docker exec ulaknode ulaknode-domain remove yourdomain.com

    After adding a domain, set up the DNS records described in the DNS FAQ above, then create mailboxes and DKIM keys for the domain.

  • 🔗 How do I add, remove, or manage email accounts? â–¼

    Use the ulaknode-mailbox tool for all mailbox operations.

    Create a new mailbox:

    docker exec ulaknode ulaknode-mailbox add alice@yourdomain.com secretpassword

    List all mailboxes for a domain:

    docker exec ulaknode ulaknode-mailbox list yourdomain.com

    Change a mailbox password:

    docker exec ulaknode ulaknode-mailbox passwd alice@yourdomain.com newpassword

    Set a storage quota:

    docker exec ulaknode ulaknode-mailbox quota-set alice@yourdomain.com 5G

    Accepted suffixes: K, M, G. Use 0 for unlimited (the default).

    Check current quota usage:

    docker exec ulaknode ulaknode-mailbox quota alice@yourdomain.com

    Show mailbox details:

    docker exec ulaknode ulaknode-mailbox show alice@yourdomain.com

    Remove a mailbox:

    docker exec ulaknode ulaknode-mailbox remove alice@yourdomain.com
  • 🔗 How do I manage email aliases? â–¼

    Use the ulaknode-alias tool to create and manage address aliases. An alias forwards mail from a source address to one or more destination addresses.

    # Add an alias
    docker exec ulaknode ulaknode-alias add info@yourdomain.com alice@yourdomain.com
    
    # List all aliases for a domain
    docker exec ulaknode ulaknode-alias list yourdomain.com
    
    # Show the destination(s) for a specific alias
    docker exec ulaknode ulaknode-alias show info@yourdomain.com
    
    # Remove an alias
    docker exec ulaknode ulaknode-alias remove info@yourdomain.com

    Both the source and destination must be full email addresses. You can point the same source alias at multiple destinations by running ulaknode-alias add multiple times with different destinations.

  • 🔗 How do I install or renew a TLS certificate? â–¼

    Use the ulaknode-cert tool to install a certificate (e.g. from Let's Encrypt) and verify it is correctly configured.

    Install a certificate:

    docker exec ulaknode ulaknode-cert install /tmp/fullchain.pem /tmp/privkey.pem

    Show the currently installed certificate:

    docker exec ulaknode ulaknode-cert show

    Verify the certificate and key match and check expiry:

    docker exec ulaknode ulaknode-cert check

    This command warns if the certificate expires within 14 days.

    Restart services after installing a new certificate:

    docker exec ulaknode ulaknode-service restart postfix
    docker exec ulaknode ulaknode-service restart dovecot
  • 🔗 How does spam filtering work, and how can I tune it? â–¼

    ulaknode uses Rspamd for spam filtering. Rspamd scores each incoming message across hundreds of rules — DNS blocklists, content analysis, header checks, Bayes statistics, and more. Messages above the configured threshold are rejected or tagged.

    Train the Bayes classifier with known spam and ham:

    docker exec ulaknode rspamc learn_spam /path/to/spam.eml
    docker exec ulaknode rspamc learn_ham /path/to/ham.eml

    Common tuning via Rspamd configuration (edit files in /etc/rspamd/local.d/):

    • Whitelist a sender: add the address or domain to the whitelist_from map
    • Blacklist a sender: add to the blacklist_from map
    • Adjust score thresholds: edit actions in rspamd.conf to raise or lower the reject/greylist/add-header thresholds

    After editing configuration files, restart Rspamd:

    docker exec ulaknode ulaknode-service restart rspamd

    The Rspamd web UI (port 11334) provides live statistics and per-message score breakdowns useful for diagnosing false positives or negatives.

  • 🔗 How do I troubleshoot a message that was not delivered? â–¼

    Start with the error log tool, then inspect the mail queue.

    View recent Postfix errors:

    docker exec ulaknode ulaknode-errlog postfix
    docker exec ulaknode ulaknode-errlog postfix 100

    The optional second argument sets how many lines to show (default: 50). The same command works for dovecot, rspamd, clamav, and fail2ban.

    View the mail queue:

    docker exec ulaknode mailq

    Inspect a specific queued message by its queue ID:

    docker exec ulaknode postcat -q QUEUEID

    Common causes of non-delivery:

    • Deferred (4xx): temporary issue on the remote side — Postfix will retry automatically
    • Bounced (5xx): permanent rejection — read the DSN for the reason (often a missing PTR record, SPF failure, or blocklist listing)
    • Spam-filtered locally: check the Rspamd log to see if the message was rejected before reaching the queue

    If you need further assistance, open a ticket at the support portal with the relevant log excerpts.

  • 🔗 How do I back up and restore ulaknode data? â–¼

    ulaknode stores all persistent data in named Docker volumes: mailboxes, logs, TLS certificates, and configuration for Postfix, Dovecot, Rspamd, and ClamAV. A reliable backup strategy must cover all of these volumes.

    We recommend docker-volume-backup-borg, a purpose-built tool that automates encrypted, compressed backups of Docker volumes using BorgBackup. It discovers volumes automatically from running containers and supports both local and remote (SSH) repositories.

    Basic backup run targeting the ulaknode container:

    docker run --rm \
      --env-file .env \
      -e BACKUP_CONTAINERS=ulaknode \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v /var/lib/docker/volumes:/var/lib/docker/volumes:ro \
      -v ~/.ssh:/root/.ssh:ro \
      itefixnet/docker-volume-backup-borg

    Configure at minimum these variables in your .env file:

    • BORG_REPO — destination repository (local path or user@host:path for remote)
    • BORG_PASSPHRASE — encryption passphrase; store this securely, without it restores are impossible
    • KEEP_DAILY / KEEP_WEEKLY / KEEP_MONTHLY — retention policy (defaults: 7 / 4 / 6)

    Stop the container during backup for a fully consistent snapshot:

    docker run --rm \
      --env-file .env \
      -e BACKUP_CONTAINERS=ulaknode \
      -e STOP_CONTAINERS=ulaknode \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v /var/lib/docker/volumes:/var/lib/docker/volumes:ro \
      itefixnet/docker-volume-backup-borg

    List available backups:

    docker run --rm --env-file .env \
      itefixnet/docker-volume-backup-borg list

    Restore a specific archive:

    docker run --rm --env-file .env \
      -v $(pwd):/restore \
      itefixnet/docker-volume-backup-borg extract ARCHIVE_NAME

    Keep the .env file and your passphrase in a safe, separate location from the backup repository itself.

  • 🔗 Is ulaknode really free? Are there hidden per-user fees? â–¼

    Yes, ulaknode is genuinely free. It is released under a permissive BSD-style license with no per-user, per-mailbox, or per-domain charges. You can run it for any number of users on your own hardware at no cost.

    Optional commercial support plans are available starting at $549/year for organisations that want professional assistance with deployment, DNS configuration, migration, maintenance, and spam-filtering optimisation. Multi-year and volume discounts are available.

    To learn more about support options or to request a quote, reach us via our contact form.