§2024-09-26

Here you can find an example install script to install WildDuck with Haraka and ZoneMTA. The install script is self contained, you can upload to your server and start it as root. It fetches all required files from Github. After installation you should see exactly the same web interface as in https://webmail.wildduck.email/

The install script should work with Ubuntu version from 22.04 (probably also with 20.04) and the server must be blank. Blank meaning that there should be no existing software installed (eg. Apache, MySQL or Postfix). If the server already has something installed, then remove the extra applications before running this script. This also means that you should not run the install script in a VPS that you already use for other stuff.

¶What does it do?

This install script installs and configures the following components:

¶What it does not configure:

¶Security

All components use TLS/HTTPS with Let's Encrypt certificates by default. Webmail component allows to set up two factor authentication (both TOTP and U2F). If 2FA is enabled then you can also generate application specific passwords for external applications (eg. for the IMAP client) from the Webmail interface as master password can not be used in that case.

¶TOTP (Time-based One-Time Password) and U2F (Universal 2nd Factor) are both authentication methods used to enhance security.

Both TOTP and U2F help protect against unauthorized access by requiring something you know (your password) and something you have (a code or a physical key).

alexlai@hc4Noble:~/build/WildDuck$ pwd
/home/alexlai/build/WildDuck
$ wget -O - https://raw.githubusercontent.com/nodemailer/wildduck/master/setup/get_install.sh | bash

$ ls 
00_install_global_functions_variables.sh  05_install_packages.sh         10_install_wildduck_webmail.sh  15_install_deploy.sh
01_install_commits.sh                     06_install_enable_services.sh  11_install_nginx.sh             install.sh
02_install_prerequisites.sh               07_install_wildduck.sh         12_install_ufw_rules.sh
03_install_check_running_services.sh      08_install_haraka.sh           13_install_ssl_certs.sh
04_install_import_keys.sh                 09_install_zone_mta.sh         14_install_start_services.sh

$ sudo ./install.sh hc4Noble.yushei.net mail.hc4Noble.yushei.net >log 2>&1 

# from other terminal
$ tail -f log
DOMAINNAME: hc4Noble.yushei.net, HOSTNAME: mail.hc4Noble.yushei.net

lsof stands for "list open files" and is a powerful tool that allows you to gather information about files and processes that are currently open on your system.

Where mydomain.com is the email address domain and mail.mydomain.com is the hostname of current server.

Make sure that used hostname points to current server as the install script tries to fetch an SSL certificate from Let's Encrypt. The MX for email address domain should point to server hostname.

If the installation succeeds then the installer writes DNS configuration to domainname-nameserver.txt file. Set up the provided DNS entries from this file before sending and receiving email.

Next point your browser to https://mydomain.com/ and you should see the WildDuck example webmail app where you can create an email account.

$ git clone deploy@hostname:/var/opt/wildduck.git
$ cd wildduck
$ git checkout master
$ .... make some changes
$ git add .
$ git commit -m "made some changes"
$ git push origin master -f

2024-09-26 hc4Noble.yushei.net

$ cat log
DOMAINNAME: hc4Noble.yushei.net, HOSTNAME: mail.hc4Noble.yushei.net
Hit:1 http://ppa.linuxfactory.or.kr noble InRelease
Get:2 http://ports.ubuntu.com/ubuntu-ports noble-security InRelease [126 kB]
Hit:3 http://tw.ports.ubuntu.com/ubuntu-ports noble InRelease
Hit:4 http://tw.ports.ubuntu.com/ubuntu-ports noble-updates InRelease
Hit:5 http://tw.ports.ubuntu.com/ubuntu-ports noble-backports InRelease
Get:6 http://ports.ubuntu.com/ubuntu-ports noble-security/main arm64 Packages [376 kB]
Get:7 http://ports.ubuntu.com/ubuntu-ports noble-security/main Translation-en [81.7 kB]
Fetched 584 kB in 4s (164 kB/s)
Reading package lists...
Reading package lists...
Building dependency tree...
Reading state information...
lsb-release is already the newest version (12.0-2).
ca-certificates is already the newest version (20240203).
curl is already the newest version (8.5.0-2ubuntu10.4).
curl set to manually installed.
gnupg is already the newest version (2.4.4-2ubuntu17).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

-- Executing 01_install_commits.sh subscript --

-- Executing 02_install_prerequisites.sh subscript --
Checking lsof
Checking ps


-- Executing 03_install_check_running_services.sh subscript --
Checking programs listening on port 25,587,993,995,80,443
OK: port 25 (SMTP) is free
OK: port 587 (SMTP TLS) is free
OK: port 993 (IMAP SSL/TLS) is free
OK: port 995 (POP3 SSL/TLS) is free
OK: port 80 (HTTP) is free
OK: port 443 (HTTPS) is free

-- Executing 04_install_import_keys.sh subscript --
Get:1 https://deb.nodesource.com/node_20.x nodistro InRelease [12.1 kB]
Get:2 http://ppa.linuxfactory.or.kr noble InRelease [44.2 kB]
Get:3 https://deb.nodesource.com/node_20.x nodistro/main arm64 Packages [9,124 B]
Hit:5 http://tw.ports.ubuntu.com/ubuntu-ports noble InRelease
Hit:6 http://ports.ubuntu.com/ubuntu-ports noble-security InRelease
Hit:7 http://tw.ports.ubuntu.com/ubuntu-ports noble-updates InRelease
Ign:8 https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/7.0 InRelease
Hit:9 http://tw.ports.ubuntu.com/ubuntu-ports noble-backports InRelease
Err:10 https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/7.0 Release
  404  Not Found [IP: 13.35.7.108 443]
Get:4 https://rspamd.com/apt-stable noble InRelease [3,158 B]
Get:11 https://rspamd.com/apt-stable noble/main arm64 Packages [1,577 B]
Reading package lists...
W: Skipping acquire of configured file 'main/source/Sources' as repository 'https://deb.nodesource.com/node_20.x nodistro InRelease' does not seem to provide it (sources.list entry misspelt?)
E: The repository 'https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/7.0 Release' does not have a Release file.

-- Executing 05_install_packages.sh subscript --
Hit:1 https://deb.nodesource.com/node_20.x nodistro InRelease
Ign:2 https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/7.0 InRelease
Err:3 https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/7.0 Release
  404  Not Found [IP: 13.35.7.109 443]
Hit:4 http://ppa.linuxfactory.or.kr noble InRelease
Hit:6 http://ports.ubuntu.com/ubuntu-ports noble-security InRelease
Hit:7 http://tw.ports.ubuntu.com/ubuntu-ports noble InRelease
Hit:8 http://tw.ports.ubuntu.com/ubuntu-ports noble-updates InRelease
Hit:9 http://tw.ports.ubuntu.com/ubuntu-ports noble-backports InRelease
Hit:5 https://rspamd.com/apt-stable noble InRelease
Reading package lists...
E: The repository 'https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/7.0 Release' does not have a Release file.
W: Skipping acquire of configured file 'main/source/Sources' as repository 'https://deb.nodesource.com/node_20.x nodistro InRelease' does not seem to provide it (sources.list entry misspelt?)
Reading package lists...
Building dependency tree...
Reading state information...
E: Unable to locate package mongodb-org
Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed:
  binutils-common libarchive13t64 libbinutils libsframe1 libsodium23
Suggested packages:
  lrzip
The following NEW packages will be installed:
  binutils-common libarchive13t64 libbinutils libsframe1 libsodium23 rspamd
0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
Need to get 7,325 kB of archives.
After this operation, 23.3 MB of additional disk space will be used.
Get:2 http://tw.ports.ubuntu.com/ubuntu-ports noble/main arm64 binutils-common arm64 2.42-4ubuntu2 [239 kB]
Get:1 https://rspamd.com/apt-stable noble/main arm64 rspamd arm64 3.9.1-1~82f43560f~noble [5,809 kB]
Get:3 http://tw.ports.ubuntu.com/ubuntu-ports noble-updates/main arm64 libarchive13t64 arm64 3.7.2-2ubuntu0.1 [377 kB]
Get:4 http://tw.ports.ubuntu.com/ubuntu-ports noble/main arm64 libsframe1 arm64 2.42-4ubuntu2 [14.4 kB]
Get:5 http://tw.ports.ubuntu.com/ubuntu-ports noble/main arm64 libbinutils arm64 2.42-4ubuntu2 [767 kB]
Get:6 http://tw.ports.ubuntu.com/ubuntu-ports noble/main arm64 libsodium23 arm64 1.0.18-1build3 [119 kB]
Fetched 7,325 kB in 6s (1,170 kB/s)
Selecting previously unselected package binutils-common:arm64.
(Reading database ... 28964 files and directories currently installed.)
Preparing to unpack .../0-binutils-common_2.42-4ubuntu2_arm64.deb ...
Unpacking binutils-common:arm64 (2.42-4ubuntu2) ...
Selecting previously unselected package libarchive13t64:arm64.
Preparing to unpack .../1-libarchive13t64_3.7.2-2ubuntu0.1_arm64.deb ...
Unpacking libarchive13t64:arm64 (3.7.2-2ubuntu0.1) ...
Selecting previously unselected package libsframe1:arm64.
Preparing to unpack .../2-libsframe1_2.42-4ubuntu2_arm64.deb ...
Unpacking libsframe1:arm64 (2.42-4ubuntu2) ...
Selecting previously unselected package libbinutils:arm64.
Preparing to unpack .../3-libbinutils_2.42-4ubuntu2_arm64.deb ...
Unpacking libbinutils:arm64 (2.42-4ubuntu2) ...
Selecting previously unselected package libsodium23:arm64.
Preparing to unpack .../4-libsodium23_1.0.18-1build3_arm64.deb ...
Unpacking libsodium23:arm64 (1.0.18-1build3) ...
Selecting previously unselected package rspamd.
Preparing to unpack .../5-rspamd_3.9.1-1~82f43560f~noble_arm64.deb ...
Unpacking rspamd (3.9.1-1~82f43560f~noble) ...
Setting up libsodium23:arm64 (1.0.18-1build3) ...
Setting up binutils-common:arm64 (2.42-4ubuntu2) ...
Setting up libsframe1:arm64 (2.42-4ubuntu2) ...
Setting up libbinutils:arm64 (2.42-4ubuntu2) ...
Setting up libarchive13t64:arm64 (3.7.2-2ubuntu0.1) ...
Setting up rspamd (3.9.1-1~82f43560f~noble) ...
Created symlink /etc/systemd/system/multi-user.target.wants/rspamd.service → /usr/lib/systemd/system/rspamd.service.
Processing triggers for man-db (2.12.0-4build2) ...
Processing triggers for libc-bin (2.39-0ubuntu8.3) ... <--- stuck here

$ cat log

DOMAINNAME: hc4Noble.yushei.net, HOSTNAME: mail.hc4Noble.yushei.net
Hit:1 https://deb.nodesource.com/node_20.x nodistro InRelease
Ign:2 https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 InRelease
Hit:3 http://ppa.linuxfactory.or.kr jammy InRelease
Hit:5 https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 Release
Hit:6 http://tw.ports.ubuntu.com/ubuntu-ports jammy InRelease
Hit:7 http://ports.ubuntu.com/ubuntu-ports jammy-security InRelease
Hit:9 http://tw.ports.ubuntu.com/ubuntu-ports jammy-updates InRelease
Hit:10 http://tw.ports.ubuntu.com/ubuntu-ports jammy-backports InRelease
Hit:4 https://rspamd.com/apt-stable jammy InRelease
Reading package lists...
W: Skipping acquire of configured file 'main/source/Sources' as repository 'https://deb.nodesource.com/node_20.x nodistro InRelease' does not seem to provide it (sources.list entry misspelt?)
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 2873 (apt-get)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?

-- Executing 01_install_commits.sh subscript --

-- Executing 02_install_prerequisites.sh subscript --
Checking lsof
Checking ps


-- Executing 03_install_check_running_services.sh subscript --
Checking programs listening on port 25,587,993,995,80,443
OK: port 25 (SMTP) is free
OK: port 587 (SMTP TLS) is free
OK: port 993 (IMAP SSL/TLS) is free
OK: port 995 (POP3 SSL/TLS) is free
OK: port 80 (HTTP) is free
OK: port 443 (HTTPS) is free

-- Executing 04_install_import_keys.sh subscript --
useradd: user 'wildduck' already exists
User wildduck already exists
useradd: user 'deploy' already exists
User deploy already exists
Hit:1 https://deb.nodesource.com/node_20.x nodistro InRelease
Hit:2 http://ppa.linuxfactory.or.kr jammy InRelease
Ign:3 https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 InRelease
Hit:4 http://ports.ubuntu.com/ubuntu-ports jammy-security InRelease
Hit:6 https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 Release
Hit:7 http://tw.ports.ubuntu.com/ubuntu-ports jammy InRelease
Hit:8 http://tw.ports.ubuntu.com/ubuntu-ports jammy-updates InRelease
Hit:10 http://tw.ports.ubuntu.com/ubuntu-ports jammy-backports InRelease
Hit:5 https://rspamd.com/apt-stable jammy InRelease
Reading package lists...
W: Skipping acquire of configured file 'main/source/Sources' as repository 'https://deb.nodesource.com/node_20.x nodistro InRelease' does not seem to provide it (sources.list entry misspelt?)

-- Executing 05_install_packages.sh subscript --
Hit:1 https://deb.nodesource.com/node_20.x nodistro InRelease
Ign:2 https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 InRelease
Hit:3 http://ppa.linuxfactory.or.kr jammy InRelease
Hit:4 http://tw.ports.ubuntu.com/ubuntu-ports jammy InRelease
Hit:5 http://ports.ubuntu.com/ubuntu-ports jammy-security InRelease
Hit:6 https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 Release
Hit:8 http://tw.ports.ubuntu.com/ubuntu-ports jammy-updates InRelease
Hit:9 http://tw.ports.ubuntu.com/ubuntu-ports jammy-backports InRelease
Hit:7 https://rspamd.com/apt-stable jammy InRelease
Reading package lists...
W: Skipping acquire of configured file 'main/source/Sources' as repository 'https://deb.nodesource.com/node_20.x nodistro InRelease' does not seem to provide it (sources.list entry misspelt?)
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 2873 (apt-get)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 2873 (apt-get)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
E: Could not get lock /var/cache/apt/archives/lock. It is held by process 2873 (apt-get)
E: Unable to lock directory /var/cache/apt/archives/
/home/alexlai/build/WildDuck/05_install_packages.sh: line 19: /etc/rspamd/override.d/dmarc.conf: No such file or directory

-- Executing 06_install_enable_services.sh subscript --
Created symlink /etc/systemd/system/multi-user.target.wants/mongod.service → /lib/systemd/system/mongod.service.
Synchronizing state of redis-server.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable redis-server

-- These are the installed and required programs:
v20.17.0
Redis server v=6.0.16 sha=00000000:0 malloc=jemalloc-5.2.1 bits=64 build=a3fdef44459b3ad6
db version v7.0.14
Build Info: {
    "version": "7.0.14",
    "gitVersion": "ce59cfc6a3c5e5c067dca0d30697edd68d4f5188",
    "openSSLVersion": "OpenSSL 3.0.2 15 Mar 2022",
    "modules": [],
    "allocator": "tcmalloc",
    "environment": {
        "distmod": "ubuntu2204",
        "distarch": "aarch64",
        "target_arch": "aarch64"
    }
}
HOSTNAME: mail.hc4Noble.yushei.net
-- Installing npm globally (workaround)

removed 1 package, and changed 21 packages in 11s

22 packages are looking for funding
  run `npm fund` for details

-- Executing 07_install_wildduck.sh subscript --
Cloning into bare repository 'wildduck.git'...
Note: switching to '9a61cff18689f773b01a77d00d6e309507fb5dd8'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 9a61cff chore(master): release 1.45.0 [skip-ci] (#717)
npm warn config production Use `--omit=dev` instead.
npm warn config optional Use `--omit=optional` to exclude optional dependencies, or
npm warn config `--include=optional` to include them.
npm warn config
npm warn config       Default value does install optional deps unless otherwise omitted.
npm warn config shrinkwrap Use the --package-lock setting instead.
npm warn deprecated har-validator@5.1.5: this library is no longer supported
npm warn deprecated are-we-there-yet@4.0.2: This package is no longer supported.
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated formidable@1.2.6: Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau
npm warn deprecated gauge@5.0.2: This package is no longer supported.
npm warn deprecated npmlog@7.0.1: This package is no longer supported.
npm warn deprecated mongodb-extended-json@1.11.1: Use EJSON from the `bson` package instead
npm warn deprecated glob@8.0.3: Glob versions prior to v9 are no longer supported
npm warn deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm warn deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142

added 420 packages in 2m

45 packages are looking for funding
  run `npm fund` for details
Created symlink /etc/systemd/system/multi-user.target.wants/wildduck.service → /etc/systemd/system/wildduck.service.

-- Executing 08_install_haraka.sh subscript --
Cloning into bare repository 'haraka-plugin-wildduck.git'...
npm warn config production Use `--omit=dev` instead.
npm warn config optional Use `--omit=optional` to exclude optional dependencies, or
npm warn config `--include=optional` to include them.
npm warn config
npm warn config       Default value does install optional deps unless otherwise omitted.
npm warn config shrinkwrap Use the --package-lock setting instead.
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm warn deprecated npmlog@6.0.2: This package is no longer supported.
npm warn deprecated @npmcli/move-file@1.1.2: This functionality has been moved to @npmcli/fs
npm warn deprecated are-we-there-yet@3.0.1: This package is no longer supported.
npm warn deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm warn deprecated gauge@4.0.4: This package is no longer supported.
npm warn deprecated ldapjs@2.3.3: This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md

added 317 packages in 1m

26 packages are looking for funding
  run `npm fund` for details
create: /opt/haraka
create: /opt/haraka/plugins
create: /opt/haraka/docs
create: /opt/haraka/config
create: /opt/haraka/config/smtp.ini
create: /opt/haraka/config/log.ini
create: /opt/haraka/config/plugins
create: /opt/haraka/config/dkim
create: /opt/haraka/config/dkim/dkim_key_gen.sh
npm warn config production Use `--omit=dev` instead.
npm warn config optional Use `--omit=optional` to exclude optional dependencies, or
npm warn config `--include=optional` to include them.
npm warn config
npm warn config       Default value does install optional deps unless otherwise omitted.
npm warn config shrinkwrap Use the --package-lock setting instead.

added 150 packages in 40s

15 packages are looking for funding
  run `npm fund` for details
Note: switching to 'a209775ceac579b8ac1a4c04c052674eba763691'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at a209775 chore(master): release 5.8.13 [skip-ci] (#41)
npm warn config production Use `--omit=dev` instead.
npm warn config optional Use `--omit=optional` to exclude optional dependencies, or
npm warn config `--include=optional` to include them.
npm warn config
npm warn config       Default value does install optional deps unless otherwise omitted.
npm warn config shrinkwrap Use the --package-lock setting instead.
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated npmlog@7.0.1: This package is no longer supported.
npm warn deprecated har-validator@5.1.5: this library is no longer supported
npm warn deprecated are-we-there-yet@4.0.2: This package is no longer supported.
npm warn deprecated glob@8.0.3: Glob versions prior to v9 are no longer supported
npm warn deprecated formidable@1.2.6: Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau
npm warn deprecated mongodb-extended-json@1.11.1: Use EJSON from the `bson` package instead
npm warn deprecated gauge@5.0.2: This package is no longer supported.
npm warn deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm warn deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142

added 429 packages in 41s

46 packages are looking for funding
  run `npm fund` for details
Created symlink /etc/systemd/system/multi-user.target.wants/haraka.service → /etc/systemd/system/haraka.service.

-- Executing 09_install_zone_mta.sh subscript --
Cloning into bare repository 'zone-mta.git'...
Cloning into bare repository 'zonemta-wildduck.git'...
Note: switching to '2ec1ba85a44c4665a6326271c8162ee76c4d6d02'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 2ec1ba8 Bumped zone-mta
Note: switching to 'f029b8d69aaa255b1c4f426848f994be21be8cd0'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at f029b8d chore(master): release 1.32.16 [skip-ci] (#29)
writing RSA key
npm warn config production Use `--omit=dev` instead.
npm warn config optional Use `--omit=optional` to exclude optional dependencies, or
npm warn config `--include=optional` to include them.
npm warn config
npm warn config       Default value does install optional deps unless otherwise omitted.
npm warn config shrinkwrap Use the --package-lock setting instead.
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated npmlog@7.0.1: This package is no longer supported.
npm warn deprecated har-validator@5.1.5: this library is no longer supported
npm warn deprecated are-we-there-yet@4.0.2: This package is no longer supported.
npm warn deprecated glob@8.0.3: Glob versions prior to v9 are no longer supported
npm warn deprecated formidable@1.2.6: Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau
npm warn deprecated are-we-there-yet@1.1.7: This package is no longer supported.
npm warn deprecated npmlog@4.1.2: This package is no longer supported.
npm warn deprecated gauge@5.0.2: This package is no longer supported.
npm warn deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm warn deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm warn deprecated gauge@2.7.4: This package is no longer supported.

added 293 packages in 31s

26 packages are looking for funding
  run `npm fund` for details
npm warn config production Use `--omit=dev` instead.
npm warn config optional Use `--omit=optional` to exclude optional dependencies, or
npm warn config `--include=optional` to include them.
npm warn config
npm warn config       Default value does install optional deps unless otherwise omitted.
npm warn config shrinkwrap Use the --package-lock setting instead.
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated npmlog@7.0.1: This package is no longer supported.
npm warn deprecated har-validator@5.1.5: this library is no longer supported
npm warn deprecated are-we-there-yet@4.0.2: This package is no longer supported.
npm warn deprecated glob@8.0.3: Glob versions prior to v9 are no longer supported
npm warn deprecated formidable@1.2.6: Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau
npm warn deprecated mongodb-extended-json@1.11.1: Use EJSON from the `bson` package instead
npm warn deprecated gauge@5.0.2: This package is no longer supported.
npm warn deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm warn deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142

added 421 packages in 1m

45 packages are looking for funding
  run `npm fund` for details
Created symlink /etc/systemd/system/multi-user.target.wants/zone-mta.service → /etc/systemd/system/zone-mta.service.

-- Executing 10_install_wildduck_webmail.sh subscript --
Cloning into bare repository 'wildduck-webmail.git'...
Note: switching to '40ee1ef973de33de5bdf3e6b7e877d156d87436a'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 40ee1ef Set the same max password length for every field
npm warn deprecated osenv@0.1.5: This package is no longer supported.
npm warn deprecated @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
npm warn deprecated har-validator@5.1.5: this library is no longer supported
npm warn deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
npm warn deprecated are-we-there-yet@3.0.1: This package is no longer supported.
npm warn deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm warn deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
npm warn deprecated glob@7.1.7: Glob versions prior to v9 are no longer supported
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated gauge@4.0.4: This package is no longer supported.
npm warn deprecated csurf@1.11.0: Please use another csrf package
npm warn deprecated npmlog@6.0.2: This package is no longer supported.
npm warn deprecated glob@6.0.4: Glob versions prior to v9 are no longer supported
npm warn deprecated rimraf@2.4.5: Rimraf versions prior to v4 are no longer supported
npm warn deprecated glob@5.0.15: Glob versions prior to v9 are no longer supported
npm warn deprecated glob@8.0.3: Glob versions prior to v9 are no longer supported
npm warn deprecated multer@1.4.4: Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.
npm warn deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142

added 442 packages, and audited 443 packages in 1m

51 packages are looking for funding
  run `npm fund` for details

11 vulnerabilities (5 moderate, 6 high)

To address issues that do not require attention, run:
  npm audit fix

To address all issues possible, run:
  npm audit fix --force

Some issues need review, and may require choosing
a different dependency.

Run `npm audit` for details.

> wildduck-webmail@1.0.1 bowerdeps
> mkdir -p public/components && bower install

bower fetch#2.0.4           not-cached https://github.com/github/fetch.git#2.0.4
bower fetch#2.0.4              resolve https://github.com/github/fetch.git#2.0.4
bower jquery#*              not-cached https://github.com/jquery/jquery-dist.git#*
bower jquery#*                 resolve https://github.com/jquery/jquery-dist.git#*
bower moment#*              not-cached https://github.com/moment/moment.git#*
bower moment#*                 resolve https://github.com/moment/moment.git#*
bower DOMPurify#^1.0.2      not-cached https://github.com/cure53/DOMPurify.git#^1.0.2
bower DOMPurify#^1.0.2         resolve https://github.com/cure53/DOMPurify.git#^1.0.2
bower handlebars#*          not-cached https://github.com/components/handlebars.js.git#*
bower handlebars#*             resolve https://github.com/components/handlebars.js.git#*
bower underscore#*          not-cached https://github.com/jashkenas/underscore.git#*
bower underscore#*             resolve https://github.com/jashkenas/underscore.git#*
bower bootstrap-daterangepicker#*       not-cached https://github.com/dangrossman/bootstrap-daterangepicker.git#*
bower bootstrap-daterangepicker#*          resolve https://github.com/dangrossman/bootstrap-daterangepicker.git#*
bower promise-polyfill#^7.0.0           not-cached https://github.com/taylorhakes/promise-polyfill.git#^7.0.0
bower promise-polyfill#^7.0.0              resolve https://github.com/taylorhakes/promise-polyfill.git#^7.0.0
bower favico.js#^0.3.10                 not-cached https://github.com/ejci/favico.js.git#^0.3.10
bower favico.js#^0.3.10                    resolve https://github.com/ejci/favico.js.git#^0.3.10
bower summernote#*                      not-cached https://github.com/summernote/summernote.git#*
bower summernote#*                         resolve https://github.com/summernote/summernote.git#*
bower event-source-polyfill#*           not-cached https://github.com/Yaffle/EventSource.git#*
bower event-source-polyfill#*              resolve https://github.com/Yaffle/EventSource.git#*
bower fetch#2.0.4                         download https://github.com/github/fetch/archive/v2.0.4.tar.gz
bower moment#*                            download https://github.com/moment/moment/archive/2.30.1.tar.gz
bower DOMPurify#^1.0.2                    download https://github.com/cure53/DOMPurify/archive/1.0.11.tar.gz
bower jquery#*                            download https://github.com/jquery/jquery-dist/archive/3.7.1.tar.gz
bower handlebars#*                        download https://github.com/components/handlebars.js/archive/v4.7.8.tar.gz
bower underscore#*                        download https://github.com/jashkenas/underscore/archive/1.13.7.tar.gz
bower bootstrap-daterangepicker#*         download https://github.com/dangrossman/bootstrap-daterangepicker/archive/v3.0.5.tar.gz
bower summernote#*                        download https://github.com/summernote/summernote/archive/v0.8.20.tar.gz
bower promise-polyfill#^7.0.0             download https://github.com/taylorhakes/promise-polyfill/archive/7.1.2.tar.gz
bower favico.js#^0.3.10                   download https://github.com/ejci/favico.js/archive/0.3.10.tar.gz
bower fetch#2.0.4                          extract archive.tar.gz
bower jquery#*                             extract archive.tar.gz
bower event-source-polyfill#*             download https://github.com/Yaffle/EventSource/archive/1.0.31.tar.gz
bower handlebars#*                         extract archive.tar.gz
bower DOMPurify#^1.0.2                     extract archive.tar.gz
bower favico.js#^0.3.10                    extract archive.tar.gz
bower promise-polyfill#^7.0.0              extract archive.tar.gz
bower underscore#*                         extract archive.tar.gz
bower event-source-polyfill#*              extract archive.tar.gz
bower bootstrap-daterangepicker#*          extract archive.tar.gz
bower moment#*                             extract archive.tar.gz
bower summernote#*                         extract archive.tar.gz
bower favico.js#^0.3.10                   resolved https://github.com/ejci/favico.js.git#0.3.10
bower fetch#2.0.4                         resolved https://github.com/github/fetch.git#2.0.4
bower handlebars#*                        resolved https://github.com/components/handlebars.js.git#4.7.8
bower event-source-polyfill#*             resolved https://github.com/Yaffle/EventSource.git#1.0.31
bower promise-polyfill#^7.0.0             mismatch Version declared in the json (7.1.0) is different than the resolved one (7.1.2)
bower promise-polyfill#^7.0.0             resolved https://github.com/taylorhakes/promise-polyfill.git#7.1.2
bower bootstrap-daterangepicker#*         resolved https://github.com/dangrossman/bootstrap-daterangepicker.git#3.0.5
bower jquery#1.9.1 - 3                  not-cached https://github.com/jquery/jquery-dist.git#1.9.1 - 3
bower jquery#1.9.1 - 3                     resolve https://github.com/jquery/jquery-dist.git#1.9.1 - 3
bower moment#>=2.9.0                    not-cached https://github.com/moment/moment.git#>=2.9.0
bower moment#>=2.9.0                       resolve https://github.com/moment/moment.git#>=2.9.0
bower jquery#1.9.1 - 3                    download https://github.com/jquery/jquery-dist/archive/3.7.1.tar.gz
bower moment#>=2.9.0                      download https://github.com/moment/moment/archive/2.30.1.tar.gz
bower DOMPurify#^1.0.2                invalid-meta for:/tmp/deploy/bower/7466080023e35ac1d0e405573139662b-7920-OQpvOM/bower.json
bower DOMPurify#^1.0.2                invalid-meta The "name" is recommended to be lowercase, can contain digits, dots, dashes
bower jquery#1.9.1 - 3                     extract archive.tar.gz
bower DOMPurify#^1.0.2                    resolved https://github.com/cure53/DOMPurify.git#1.0.11
bower moment#>=2.9.0                       extract archive.tar.gz
bower jquery#*                            resolved https://github.com/jquery/jquery-dist.git#3.7.1
bower jquery#1.9.1 - 3                    resolved https://github.com/jquery/jquery-dist.git#3.7.1
bower summernote#*                        resolved https://github.com/summernote/summernote.git#0.8.20
bower underscore#*                        resolved https://github.com/jashkenas/underscore.git#1.13.7
bower moment#*                            resolved https://github.com/moment/moment.git#2.30.1
bower moment#>=2.9.0                      resolved https://github.com/moment/moment.git#2.30.1
bower favico.js#^0.3.10                    install favico.js#0.3.10
bower fetch#2.0.4                          install fetch#2.0.4
bower handlebars#*                         install handlebars#4.7.8
bower event-source-polyfill#*              install event-source-polyfill#1.0.31
bower promise-polyfill#^7.0.0              install promise-polyfill#7.1.2
bower bootstrap-daterangepicker#*          install bootstrap-daterangepicker#3.0.5
bower DOMPurify#^1.0.2                     install DOMPurify#1.0.11
bower jquery#1.9.1 - 3                     install jquery#3.7.1
bower summernote#*                         install summernote#0.8.20
bower underscore#*                         install underscore#1.13.7
bower moment#>=2.9.0                       install moment#2.30.1

favico.js#0.3.10 public/components/favico.js

fetch#2.0.4 public/components/fetch

handlebars#4.7.8 public/components/handlebars

event-source-polyfill#1.0.31 public/components/event-source-polyfill

promise-polyfill#7.1.2 public/components/promise-polyfill

bootstrap-daterangepicker#3.0.5 public/components/bootstrap-daterangepicker
├── jquery#3.7.1
└── moment#2.30.1

DOMPurify#1.0.11 public/components/DOMPurify

jquery#3.7.1 public/components/jquery

summernote#0.8.20 public/components/summernote

underscore#1.13.7 public/components/underscore

moment#2.30.1 public/components/moment
Created symlink /etc/systemd/system/multi-user.target.wants/wildduck-webmail.service → /etc/systemd/system/wildduck-webmail.service.

-- Executing 11_install_nginx.sh subscript --
.+..........+.....+..........+.........+.....+.+..+....+......+..+...+....+...+...+.........+..............+....+.....+...+....+.....+.+........+....+...+.....+.........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*............+...+...+..............+...+...+....+...+........+.+...+..+...+......+...............+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+...........+.........+.+...........+...+......+.............+.....+......+.+...+.....+............+.+....................+...+....+...+..+......+......+.........+............+.......+........+.......+......+......+.....+.+...+......+.....+...+.......+.....+.+........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
......+...........+....+...+..+.......+...+...+...+.....+.......+...+.....+.+...................................+.+..+...+....+.....+...+.+......+...+...+.....+....+........+......+......+.+..+.+......+......+...............+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..........+...+..+.......+..+.+..+..........+.....+......+.+.........+............+...+......+.....+...............+...+..........+......+..+.......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+........+.+......+.........+...+........+.........+.............+..+...+...+....+.........+.........+..+....+....................+....+..+.........+......................+...+......+...+...............+........+............+......+......+.........+.+...........+.........+.+...+..............+.......+.........+.....+.+.........+..+...+......+..................+.+..+............+...+...+.+......+...+.....+......+.............+..+....+.....+..........+..+..........+..+............+....+...........+.........+....+...+.....+...+.......+.....+..................+.+...+...+..+...+.......+..+...............+.+..+......+......+...+..........+..+......+...+.......+...+.........+.....+.......+........+.......+....................+.............+.....+.......+.........+.........+..+....+......+...+.....+.+..+...+....+...+...+............+..+.+.....+.+........+..........+...+.........+..............+....+...+.........+........+...+.............+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
nginx.service is not active, cannot reload.

-- Executing 12_install_ufw_rules.sh subscript --
Rules updated
Rules updated (v6)
Rules updated
Rules updated (v6)
Rules updated
Rules updated (v6)
Rules updated
Rules updated (v6)
Rules updated
Rules updated (v6)
Rules updated
Rules updated (v6)
Rules updated
Rules updated (v6)
Firewall is active and enabled on system startup

-- Executing 13_install_ssl_certs.sh subscript --

Redirecting output to ‘wget-log’.
[Thu Sep 26 04:09:11 PM CST 2024] It is recommended to install socat first.
[Thu Sep 26 04:09:11 PM CST 2024] We use socat for standalone server if you use standalone mode.
[Thu Sep 26 04:09:11 PM CST 2024] If you don't use standalone mode, just ignore this warning.
[Thu Sep 26 04:09:11 PM CST 2024] Installing to /root/.acme.sh
[Thu Sep 26 04:09:11 PM CST 2024] Installed to /root/.acme.sh/acme.sh
[Thu Sep 26 04:09:11 PM CST 2024] Installing alias to '/root/.bashrc'
[Thu Sep 26 04:09:11 PM CST 2024] OK, Close and reopen your terminal to start using acme.sh
[Thu Sep 26 04:09:11 PM CST 2024] Installing cron job
no crontab for root
no crontab for root
[Thu Sep 26 04:09:11 PM CST 2024] Good, bash is found, so change the shebang to use bash as preferred.
[Thu Sep 26 04:09:12 PM CST 2024] OK
[Thu Sep 26 04:09:13 PM CST 2024] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Thu Sep 26 04:09:13 PM CST 2024] Create account key ok.
[Thu Sep 26 04:09:14 PM CST 2024] Registering account: https://acme-v02.api.letsencrypt.org/directory
[Thu Sep 26 04:09:15 PM CST 2024] Registered
[Thu Sep 26 04:09:15 PM CST 2024] ACCOUNT_THUMBPRINT='tT15cSPXbbDkyr2F9Dxs_gYHBxTLLT88wLqPXzYCPLk'
[Thu Sep 26 04:09:16 PM CST 2024] Creating domain key
[Thu Sep 26 04:09:16 PM CST 2024] The domain key is here: /root/.acme.sh/mail.hc4Noble.yushei.net_ecc/mail.hc4Noble.yushei.net.key
[Thu Sep 26 04:09:16 PM CST 2024] Single domain='mail.hc4Noble.yushei.net'
[Thu Sep 26 04:09:16 PM CST 2024] Getting domain auth token for each domain
[Thu Sep 26 04:09:18 PM CST 2024] Getting webroot for domain='mail.hc4Noble.yushei.net'
[Thu Sep 26 04:09:18 PM CST 2024] Verifying: mail.hc4Noble.yushei.net
[Thu Sep 26 04:09:18 PM CST 2024] Nginx mode for domain:mail.hc4Noble.yushei.net
[Thu Sep 26 04:09:18 PM CST 2024] Found conf file: /etc/nginx/sites-enabled/mail.hc4Noble.yushei.net
[Thu Sep 26 04:09:18 PM CST 2024] Backup /etc/nginx/sites-enabled/mail.hc4Noble.yushei.net to /root/.acme.sh/mail.hc4Noble.yushei.net_ecc/backup/mail.hc4Noble.yushei.net.nginx.conf
[Thu Sep 26 04:09:18 PM CST 2024] Check the nginx conf before setting up.
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[Thu Sep 26 04:09:18 PM CST 2024] OK, Set up nginx config file
[Thu Sep 26 04:09:18 PM CST 2024] nginx conf is done, let's check it again.
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[Thu Sep 26 04:09:19 PM CST 2024] Reload nginx
nginx: [error] invalid PID number "" in "/run/nginx.pid"
[Thu Sep 26 04:09:19 PM CST 2024] It seems that nginx reload error, let's restore.
[Thu Sep 26 04:09:19 PM CST 2024] Please add '--debug' or '--log' to check more details.
[Thu Sep 26 04:09:19 PM CST 2024] See: https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh
Warning: Failed to generate certificates, using self-signed certs

-- Executing 14_install_start_services.sh subscript --

-- Executing 15_install_deploy.sh subscript --
Waiting for the server to start up...........
Registering DKIM key for hc4Noble.yushei.net
{"domain":"hc4Noble.yushei.net","selector":"sep2024","description":"Default DKIM key for hc4Noble.yushei.net","privateKey":"-----BEGIN PRIVATE KEY-----\nMIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOMrv3w9RIOrR7CD\nJQn3xXpzMZGqEB9g76kVtB8Tz1Afz5dbgbkXVvSbZLFUVxPNCeHd+/XPB/WQnRkZ\ngl9Sop0/pX1Wt2x2AnDhJ20hDrlzuWPfaGaPtYIOhqUsWDJ8WrSQgtnZuk792JBF\nr72cxOFLbq9q26npxVch2qjlljp5AgMBAAECgYAnoxt/JwWMX9dbYhaVXakUS4Mr\nolu7zeMjQokyHve+SD6lby78R6lBdtej5U5oQw9lXKE46428+CWhGoVX8ogyyY20\nCiA1yd6kAWhfGwd685xMhKoac/47LaUvbIDmixir3M3QGysgJAOIOdJOIyGmA4ap\nE0X2ezhTLaZ4p+H2jQJBAPseNYmzCIv6IT0iXNlu+BBi/FYv+tmQUXY9h+oeeK6o\na8KOw0rJ8/C+vxrtuFqQqGDoyDWJbePdxE2zApPENaMCQQDnlls27SdxqwxGoiq7\nk+P5e/e2NIXQJOUbd7kr6512C3/G/41vl2GVzkES4Yr9v4N2Vvc3ffCvcuGnxLw6\nnPkzAkBbb5GA9R6ckVQ/BV8XkO9kUBafb1MAmyr+ScNOfQ/mUM8EBaWYetaHB31g\nWcSxvVCCEOCtlb/co6hRvmem1F/PAkBw078Cxo22AkiLzQwWsRmbfbsUiQg8fQ0l\n0bFkZXkkfru0/uIwYMdJTeBES6AEuh5ZNEtjPLdbMxQfQWkXAU0jAkEAn5jIsn+E\ntogPtnrQZLvyvSE/JLX670a7KooaiX65bBZl3s/DSYj1lLNyNT4fu36ThQ83nUPO\nU5+OoiGnKrRKgw==\n-----END PRIVATE KEY-----\n"}
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1969  100   911  100  1058   3358   3900 --:--:-- --:--:-- --:--:--  7319
HTTP/1.1 200 OK
Server: WildDuck API
vary: origin,access-control-request-method,access-control-request-headers
Content-Type: application/json; charset=utf-8
Content-Length: 911
Date: Thu, 26 Sep 2024 08:09:38 GMT
Connection: keep-alive
Keep-Alive: timeout=5

{
  "id": "66f516c24ce9adb110913d5d",
  "domain": "hc4noble.yushei.net",
  "selector": "sep2024",
  "description": "Default DKIM key for hc4Noble.yushei.net",
  "fingerprint": "be:6e:e6:7f:ac:dd:39:47:bd:35:be:22:31:59:18:a3:02:f5:f9:89:bd:5f:da:cc:73:9a:4a:4e:ba:a1:1e:ea",
  "publicKey": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjK798PUSDq0ewgyUJ98V6czGR\nqhAfYO+pFbQfE89QH8+XW4G5F1b0m2SxVFcTzQnh3fv1zwf1kJ0ZGYJfUqKdP6V9\nVrdsdgJw4SdtIQ65c7lj32hmj7WCDoalLFgyfFq0kILZ2bpO/diQRa+9nMThS26v\natup6cVXIdqo5ZY6eQIDAQAB\n-----END PUBLIC KEY-----\n",
  "dnsTxt": {
    "name": "sep2024._domainkey.hc4noble.yushei.net",
    "value": "v=DKIM1;t=s;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjK798PUSDq0ewgyUJ98V6czGRqhAfYO+pFbQfE89QH8+XW4G5F1b0m2SxVFcTzQnh3fv1zwf1kJ0ZGYJfUqKdP6V9VrdsdgJw4SdtIQ65c7lj32hmj7WCDoalLFgyfFq0kILZ2bpO/diQRa+9nMThS26vatup6cVXIdqo5ZY6eQIDAQAB"
  },
  "success": true
}

DEPLOY SETUP

1. Add your ssh key to /home/deploy/.ssh/authorized_keys

2. Clone application code
$ git clone deploy@mail.hc4Noble.yushei.net:/var/opt/wildduck.git
$ git clone deploy@mail.hc4Noble.yushei.net:/var/opt/zone-mta.git
$ git clone deploy@mail.hc4Noble.yushei.net:/var/opt/wildduck-webmail.git
$ git clone deploy@mail.hc4Noble.yushei.net:/var/opt/haraka-plugin-wildduck.git
$ git clone deploy@mail.hc4Noble.yushei.net:/var/opt/zonemta-wildduck.git

3. After making a change in local copy deploy to server
$ git push origin master
(you might need to use -f when pushing first time)

NAMESERVER SETUP
================

MX
--
Add this MX record to the hc4Noble.yushei.net DNS zone:

hc4Noble.yushei.net. IN MX 5 mail.hc4Noble.yushei.net.

SPF
---
Add this TXT record to the hc4Noble.yushei.net DNS zone:

hc4Noble.yushei.net. IN TXT "v=spf1 a:mail.hc4Noble.yushei.net a:hc4Noble.yushei.net ip4:210.242.152.235 ~all"

Or:
hc4Noble.yushei.net. IN TXT "v=spf1 a:mail.hc4Noble.yushei.net ip4:210.242.152.235 ~all"
hc4Noble.yushei.net. IN TXT "v=spf1 ip4:210.242.152.235 ~all"

Some explanation:
SPF is basically a DNS entry (TXT), where you can define,
which server hosts (a:[HOSTNAME]) or ip address (ip4:[IP_ADDRESS])
are allowed to send emails.
So the receiver server (eg. gmail's server) can look up this entry
and decide if you(as a sender server) is allowed to send emails as
this email address.

If you are unsure, list more a:, ip4 entries, rather then fewer.

Example:
company website: awesome.com
company's email server: mail.awesome.com
company's reverse dns entry for this email server: mail.awesome.com -> 11.22.33.44

SPF record in this case would be:
awesome.com. IN TXT "v=spf1 a:mail.awesome.com a:awesome.com ip4:11.22.33.44 ~all"

The following servers can send emails for *@awesome.com email addresses:
awesome.com (company's website handling server)
mail.awesome.com (company's mail server)
11.22.33.44 (company's mail server's ip address)

Please note, that a:mail.awesome.com is the same as ip4:11.22.33.44, so it is
redundant. But better safe than sorry.
And in this example, the company's website handling server can also send
emails and in general it is an outbound only server.
If a website handles email sending (confirmation emails, contact form, etc).

DKIM
----
Add this TXT record to the hc4Noble.yushei.net DNS zone:

sep2024._domainkey.hc4Noble.yushei.net. IN TXT "v=DKIM1;k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjK798PUSDq0ewgyUJ98V6czGRqhAfYO+pFbQfE89QH8+XW4G5F1b0m2SxVFcTzQnh3fv1zwf1kJ0ZGYJfUqKdP6V9VrdsdgJw4SdtIQ65c7lj32hmj7WCDoalLFgyfFq0kILZ2bpO/diQRa+9nMThS26vatup6cVXIdqo5ZY6eQIDAQAB"

The DKIM .json text we added to wildduck server:
    curl -i -XPOST http://localhost:8080/dkim \
    -H 'Content-type: application/json' \
    -d '{"domain":"hc4Noble.yushei.net","selector":"sep2024","description":"Default DKIM key for hc4Noble.yushei.net","privateKey":"-----BEGIN PRIVATE KEY-----\nMIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOMrv3w9RIOrR7CD\nJQn3xXpzMZGqEB9g76kVtB8Tz1Afz5dbgbkXVvSbZLFUVxPNCeHd+/XPB/WQnRkZ\ngl9Sop0/pX1Wt2x2AnDhJ20hDrlzuWPfaGaPtYIOhqUsWDJ8WrSQgtnZuk792JBF\nr72cxOFLbq9q26npxVch2qjlljp5AgMBAAECgYAnoxt/JwWMX9dbYhaVXakUS4Mr\nolu7zeMjQokyHve+SD6lby78R6lBdtej5U5oQw9lXKE46428+CWhGoVX8ogyyY20\nCiA1yd6kAWhfGwd685xMhKoac/47LaUvbIDmixir3M3QGysgJAOIOdJOIyGmA4ap\nE0X2ezhTLaZ4p+H2jQJBAPseNYmzCIv6IT0iXNlu+BBi/FYv+tmQUXY9h+oeeK6o\na8KOw0rJ8/C+vxrtuFqQqGDoyDWJbePdxE2zApPENaMCQQDnlls27SdxqwxGoiq7\nk+P5e/e2NIXQJOUbd7kr6512C3/G/41vl2GVzkES4Yr9v4N2Vvc3ffCvcuGnxLw6\nnPkzAkBbb5GA9R6ckVQ/BV8XkO9kUBafb1MAmyr+ScNOfQ/mUM8EBaWYetaHB31g\nWcSxvVCCEOCtlb/co6hRvmem1F/PAkBw078Cxo22AkiLzQwWsRmbfbsUiQg8fQ0l\n0bFkZXkkfru0/uIwYMdJTeBES6AEuh5ZNEtjPLdbMxQfQWkXAU0jAkEAn5jIsn+E\ntogPtnrQZLvyvSE/JLX670a7KooaiX65bBZl3s/DSYj1lLNyNT4fu36ThQ83nUPO\nU5+OoiGnKrRKgw==\n-----END PRIVATE KEY-----\n"}'


Please refer to the manual how to change/delete/update DKIM keys
via the REST api (with curl on localhost) for the newest version.

List DKIM keys:
    curl -i http://localhost:8080/dkim
Delete DKIM:
    curl -i -XDELETE http://localhost:8080/dkim/59ef21aef255ed1d9d790e81

Move DKIM keys to another machine:

Save the above curl command and dns entry.
Also copy the following two files too:
/opt/zone-mta/keys/[MAILDOMAIN]-dkim.cert
/opt/zone-mta/keys/[MAILDOMAIN]-dkim.pem

pem: private key (guard it well)
cert: public key

DMARC
---
Add this TXT record to the hc4Noble.yushei.net DNS zone:

_dmarc.hc4Noble.yushei.net. IN TXT "v=DMARC1; p=reject;"

PTR
---
Make sure that your public IP has a PTR record set to mail.hc4Noble.yushei.net.
If your hosting provider does not allow you to set PTR records but has
assigned their own hostname, then edit /etc/zone-mta/pools.toml and replace
the hostname mail.hc4Noble.yushei.net with the actual hostname of this server.


TL;DR
-----
Add the following DNS records to the hc4Noble.yushei.net DNS zone:

hc4Noble.yushei.net. IN MX 5 mail.hc4Noble.yushei.net.
hc4Noble.yushei.net. IN TXT "v=spf1 ip4:210.242.152.235 ~all"
sep2024._domainkey.hc4Noble.yushei.net. IN TXT "v=DKIM1;k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjK798PUSDq0ewgyUJ98V6czGRqhAfYO+pFbQfE89QH8+XW4G5F1b0m2SxVFcTzQnh3fv1zwf1kJ0ZGYJfUqKdP6V9VrdsdgJw4SdtIQ65c7lj32hmj7WCDoalLFgyfFq0kILZ2bpO/diQRa+9nMThS26vatup6cVXIdqo5ZY6eQIDAQAB"
_dmarc.hc4Noble.yushei.net. IN TXT "v=DMARC1; p=reject;"


(this text is also stored to /home/alexlai/build/WildDuck/hc4Noble.yushei.net-nameserver.txt)

All done, open https://mail.hc4Noble.yushei.net/ in your browser