diff --git a/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/README.md b/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/README.md
new file mode 100644
index 0000000..315fd23
--- /dev/null
+++ b/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/README.md
@@ -0,0 +1,722 @@
+
+
+# How to self-host a hardened Borg backup server and configure macOS client
+
+## Requirements
+
+- Virtual private server (VPS) or dedicated server running Debian 10 (buster)
+- Computer running macOS Mojave or Catalina
+
+## Caveats
+
+- When copy/pasting commands that start with `$`, strip out `$` as this character is not part of the command
+- When copy/pasting commands that start with `cat << "EOF"`, select all lines at once (from `cat << "EOF"` to `EOF` inclusively) as they are part of the same (single) command
+
+## Setup guide
+
+### Step 1: create `server` SSH key pair (on Mac)
+
+When asked for file in which to save key, enter `server`.
+
+When asked for passphrase, use output from `openssl rand -base64 24` (and store passphrase in password manager).
+
+Use `server.pub` public key when setting up server.
+
+```console
+$ mkdir -p ~/.ssh
+
+$ cd ~/.ssh
+
+$ ssh-keygen -t rsa -C "server"
+Generating public/private rsa key pair.
+Enter file in which to save the key (/Users/sunknudsen/.ssh/id_rsa): server
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in server.
+Your public key has been saved in server.pub.
+The key fingerprint is:
+SHA256:rZFDBWi8f6BcRR2gqzIWmWtBiLdk89znOSpZkZGOQH8 server
+The key's randomart image is:
++---[RSA 3072]----+
+| .. . o.o+o.. |
+| ..o * o. . |
+|. *.o+E+o. |
+| + *.==.o+ |
+| . B..=S.. |
+| +++.=. |
+| *o. =. |
+| ooo . . |
+| .. |
++----[SHA256]-----+
+
+$ cat server.pub
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCowL4nNnu5Ca3ixlMxD6vVUexhx7M214ElheY/Y3K1mGavd5H6ynhkF71DAgI3YOB3B9KM/IzvV+8ioY+FUVlovBrKwqXzBwb5fnAGPjymjRMY93nYVExICHjI6aQX+9CG1WxRMPhZpDo51sKXORpWQDbMG+CfDa5nmjVjysoCdqwJfd22WEDFIXTiUdVXC5EvJBWiC0MUAphRPmNF/fXyaZPoiL1RmNX7h6JsMQJC/iWHwYgQZhzQCuoAOnvEXKUnu6s7FEUOSbqHCnOuHzxVkDHg1yy667hhyOuwkPdUW276T44GgwicSg/T2IWmwf5cBmDzaSr21kaM00zeg+stqkIwKqdpd0PhV8tjIdKCm3H9GsCRpE0erXLhJVsQTjmmFaodvFyroRHeyH9VBqzYrJXMhG/iXwK8uCeOwGFUosddYw3jJ3sLgsRI34oGKSq9HIRd7P5gdxUZ8cJiZUCpfS4vI4cZDkyR5D8Xvupe/X2pS5Llc8wtiy1K3nxIEQE= server
+```
+
+### Step 2: create `borg` SSH key pair (on Mac)
+
+When asked for file in which to save key, enter `borg`.
+
+When asked for passphrase, leave field empty for no passphrase.
+
+```console
+$ ssh-keygen -t rsa -C "borg"
+Generating public/private rsa key pair.
+Enter file in which to save the key (/Users/sunknudsen/.ssh/id_rsa): borg
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in borg.
+Your public key has been saved in borg.pub.
+The key fingerprint is:
+SHA256:ZB293/YueacLtg2a5anHe/PXruP8YwZXwU/caebReSk borg
+The key's randomart image is:
++---[RSA 3072]----+
+| .. ..*|
+| . ..E X*|
+| o . .=.=|
+| o . .o|
+| S . ..|
+| ...o|
+| .= ooo|
+| *oB*+*|
+| +o=+X&O|
++----[SHA256]-----+
+
+$ cat borg.pub
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDawvaD0JmNz3XBChQq9OZROa0psAwH0BpHwGZ/4cuDiTnU8gt3gYXDANkS++SKbUNMJCQW3QgVNFhpk2SmWA8lLvlpuD5J3kvHNFNKFv/hBc0XxsVJlpASONeCwilnS5otIqnDT0+KFMOevZUMCumEoBtjQ3IQbGkpWgf3NJ6ysXkt6kLRk7PMls4E733v/T4XUJmeBWT6B0rECqWE3aFzrjjZbfyJho0Pp8VzjT3m4vknNCvvwionjXRti5ObvEo3OZGWQbuhwW63JPS+aldNX9Xo0VC8t2UuSzzy7OeGI+JB76Pw1RYfXaMeflHry3O50kCIWIWHPNblw0sBPBsRs9BDg4R8urwpdVYjyirw9cZHDA8lkPxh0WS3IbA7Q1iRlVrfJkm9r4SqohxwQUeHIT7lpsyDHObUDF3KejRCWtyCqabPJVHqvGIds6rjQQo9lP5JNkeHg+qg8Cw61FihGLrlFStvgx1pMbBo2TvMEsRo65psVYUyi79taqbdlZM= borg
+```
+
+### Step 3: generate SSH authorized keys heredoc (on Mac)
+
+#### Set temporary environment variable
+
+`BORG_STORAGE_QUOTA` backup storage quota
+
+```shell
+BORG_STORAGE_QUOTA="10G"
+```
+
+#### Generate heredoc (the output of following command will be used at [step 21](#step-21-configure-borgs-ssh-authorized-keys))
+
+```shell
+cat << _EOF
+cat << EOF > /home/borg/.ssh/authorized_keys
+command="borg serve --append-only --restrict-to-repository /home/borg/backup --storage-quota $BORG_STORAGE_QUOTA",restrict $(cat ~/.ssh/borg.pub)"
+command="borg serve --restrict-to-repository /home/borg/backup --storage-quota $BORG_STORAGE_QUOTA",restrict $(cat ~/.ssh/server.pub)"
+EOF
+_EOF
+```
+
+### Step 4: log in to server as root
+
+Replace `185.112.144.30` with IP of server.
+
+```shell
+ssh root@185.112.144.30 -i ~/.ssh/server
+```
+
+### Step 5: create `server-admin` user
+
+When asked for password, use output from `openssl rand -base64 24` (and store password in password manager).
+
+All other fields are optional, press enter to skip them and then press Y.
+
+```console
+$ adduser server-admin
+Adding user `server-admin' ...
+Adding new group `server-admin' (1000) ...
+Adding new user `server-admin' (1000) with group `server-admin' ...
+Creating home directory `/home/server-admin' ...
+Copying files from `/etc/skel' ...
+New password:
+Retype new password:
+passwd: password updated successfully
+Changing the user information for server-admin
+Enter the new value, or press ENTER for the default
+ Full Name []:
+ Room Number []:
+ Work Phone []:
+ Home Phone []:
+ Other []:
+Is the information correct? [Y/n] Y
+```
+
+### Step 6: create `borg` user
+
+When asked for password, use output from `openssl rand -base64 24` (and store password in password manager).
+
+All other fields are optional, press enter to skip them and then press Y.
+
+```console
+$ adduser borg
+Adding user `borg' ...
+Adding new group `borg' (1000) ...
+Adding new user `borg' (1000) with group `borg' ...
+Creating home directory `/home/borg' ...
+Copying files from `/etc/skel' ...
+New password:
+Retype new password:
+passwd: password updated successfully
+Changing the user information for borg
+Enter the new value, or press ENTER for the default
+ Full Name []:
+ Room Number []:
+ Work Phone []:
+ Home Phone []:
+ Other []:
+Is the information correct? [Y/n] Y
+```
+
+### Step 7: copy root’s `authorized_keys` file to server-admin’s home folder
+
+```shell
+mkdir /home/server-admin/.ssh
+cp /root/.ssh/authorized_keys /home/server-admin/.ssh/authorized_keys
+chown -R server-admin:server-admin /home/server-admin/.ssh
+```
+
+### Step 8: set root password
+
+When asked for password, use output from `openssl rand -base64 24` (and store password in password manager).
+
+```shell
+passwd
+```
+
+### Step 9: log out
+
+```shell
+exit
+```
+
+### Step 10: log in as `server-admin`
+
+Replace `185.112.144.30` with IP of server.
+
+```shell
+ssh server-admin@185.112.144.30 -i ~/.ssh/server
+```
+
+### Step 11: switch to root
+
+When asked, enter root password.
+
+```shell
+su -
+```
+
+### Step 12: update SSH config to disable root login and password authentication and restart SSH
+
+```shell
+sed -i -E 's/(#)?PermitRootLogin (prohibit-password|yes)/PermitRootLogin no/' /etc/ssh/sshd_config
+sed -i -E 's/(#)?PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
+systemctl restart ssh
+```
+
+### Step 13: update APT index and upgrade packages
+
+#### Update APT index
+
+```shell
+apt update
+```
+
+#### Upgrade packages
+
+```shell
+apt upgrade -y
+```
+
+### Step 14: install and configure Vim
+
+#### Install Vim
+
+```shell
+apt install -y vim
+```
+
+#### Configure Vim
+
+```shell
+cat << "EOF" > ~/.vimrc
+set encoding=UTF-8
+set termencoding=UTF-8
+set nocompatible
+set backspace=indent,eol,start
+set autoindent
+set tabstop=2
+set shiftwidth=2
+set expandtab
+set smarttab
+set ruler
+set paste
+syntax on
+EOF
+```
+
+### Step 15: set timezone (the following is for Montreal time)
+
+See [https://en.wikipedia.org/wiki/List_of_tz_database_time_zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for available timezones.
+
+```shell
+timedatectl set-timezone America/Montreal
+```
+
+### Step 16: install iptables-persistent
+
+When asked to save current IPv4 or IPv6 rules, answer `Yes`.
+
+```shell
+apt install -y iptables-persistent
+```
+
+### Step 17: configure iptables
+
+```shell
+iptables -N SSH_BRUTE_FORCE_MITIGATION
+iptables -A SSH_BRUTE_FORCE_MITIGATION -m recent --name SSH --set
+iptables -A SSH_BRUTE_FORCE_MITIGATION -m recent --name SSH --update --seconds 300 --hitcount 10 -m limit --limit 1/second --limit-burst 100 -j LOG --log-prefix "iptables[ssh-brute-force]: "
+iptables -A SSH_BRUTE_FORCE_MITIGATION -m recent --name SSH --update --seconds 300 --hitcount 10 -j DROP
+iptables -A SSH_BRUTE_FORCE_MITIGATION -j ACCEPT
+iptables -A INPUT -i lo -j ACCEPT
+iptables -A INPUT -p tcp --dport 22 --syn -m conntrack --ctstate NEW -j SSH_BRUTE_FORCE_MITIGATION
+iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
+iptables -A OUTPUT -o lo -j ACCEPT
+iptables -A OUTPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT
+iptables -A OUTPUT -p udp --dport 53 -m state --state NEW -j ACCEPT
+iptables -A OUTPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
+iptables -A OUTPUT -p udp --dport 123 -m state --state NEW -j ACCEPT
+iptables -A OUTPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT
+iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
+iptables -P FORWARD DROP
+iptables -P INPUT DROP
+iptables -P OUTPUT DROP
+```
+
+If the server is IPv4-only, run:
+
+```shell
+ip6tables -P FORWARD DROP
+ip6tables -P INPUT DROP
+ip6tables -P OUTPUT DROP
+```
+
+If the server is dual stack (IPv4 + IPv6) run:
+
+```shell
+ip6tables -A INPUT -i lo -j ACCEPT
+ip6tables -A INPUT -p ipv6-icmp --icmpv6-type destination-unreachable -j ACCEPT
+ip6tables -A INPUT -p ipv6-icmp --icmpv6-type packet-too-big -j ACCEPT
+ip6tables -A INPUT -p ipv6-icmp --icmpv6-type time-exceeded -j ACCEPT
+ip6tables -A INPUT -p ipv6-icmp --icmpv6-type parameter-problem -j ACCEPT
+ip6tables -A INPUT -p ipv6-icmp --icmpv6-type router-advertisement -m hl --hl-eq 255 -j ACCEPT
+ip6tables -A INPUT -p ipv6-icmp --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j ACCEPT
+ip6tables -A INPUT -p ipv6-icmp --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j ACCEPT
+ip6tables -A INPUT -p ipv6-icmp --icmpv6-type redirect -m hl --hl-eq 255 -j ACCEPT
+ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
+ip6tables -A OUTPUT -o lo -j ACCEPT
+ip6tables -A OUTPUT -p ipv6-icmp --icmpv6-type destination-unreachable -j ACCEPT
+ip6tables -A OUTPUT -p ipv6-icmp --icmpv6-type packet-too-big -j ACCEPT
+ip6tables -A OUTPUT -p ipv6-icmp --icmpv6-type time-exceeded -j ACCEPT
+ip6tables -A OUTPUT -p ipv6-icmp --icmpv6-type parameter-problem -j ACCEPT
+ip6tables -A OUTPUT -p ipv6-icmp --icmpv6-type router-solicitation -m hl --hl-eq 255 -j ACCEPT
+ip6tables -A OUTPUT -p ipv6-icmp --icmpv6-type neighbour-solicitation -m hl --hl-eq 255 -j ACCEPT
+ip6tables -A OUTPUT -p ipv6-icmp --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT
+ip6tables -A OUTPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT
+ip6tables -A OUTPUT -p udp --dport 53 -m state --state NEW -j ACCEPT
+ip6tables -A OUTPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
+ip6tables -A OUTPUT -p udp --dport 123 -m state --state NEW -j ACCEPT
+ip6tables -A OUTPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT
+ip6tables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
+ip6tables -P FORWARD DROP
+ip6tables -P INPUT DROP
+ip6tables -P OUTPUT DROP
+```
+
+### Step 18: log out and log in to confirm iptables didn’t block SSH
+
+#### Log out
+
+```shell
+exit
+exit
+```
+
+#### Log in
+
+Replace `185.112.144.30` with IP of server.
+
+```shell
+ssh server-admin@185.112.144.30 -i ~/.ssh/server
+```
+
+#### Switch to root
+
+When asked, enter root password.
+
+```shell
+su -
+```
+
+### Step 19: make iptables rules persistent
+
+```shell
+iptables-save > /etc/iptables/rules.v4
+ip6tables-save > /etc/iptables/rules.v6
+```
+
+### Step 20: install [Borg](https://github.com/borgbackup/borg)
+
+```shell
+apt install -y borgbackup
+```
+
+### Step 21: configure borg’s SSH authorized keys
+
+#### Switch to borg
+
+```shell
+su - borg
+```
+
+#### Create `.ssh` folder if it doesn’t exist
+
+```shell
+mkdir -p /home/borg/.ssh
+```
+
+#### Create `/home/borg/.ssh/authorized_keys`
+
+> Heads-up: use heredoc generated at [step 3](#step-3-generate-ssh-authorized-keys-heredoc-on-mac).
+
+```shell
+cat << EOF > /home/borg/.ssh/authorized_keys
+command="borg serve --append-only --restrict-to-repository /home/borg/backup --storage-quota 10G",restrict ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDawvaD0JmNz3XBChQq9OZROa0psAwH0BpHwGZ/4cuDiTnU8gt3gYXDANkS++SKbUNMJCQW3QgVNFhpk2SmWA8lLvlpuD5J3kvHNFNKFv/hBc0XxsVJlpASONeCwilnS5otIqnDT0+KFMOevZUMCumEoBtjQ3IQbGkpWgf3NJ6ysXkt6kLRk7PMls4E733v/T4XUJmeBWT6B0rECqWE3aFzrjjZbfyJho0Pp8VzjT3m4vknNCvvwionjXRti5ObvEo3OZGWQbuhwW63JPS+aldNX9Xo0VC8t2UuSzzy7OeGI+JB76Pw1RYfXaMeflHry3O50kCIWIWHPNblw0sBPBsRs9BDg4R8urwpdVYjyirw9cZHDA8lkPxh0WS3IbA7Q1iRlVrfJkm9r4SqohxwQUeHIT7lpsyDHObUDF3KejRCWtyCqabPJVHqvGIds6rjQQo9lP5JNkeHg+qg8Cw61FihGLrlFStvgx1pMbBo2TvMEsRo65psVYUyi79taqbdlZM= borg"
+command="borg serve --restrict-to-repository /home/borg/backup --storage-quota 10G",restrict ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCowL4nNnu5Ca3ixlMxD6vVUexhx7M214ElheY/Y3K1mGavd5H6ynhkF71DAgI3YOB3B9KM/IzvV+8ioY+FUVlovBrKwqXzBwb5fnAGPjymjRMY93nYVExICHjI6aQX+9CG1WxRMPhZpDo51sKXORpWQDbMG+CfDa5nmjVjysoCdqwJfd22WEDFIXTiUdVXC5EvJBWiC0MUAphRPmNF/fXyaZPoiL1RmNX7h6JsMQJC/iWHwYgQZhzQCuoAOnvEXKUnu6s7FEUOSbqHCnOuHzxVkDHg1yy667hhyOuwkPdUW276T44GgwicSg/T2IWmwf5cBmDzaSr21kaM00zeg+stqkIwKqdpd0PhV8tjIdKCm3H9GsCRpE0erXLhJVsQTjmmFaodvFyroRHeyH9VBqzYrJXMhG/iXwK8uCeOwGFUosddYw3jJ3sLgsRI34oGKSq9HIRd7P5gdxUZ8cJiZUCpfS4vI4cZDkyR5D8Xvupe/X2pS5Llc8wtiy1K3nxIEQE= server"
+EOF
+```
+
+> Heads-up: the following steps are done on Mac.
+
+### Step 22: download and install [FUSE for macOS](https://osxfuse.github.io/)
+
+Go to [https://osxfuse.github.io/](https://osxfuse.github.io/), download and install latest release.
+
+### Step 23: install [Borg](https://github.com/borgbackup/borg)
+
+#### Install [Homebrew](https://brew.sh/)
+
+```shell
+/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
+```
+
+#### Disable Homebrew analytics
+
+```shell
+brew analytics off
+```
+
+#### Install Borg
+
+```shell
+brew install borgbackup
+```
+
+#### Initialize Borg repo
+
+Replace `185.112.144.30` with IP of server.
+
+```shell
+export BORG_PASSCOMMAND="security find-generic-password -a $USER -s borg-passphrase -w"
+export BORG_RSH="ssh -i ~/.ssh/borg"
+borg init --encryption=keyfile-blake2 "borg@185.112.144.30:backup"
+
+By default repositories initialized with this version will produce security
+errors if written to with an older version (up to and including Borg 1.0.8).
+
+If you want to use these older versions, you can disable the check by running:
+borg upgrade --disable-tam ssh://borg@185.112.144.30/./backup
+
+See https://borgbackup.readthedocs.io/en/stable/changes.html#pre-1-0-9-manifest-spoofing-vulnerability for details about the security implications.
+
+IMPORTANT: you will need both KEY AND PASSPHRASE to access this repo!
+Use "borg key export" to export the key, optionally in printable format.
+Write down the passphrase. Store both at safe place(s).
+
+```
+
+#### Backup `~/.config/borg` folder (IMPORTANT!)
+
+> Heads-up: `~/.config/borg` includes a key which is used alongside passphrase to encrypt data.
+
+### Step 24: generate "Keychain Access" backup password
+
+```shell
+security add-generic-password -D secret -U -a $USER -s borg-passphrase -w $(openssl rand -base64 24)
+```
+
+### Step 25: set temporary environment variables
+
+Replace `185.112.144.30` with IP of server and set backup name.
+
+```shell
+SERVER_IP="185.112.144.30"
+BACKUP_NAME="$USER-macbook-pro"
+```
+
+### Step 26: create `/usr/local/bin/borg-backup.sh` script
+
+```shell
+cat << EOF > /usr/local/bin/borg-backup.sh
+#! /bin/sh
+
+set -e
+
+repo="borg@$SERVER_IP:backup"
+prefix="$BACKUP_NAME-"
+
+export BORG_PASSCOMMAND="security find-generic-password -a $USER -s borg-passphrase -w"
+export BORG_RSH="ssh -i ~/.ssh/borg"
+
+borg create \\
+ --filter "AME" \\
+ --list \\
+ --stats \\
+ --verbose \\
+ "\$repo::\$prefix{now:%F-%H%M%S}" \\
+ "/Users/$USER/.gnupg" \\
+ "/Users/$USER/.ssh" \\
+ "/Users/$USER/Library/Keychains"
+
+printf "%s\n" "Done"
+EOF
+chmod +x /usr/local/bin/borg-backup.sh
+```
+
+### Step 27: edit `/usr/local/bin/borg-backup.sh` script
+
+```shell
+vi /usr/local/bin/borg-backup.sh
+```
+
+### Step 28: create `/usr/local/bin/borg-list.sh` script
+
+```shell
+cat << EOF > /usr/local/bin/borg-list.sh
+#! /bin/sh
+
+set -e
+
+prefix="$BACKUP_NAME-"
+repo="borg@$SERVER_IP:backup"
+
+export BORG_PASSCOMMAND="security find-generic-password -a $USER -s borg-passphrase -w"
+export BORG_RSH="ssh -i ~/.ssh/borg"
+
+borg list --prefix "\$prefix" "\$repo"
+
+printf "%s\n" "Done"
+EOF
+chmod +x /usr/local/bin/borg-list.sh
+```
+
+### Step 29: create `/usr/local/bin/borg-prune.sh` script
+
+```shell
+cat << EOF > /usr/local/bin/borg-prune.sh
+#! /bin/sh
+
+set -e
+
+prefix="$BACKUP_NAME-"
+repo="borg@$SERVER_IP:backup"
+
+export BORG_PASSCOMMAND="security find-generic-password -a $USER -s borg-passphrase -w"
+export BORG_RSH="ssh -i ~/.ssh/server"
+
+borg prune --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --list --prefix "\$prefix" --stats "\$repo"
+
+printf "%s\n" "Done"
+EOF
+chmod +x /usr/local/bin/borg-prune.sh
+```
+
+### Step 30: create `/usr/local/bin/borg-restore.sh` script
+
+```shell
+cat << EOF > /usr/local/bin/borg-restore.sh
+#! /bin/sh
+
+set -e
+
+function umount()
+{
+ if [ -d "\$mount_point" ]; then
+ borg umount \$mount_point
+ fi
+}
+
+trap umount ERR INT
+
+mount_point="\${TMPDIR}borg"
+prefix="$BACKUP_NAME-"
+repo="borg@$SERVER_IP:backup"
+
+mkdir -p \$mount_point
+
+export BORG_PASSCOMMAND="security find-generic-password -a $USER -s borg-passphrase -w"
+export BORG_RSH="ssh -i ~/.ssh/borg"
+
+borg mount --prefix "\$prefix" "\$repo" "\$mount_point"
+
+open \$mount_point
+
+printf "Restore data and press enter"
+
+read -r answer
+
+umount
+
+printf "%s\n" "Done"
+EOF
+chmod +x /usr/local/bin/borg-restore.sh
+```
+
+### Step 31: download and install [Borg Backup](https://github.com/sunknudsen/borg-backup/releases/download/v1.0/borg-backup-1.0.dmg) ([PGP signature](https://github.com/sunknudsen/borg-backup/releases/download/v1.0/borg-backup-1.0.dmg.sig), [PGP public key](https://sunknudsen.com/sunknudsen.asc))
+
+> Heads-up: source code available on [GitHub](https://github.com/sunknudsen/borg-backup).
+
+### Step 32: initialize Borg Backup
+
+```shell
+open /Applications/Borg\ Backup.app
+```
+
+> Heads-up: given Borg Backup is developed outside the [Apple Developer Program](https://developer.apple.com/programs/), macOS will prevent opening the app without explicit consent (“Open Anyway”) in “System Preferences” / “Privacy & Security”.
+
+
+
+
+
+
+
+### Step 33: schedule backup every hour using launchd
+
+```shell
+mkdir -p ~/Library/LaunchAgents
+cat << EOF > ~/Library/LaunchAgents/local.borg-backup.plist
+
+
+
+
+ Label
+ Borg Backup.app
+
+ ProgramArguments
+
+ open
+ /Applications/Borg Backup.app
+
+
+ RunAtLoad
+
+
+ StartCalendarInterval
+
+ Minute
+ 0
+
+
+
+EOF
+launchctl load ~/Library/LaunchAgents/local.borg-backup.plist
+```
+
+## Usage guide
+
+### Backup
+
+```console
+$ borg-backup.sh
+Creating archive at "borg@185.112.144.30:backup::sunknudsen-macbook-pro-{now:%F-%H%M%S}"
+A /Users/sunknudsen/Library/Keychains/4FD89B1C-70AF-58EC-8026-35E97A08F9FE/keychain-2.db-wal
+Remote: Storage quota: 667.73 kB out of 10.00 GB used.
+Remote: Storage quota: 671.72 kB out of 10.00 GB used.
+------------------------------------------------------------------------------
+Archive name: sunknudsen-macbook-pro-2020-11-12-095711
+Archive fingerprint: 943420e2bfd0154a953c7dc84a6c42f1ab49888e17453df0c63518b65512d718
+Time (start): Thu, 2020-11-12 09:57:14
+Time (end): Thu, 2020-11-12 09:57:15
+Duration: 0.39 seconds
+Number of files: 29
+Utilization of max. archive size: 0%
+------------------------------------------------------------------------------
+ Original size Compressed size Deduplicated size
+This archive: 8.43 MB 666.16 kB 3.84 kB
+All archives: 16.87 MB 1.33 MB 669.77 kB
+
+ Unique chunks Total chunks
+Chunk index: 31 62
+------------------------------------------------------------------------------
+Done
+```
+
+Done
+
+👍
+
+### List
+
+```console
+$ borg-list.sh
+sunknudsen-macbook-pro-2020-11-12-095625 Thu, 2020-11-12 09:56:28 [a8f8ef592501cc240da7f000b23626a4371719565d8c9e5ce55855b1fe465742]
+sunknudsen-macbook-pro-2020-11-12-095711 Thu, 2020-11-12 09:57:14 [943420e2bfd0154a953c7dc84a6c42f1ab49888e17453df0c63518b65512d718]
+Done
+```
+
+Done
+
+👍
+
+### Prune
+
+```console
+$ borg-prune.sh
+borg-prune.sh
+Enter passphrase for key '/Users/sunknudsen/.ssh/server':
+Keeping archive: sunknudsen-macbook-pro-2020-11-12-095711 Thu, 2020-11-12 09:57:14 [943420e2bfd0154a953c7dc84a6c42f1ab49888e17453df0c63518b65512d718]
+Pruning archive: sunknudsen-macbook-pro-2020-11-12-095625 Thu, 2020-11-12 09:56:28 [a8f8ef592501cc240da7f000b23626a4371719565d8c9e5ce55855b1fe465742] (1/1)
+------------------------------------------------------------------------------
+ Original size Compressed size Deduplicated size
+Deleted data: -8.43 MB -666.16 kB -3.84 kB
+All archives: 8.43 MB 666.16 kB 665.93 kB
+
+ Unique chunks Total chunks
+Chunk index: 29 31
+------------------------------------------------------------------------------
+Done
+```
+
+Done
+
+👍
+
+### Restore
+
+```console
+$ borg-restore.sh
+Restore data and press enter
+Done
+```
+
+Done
+
+👍
diff --git a/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/allow-app-step-1.png b/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/allow-app-step-1.png
new file mode 100755
index 0000000..bf703fd
Binary files /dev/null and b/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/allow-app-step-1.png differ
diff --git a/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/allow-app-step-2.png b/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/allow-app-step-2.png
new file mode 100755
index 0000000..bbc1732
Binary files /dev/null and b/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/allow-app-step-2.png differ
diff --git a/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/allow-app-step-3.png b/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/allow-app-step-3.png
new file mode 100755
index 0000000..e70e649
Binary files /dev/null and b/how-to-self-host-a-hardened-borg-backup-server-and-configure-macos-client/allow-app-step-3.png differ