From 697d2a002f817a71615af289b8c0900f2e806da8 Mon Sep 17 00:00:00 2001 From: Steven Foerster Date: Thu, 30 Apr 2020 01:56:43 +0000 Subject: [PATCH 1/7] Resolve "SSH" --- README.md | 3 ++- scripts/install.sh | 2 ++ scripts/subinstallers/cockpit.sh | 11 +++++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 38db946..88f3f9c 100644 --- a/README.md +++ b/README.md @@ -397,6 +397,7 @@ These are some notes regarding the technical design and implementations of Mistb - The "Update" button will pull updated Docker images for mistborn, postgresql, redis, pihole, and dnscrypt. Those services will then be restarted. - The generated TLS certificate has an RSA modulus of 4096 bits, is signed with SHA-256, and is good for 10 years. The nanny at Apple has decided to restrict the kinds of certificates iOS users may choose to manually trust and so you may have issues with TLS on an Apple device for now. - Outbound UDP on port 53 is blocked. All DNS requests should be handled by the dnscrypt_proxy service and if any client, service, etc. tries to circumvent that it is blocked. +- Unattended upgrades are set to automatically install operating system security updates. # Roadmap Many features and refinements are in the works at various stages including: @@ -414,7 +415,7 @@ Many features and refinements are in the works at various stages including: Contact me at [steven@cyber5k.com](mailto:steven@cyber5k.com) -# Support +# Support Mistborn Please consider supporting the project via: - [Paypal.me](https://paypal.me/cyber5k) diff --git a/scripts/install.sh b/scripts/install.sh index 87f4e2f..1d81e21 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -119,6 +119,8 @@ sudo sed -i 's/#PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/s sudo sed -i 's/PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config sudo sed -i 's/#PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config sudo sed -i 's/PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config +sudo sed -i 's/#Port.*/Port 22/' /etc/ssh/sshd_config +sudo sed -i 's/Port.*/Port 22/' /etc/ssh/sshd_config sudo systemctl enable ssh sudo systemctl restart ssh diff --git a/scripts/subinstallers/cockpit.sh b/scripts/subinstallers/cockpit.sh index da90569..1a9d7f5 100755 --- a/scripts/subinstallers/cockpit.sh +++ b/scripts/subinstallers/cockpit.sh @@ -4,22 +4,25 @@ figlet "Mistborn: Installing Cockpit" if [ "$DISTRO" == "ubuntu" ]; then echo "Ubuntu backports enabled by default" - - sudo apt-get install -y cockpit cockpit-docker elif [ "$DISTRO" == "debian" ]; then sudo grep -qF "buster-backports" /etc/apt/sources.list.d/backports.list \ && echo "buster-backports already in sources" \ || echo 'deb http://deb.debian.org/debian buster-backports main' | sudo tee -a /etc/apt/sources.list.d/backports.list - sudo apt-get install -y cockpit cockpit-docker elif [ "$DISTRO" == "raspbian" ]; then echo "Raspbian repos contain cockpit" - sudo apt-get install -y cockpit cockpit-docker fi + +sudo apt-get install -y cockpit + +if $(sudo apt-cache show cockpit-docker > /dev/null 2>&1) ; then + # no longer supported upstream in Ubuntu 20.04 + sudo apt-get install -y cockpit-docker +fi sudo cp ./scripts/conf/cockpit.conf /etc/cockpit/cockpit.conf sudo systemctl restart cockpit.socket From f4d24dc755bf771941699760650aec1ca033a89a Mon Sep 17 00:00:00 2001 From: Steven Foerster Date: Thu, 30 Apr 2020 21:09:21 -0400 Subject: [PATCH 2/7] iptables -w --- scripts/services/Mistborn-base.service | 2 +- scripts/services/Mistborn-bitwarden.service | 2 +- scripts/services/Mistborn-jitsi.service | 2 +- scripts/services/Mistborn-rocketchat.service | 2 +- scripts/services/Mistborn-syncthing.service | 2 +- scripts/services/Mistborn-tor.service | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/services/Mistborn-base.service b/scripts/services/Mistborn-base.service index a810c4a..5857e07 100644 --- a/scripts/services/Mistborn-base.service +++ b/scripts/services/Mistborn-base.service @@ -14,7 +14,7 @@ ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/base.yml down ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/base.yml build ExecStartPre=-/sbin/ip address add 10.2.3.1/30 dev DIFACE -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p udp --dport 53 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p udp --dport 53 -j MISTBORN_LOG_DROP ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 53 -j MISTBORN_LOG_DROP ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 80 -j MISTBORN_LOG_DROP ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 443 -j MISTBORN_LOG_DROP diff --git a/scripts/services/Mistborn-bitwarden.service b/scripts/services/Mistborn-bitwarden.service index 4a1df26..d722101 100644 --- a/scripts/services/Mistborn-bitwarden.service +++ b/scripts/services/Mistborn-bitwarden.service @@ -11,7 +11,7 @@ PermissionsStartOnly=true # Shutdown container (if running) when unit is stopped ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/bitwarden.yml down -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 3012 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p tcp --dport 3012 -j MISTBORN_LOG_DROP # Start container when unit is started ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/bitwarden.yml up --build # Stop container when unit is stopped diff --git a/scripts/services/Mistborn-jitsi.service b/scripts/services/Mistborn-jitsi.service index 80970e9..a5946db 100644 --- a/scripts/services/Mistborn-jitsi.service +++ b/scripts/services/Mistborn-jitsi.service @@ -13,7 +13,7 @@ EnvironmentFile=/opt/mistborn/.envs/.production/.jitsi # Shutdown container (if running) when unit is stopped ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/jitsi-meet.yml down -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p udp --dport $JVB_PORT -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p udp --dport $JVB_PORT -j MISTBORN_LOG_DROP ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport $JVB_TCP_PORT -j MISTBORN_LOG_DROP # Start container when unit is started ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/jitsi-meet.yml up --build diff --git a/scripts/services/Mistborn-rocketchat.service b/scripts/services/Mistborn-rocketchat.service index 1b8b90c..1c75a6f 100644 --- a/scripts/services/Mistborn-rocketchat.service +++ b/scripts/services/Mistborn-rocketchat.service @@ -11,7 +11,7 @@ PermissionsStartOnly=true # Shutdown container (if running) when unit is stopped ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/rocketchat.yml down -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 3001 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p tcp --dport 3001 -j MISTBORN_LOG_DROP # Start container when unit is started ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/rocketchat.yml up --build # Stop container when unit is stopped diff --git a/scripts/services/Mistborn-syncthing.service b/scripts/services/Mistborn-syncthing.service index 3e5ea0b..876a6c9 100644 --- a/scripts/services/Mistborn-syncthing.service +++ b/scripts/services/Mistborn-syncthing.service @@ -11,7 +11,7 @@ PermissionsStartOnly=true # Shutdown container (if running) when unit is stopped ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/syncthing.yml down -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p udp --dport 21027 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p udp --dport 21027 -j MISTBORN_LOG_DROP ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 22000 -j MISTBORN_LOG_DROP # Start container when unit is started ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/syncthing.yml up --build diff --git a/scripts/services/Mistborn-tor.service b/scripts/services/Mistborn-tor.service index de794bc..90da6b9 100644 --- a/scripts/services/Mistborn-tor.service +++ b/scripts/services/Mistborn-tor.service @@ -11,7 +11,7 @@ PermissionsStartOnly=true # Shutdown container (if running) when unit is stopped ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/tor.yml down -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 9150 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p tcp --dport 9150 -j MISTBORN_LOG_DROP # Start container when unit is started ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/tor.yml up --build # Stop container when unit is stopped From 140ed04828e1938ac0ed5804d92949b3d526fc21 Mon Sep 17 00:00:00 2001 From: Steven Foerster Date: Sat, 9 May 2020 11:23:05 -0400 Subject: [PATCH 3/7] cockpit env --- base.yml | 2 +- scripts/install.sh | 3 +++ scripts/services/Mistborn-base.service | 14 +++++++------- scripts/services/Mistborn-bitwarden.service | 2 +- scripts/services/Mistborn-jitsi.service | 4 ++-- scripts/services/Mistborn-rocketchat.service | 2 +- scripts/services/Mistborn-syncthing.service | 4 ++-- scripts/services/Mistborn-tor.service | 2 +- scripts/subinstallers/gen_prod_env.sh | 1 + 9 files changed, 19 insertions(+), 15 deletions(-) diff --git a/base.yml b/base.yml index 19fd8a6..4596b96 100644 --- a/base.yml +++ b/base.yml @@ -166,7 +166,7 @@ services: - DNSCRYPT_LISTEN_PORT=5054 # resolvers: https://download.dnscrypt.info/dnscrypt-resolvers/v2/public-resolvers.md #- DNSCRYPT_SERVER_NAMES=['scaleway-fr','google','yandex','cloudflare'] - - DNSCRYPT_SERVER_NAMES=['cloudflare','dnswarden-doh1','dnswarden-doh2','dnswarden-doh3','securedns-doh','adguard-dns-doh'] + - DNSCRYPT_SERVER_NAMES=['cloudflare','dnswarden-doh1','dnswarden-doh2','dnswarden-doh3','adguard-dns-doh'] networks: pihole_net: ipv4_address: 10.2.0.2 diff --git a/scripts/install.sh b/scripts/install.sh index 1d81e21..7d48206 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -150,6 +150,9 @@ if [[ "$MISTBORN_INSTALL_COCKPIT" =~ ^([yY][eE][sS]|[yY])$ ]] then # install cockpit source ./scripts/subinstallers/cockpit.sh + + # set variable (that will be available in environment) + MISTBORN_INSTALL_COCKPIT=Y fi # Mistborn-cli (pip3 installed by docker) diff --git a/scripts/services/Mistborn-base.service b/scripts/services/Mistborn-base.service index 5857e07..2428a7b 100644 --- a/scripts/services/Mistborn-base.service +++ b/scripts/services/Mistborn-base.service @@ -14,13 +14,13 @@ ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/base.yml down ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/base.yml build ExecStartPre=-/sbin/ip address add 10.2.3.1/30 dev DIFACE -ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p udp --dport 53 -j MISTBORN_LOG_DROP -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 53 -j MISTBORN_LOG_DROP -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 80 -j MISTBORN_LOG_DROP -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 443 -j MISTBORN_LOG_DROP -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 5555 -j MISTBORN_LOG_DROP -ExecStartPre=/sbin/iptables -A OUTPUT -o DIFACE -p udp --dport 53 -j MISTBORN_LOG_DROP -ExecStartPre=/sbin/ip6tables -A OUTPUT -p udp --dport 53 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p udp --dport 53 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p tcp --dport 53 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p tcp --dport 80 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p tcp --dport 443 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p tcp --dport 5555 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -A OUTPUT -o DIFACE -p udp --dport 53 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/ip6tables -w -A OUTPUT -p udp --dport 53 -j MISTBORN_LOG_DROP ExecStartPre=/sbin/resolvconf -u # Start container when unit is started ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/base.yml up diff --git a/scripts/services/Mistborn-bitwarden.service b/scripts/services/Mistborn-bitwarden.service index d722101..ff79fde 100644 --- a/scripts/services/Mistborn-bitwarden.service +++ b/scripts/services/Mistborn-bitwarden.service @@ -11,7 +11,7 @@ PermissionsStartOnly=true # Shutdown container (if running) when unit is stopped ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/bitwarden.yml down -ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p tcp --dport 3012 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p tcp --dport 3012 -j MISTBORN_LOG_DROP # Start container when unit is started ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/bitwarden.yml up --build # Stop container when unit is stopped diff --git a/scripts/services/Mistborn-jitsi.service b/scripts/services/Mistborn-jitsi.service index a5946db..49a9c21 100644 --- a/scripts/services/Mistborn-jitsi.service +++ b/scripts/services/Mistborn-jitsi.service @@ -13,8 +13,8 @@ EnvironmentFile=/opt/mistborn/.envs/.production/.jitsi # Shutdown container (if running) when unit is stopped ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/jitsi-meet.yml down -ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p udp --dport $JVB_PORT -j MISTBORN_LOG_DROP -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport $JVB_TCP_PORT -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p udp --dport $JVB_PORT -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p tcp --dport $JVB_TCP_PORT -j MISTBORN_LOG_DROP # Start container when unit is started ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/jitsi-meet.yml up --build # Stop container when unit is stopped diff --git a/scripts/services/Mistborn-rocketchat.service b/scripts/services/Mistborn-rocketchat.service index 1c75a6f..1ad5a84 100644 --- a/scripts/services/Mistborn-rocketchat.service +++ b/scripts/services/Mistborn-rocketchat.service @@ -11,7 +11,7 @@ PermissionsStartOnly=true # Shutdown container (if running) when unit is stopped ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/rocketchat.yml down -ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p tcp --dport 3001 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p tcp --dport 3001 -j MISTBORN_LOG_DROP # Start container when unit is started ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/rocketchat.yml up --build # Stop container when unit is stopped diff --git a/scripts/services/Mistborn-syncthing.service b/scripts/services/Mistborn-syncthing.service index 876a6c9..e3065f3 100644 --- a/scripts/services/Mistborn-syncthing.service +++ b/scripts/services/Mistborn-syncthing.service @@ -11,8 +11,8 @@ PermissionsStartOnly=true # Shutdown container (if running) when unit is stopped ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/syncthing.yml down -ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p udp --dport 21027 -j MISTBORN_LOG_DROP -ExecStartPre=/sbin/iptables -I DOCKER-USER -i DIFACE -p tcp --dport 22000 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p udp --dport 21027 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p tcp --dport 22000 -j MISTBORN_LOG_DROP # Start container when unit is started ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/syncthing.yml up --build # Stop container when unit is stopped diff --git a/scripts/services/Mistborn-tor.service b/scripts/services/Mistborn-tor.service index 90da6b9..bbb871f 100644 --- a/scripts/services/Mistborn-tor.service +++ b/scripts/services/Mistborn-tor.service @@ -11,7 +11,7 @@ PermissionsStartOnly=true # Shutdown container (if running) when unit is stopped ExecStartPre=/usr/local/bin/docker-compose -f /opt/mistborn/extra/tor.yml down -ExecStartPre=/sbin/iptables -w 300 -I DOCKER-USER -i DIFACE -p tcp --dport 9150 -j MISTBORN_LOG_DROP +ExecStartPre=/sbin/iptables -w -I DOCKER-USER -i DIFACE -p tcp --dport 9150 -j MISTBORN_LOG_DROP # Start container when unit is started ExecStart=/usr/local/bin/docker-compose -f /opt/mistborn/extra/tor.yml up --build # Stop container when unit is stopped diff --git a/scripts/subinstallers/gen_prod_env.sh b/scripts/subinstallers/gen_prod_env.sh index 3848efc..45d93b8 100755 --- a/scripts/subinstallers/gen_prod_env.sh +++ b/scripts/subinstallers/gen_prod_env.sh @@ -19,6 +19,7 @@ echo "MISTBORN_DEFAULT_PASSWORD=$MISTBORN_DEFAULT_PASSWORD" >> $DJANGO_PROD_FILE echo "#MAILGUN_API_KEY=" >> $DJANGO_PROD_FILE echo "#MAILGUN_API_URL=" >> $DJANGO_PROD_FILE echo "#SENTRY_DNS=" >> $DJANGO_PROD_FILE +echo "MISTBORN_INSTALL_COCKPIT=$MISTBORN_INSTALL_COCKPIT" >> $DJANGO_PROD_FILE # generate production .env file for postgresql POSTGRES_PROD_FILE="./.envs/.production/.postgres" From 9ec056aa288eed6eab1c464053619efc066ba844 Mon Sep 17 00:00:00 2001 From: Steven Foerster Date: Sat, 30 May 2020 18:07:30 +0000 Subject: [PATCH 4/7] Resolve "Noninteractive installations" --- README.md | 15 ++++++++++++++- scripts/noninteractive/.install_barebones | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 scripts/noninteractive/.install_barebones diff --git a/README.md b/README.md index 88f3f9c..6c639e6 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ Within Mistborn is a panel to enable and manage these free extra services (off b # Quickstart Tested Operating Systems (in order of thoroughness): -- Ubuntu 18.04 LTS - Ubuntu 20.04 LTS +- Ubuntu 18.04 LTS - Debian 10 (Buster) - Raspbian Buster @@ -141,6 +141,19 @@ Running `install.sh` will do the following: - copy Mistborn systemd service files to `/etc/systemd/system` - start and enable Mistborn-base +# Non-Interactive Installation +In order to install without interaction some environment variables need to be pre-set. + +## Environment Variables +See the environment variables needed in `./scripts/noninteractive/.install_barebones` + +## Example Noninteractive Install +This will perform a noninteractive install with the default environment variables set in `.install_barebones`. +``` +git clone https://gitlab.com/cyber5k/mistborn.git +sudo bash -c "source ./mistborn/scripts/noninteractive/.install_barebones && ./mistborn/scripts/install.sh" +``` + # Post-Installation When Mistborn-base starts up it will create volumes, initialize the PostgreSQL database, start pihole, run Django migrations and then check to see if a Mistborn superuser named `admin` exists yet. If not, it will create the superuser `admin` along with an accompanying default Wireguard configuration file and start the Wireguard service. You can watch all of this happen with: ``` diff --git a/scripts/noninteractive/.install_barebones b/scripts/noninteractive/.install_barebones new file mode 100644 index 0000000..48deb0e --- /dev/null +++ b/scripts/noninteractive/.install_barebones @@ -0,0 +1,2 @@ +export MISTBORN_DEFAULT_PASSWORD=$(python3 -c "import secrets; import string; print(f''.join([secrets.choice(string.ascii_letters+string.digits) for x in range(20)]))") +export MISTBORN_INSTALL_COCKPIT=No From edd51d7b9d48cfff0c6d22f65340e3992b654235 Mon Sep 17 00:00:00 2001 From: Steven Foerster Date: Mon, 8 Jun 2020 21:37:03 -0400 Subject: [PATCH 5/7] resolvconf --- scripts/install.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/install.sh b/scripts/install.sh index 7d48206..07d322e 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -230,8 +230,9 @@ sudo grep -qF "$(hostname)" /etc/hosts && echo "$(hostname) already in /etc/host echo "address=/.mistborn/10.2.3.1" | sudo tee ../mistborn_volumes/base/pihole/etc-dnsmasqd/02-lan.conf # ResolvConf (OpenResolv installed with Wireguard) -sudo sed -i "s/#name_servers.*/name_servers=$IPV4_PUBLIC/" /etc/resolvconf.conf -sudo sed -i "s/name_servers.*/name_servers=$IPV4_PUBLIC/" /etc/resolvconf.conf +#sudo sed -i "s/#name_servers.*/name_servers=$IPV4_PUBLIC/" /etc/resolvconf.conf +sudo sed -i "s/#name_servers.*/name_servers=10.2.3.1/" /etc/resolvconf.conf +sudo sed -i "s/name_servers.*/name_servers=10.2.3.1/" /etc/resolvconf.conf #sudo sed -i "s/#name_servers.*/name_servers=127.0.0.1/" /etc/resolvconf.conf sudo resolvconf -u 1>/dev/null 2>&1 From fa65762c7d04d4b2a131c87b20191f4d7c1aa4dc Mon Sep 17 00:00:00 2001 From: Steven Foerster Date: Sat, 11 Jul 2020 13:15:28 +0000 Subject: [PATCH 6/7] Resolve "Debian-family Noninteractive scripts" --- scripts/install.sh | 14 ++++++++------ scripts/subinstallers/cockpit.sh | 4 ++-- scripts/subinstallers/docker.sh | 4 ++-- scripts/subinstallers/docker_manual.sh | 8 ++++---- scripts/subinstallers/iptables.sh | 2 +- scripts/subinstallers/openssl.sh | 2 +- scripts/subinstallers/wireguard.sh | 4 ++-- scripts/update.sh | 2 ++ 8 files changed, 22 insertions(+), 18 deletions(-) diff --git a/scripts/install.sh b/scripts/install.sh index 07d322e..0e7812a 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -2,6 +2,8 @@ set -e +export DEBIAN_FRONTEND=noninteractive + ## ensure run as nonroot user #if [ "$EUID" -eq 0 ]; then MISTBORN_USER="mistborn" @@ -97,7 +99,7 @@ git submodule update --init --recursive sudo apt-get update # install figlet -sudo apt-get install -y figlet +sudo -E apt-get install -y figlet # get os and distro source ./scripts/subinstallers/platform.sh @@ -114,7 +116,7 @@ fi # SSH Server -sudo apt-get install -y openssh-server +sudo -E apt-get install -y openssh-server sudo sed -i 's/#PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config sudo sed -i 's/PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config sudo sed -i 's/#PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config @@ -125,13 +127,13 @@ sudo systemctl enable ssh sudo systemctl restart ssh # Additional tools fail2ban -sudo apt-get install -y dnsutils fail2ban +sudo -E apt-get install -y dnsutils fail2ban # Install kernel headers if [ "$DISTRO" == "ubuntu" ] || [ "$DISTRO" == "debian" ]; then - sudo apt install -y linux-headers-$(uname -r) + sudo -E apt install -y linux-headers-$(uname -r) elif [ "$DISTRO" == "raspbian" ]; then - sudo apt-get install -y raspberrypi-kernel-headers + sudo -E apt install -y raspberrypi-kernel-headers fi # Wireugard @@ -143,7 +145,7 @@ sudo systemctl enable docker sudo systemctl start docker # Unattended upgrades -sudo apt-get install -y unattended-upgrades +sudo -E apt-get install -y unattended-upgrades # Cockpit if [[ "$MISTBORN_INSTALL_COCKPIT" =~ ^([yY][eE][sS]|[yY])$ ]] diff --git a/scripts/subinstallers/cockpit.sh b/scripts/subinstallers/cockpit.sh index 1a9d7f5..445ea69 100755 --- a/scripts/subinstallers/cockpit.sh +++ b/scripts/subinstallers/cockpit.sh @@ -17,11 +17,11 @@ elif [ "$DISTRO" == "raspbian" ]; then fi -sudo apt-get install -y cockpit +sudo -E apt-get install -y cockpit if $(sudo apt-cache show cockpit-docker > /dev/null 2>&1) ; then # no longer supported upstream in Ubuntu 20.04 - sudo apt-get install -y cockpit-docker + sudo -E apt-get install -y cockpit-docker fi sudo cp ./scripts/conf/cockpit.conf /etc/cockpit/cockpit.conf diff --git a/scripts/subinstallers/docker.sh b/scripts/subinstallers/docker.sh index b21d452..a051604 100755 --- a/scripts/subinstallers/docker.sh +++ b/scripts/subinstallers/docker.sh @@ -4,11 +4,11 @@ figlet "Mistborn: Installing Docker" sudo apt update -sudo apt install -y python python3-pip python3-setuptools libffi-dev python3-dev libssl-dev +sudo -E apt install -y python python3-pip python3-setuptools libffi-dev python3-dev libssl-dev if [ "$DISTRO" == "ubuntu" ] && [ "$VERSION_ID" == "20.04" ]; then echo "Automated Docker install" - sudo apt-get install -y docker-compose + sudo -E apt-get install -y docker-compose else echo "Manual Docker installation" source ./scripts/subinstallers/docker_manual.sh diff --git a/scripts/subinstallers/docker_manual.sh b/scripts/subinstallers/docker_manual.sh index 9692109..5fca1c9 100755 --- a/scripts/subinstallers/docker_manual.sh +++ b/scripts/subinstallers/docker_manual.sh @@ -2,7 +2,7 @@ # dependencies echo "Installing Docker dependencies" -sudo apt-get install -y \ +sudo -E apt-get install -y \ apt-transport-https \ ca-certificates \ curl \ @@ -42,9 +42,9 @@ echo "Installing docker" sudo apt-get update if [ "$DISTRO" == "ubuntu" ] || [ "$DISTRO" == "debian" ]; then - sudo apt-get install -y docker-ce docker-ce-cli containerd.io + sudo -E apt-get install -y docker-ce docker-ce-cli containerd.io elif [ "$DISTRO" == "raspbian" ]; then - sudo apt install -y --no-install-recommends \ + sudo -E apt install -y --no-install-recommends \ docker-ce \ cgroupfs-mount fi @@ -59,7 +59,7 @@ echo "Installing Docker Compose" # sudo chmod +x /usr/local/bin/docker-compose #elif [ "$DISTRO" == "raspbian" ]; then # Install required packages -sudo apt install -y python-backports.ssl-match-hostname +sudo -E apt install -y python-backports.ssl-match-hostname # Install Docker Compose from pip # This might take a while diff --git a/scripts/subinstallers/iptables.sh b/scripts/subinstallers/iptables.sh index 3715306..7c59891 100755 --- a/scripts/subinstallers/iptables.sh +++ b/scripts/subinstallers/iptables.sh @@ -102,7 +102,7 @@ if [ ! "$(dpkg-query -l iptables-persistent)" ]; then echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections # install - sudo apt-get install -y iptables-persistent ipset + sudo -E apt-get install -y iptables-persistent ipset else echo "Saving iptables rules" sudo bash -c "iptables-save > /etc/iptables/rules.v4" diff --git a/scripts/subinstallers/openssl.sh b/scripts/subinstallers/openssl.sh index e010fad..c5d58eb 100755 --- a/scripts/subinstallers/openssl.sh +++ b/scripts/subinstallers/openssl.sh @@ -8,7 +8,7 @@ CRT_PATH="$KEY_FOLDER/$CRT_FILE" KEY_PATH="$KEY_FOLDER/$KEY_FILE" # ensure openssl installed -sudo apt-get install -y openssl +sudo -E apt-get install -y openssl # make folder mkdir -p $KEY_FOLDER diff --git a/scripts/subinstallers/wireguard.sh b/scripts/subinstallers/wireguard.sh index 93b2490..a544591 100755 --- a/scripts/subinstallers/wireguard.sh +++ b/scripts/subinstallers/wireguard.sh @@ -11,7 +11,7 @@ if ! $(sudo apt-cache show wireguard > /dev/null 2>&1) ; then # Wireguard if [ "$DISTRO" == "raspbian" ]; then echo "Adding Wireguard repo keys" - sudo apt-get install -y dirmngr + sudo -E apt-get install -y dirmngr sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8B48AD6246925553 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7638D0442B90D010 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 04EE7237B7D453EC @@ -29,4 +29,4 @@ fi echo "Installing Wireguard" sudo apt-get update -sudo apt-get install -y openresolv wireguard +sudo -E apt-get install -y openresolv wireguard diff --git a/scripts/update.sh b/scripts/update.sh index 049fbec..e901489 100755 --- a/scripts/update.sh +++ b/scripts/update.sh @@ -2,6 +2,8 @@ set -e +export DEBIAN_FRONTEND=noninteractive + sudo git -C /opt/mistborn pull sudo git -C /opt/mistborn submodule update --init --recursive From 09cfda0e37a6f89ee0fb84a2ae59587e7efd51bf Mon Sep 17 00:00:00 2001 From: Steven Foerster Date: Tue, 28 Jul 2020 18:53:09 +0000 Subject: [PATCH 7/7] Resolve "Multifactor Authentication" --- README.md | 35 +++++++++- .../production/traefik/traefik.toml.template | 66 +++++++++++++++++++ scripts/env/setup.sh | 8 +-- scripts/install.sh | 1 + scripts/subinstallers/gen_prod_env.sh | 2 + scripts/subinstallers/iptables.sh | 3 +- scripts/update.sh | 4 ++ 7 files changed, 113 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6c639e6..e210492 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Mistborn -A secure platform for easily standing up and managing your own cloud services: including firewall, ad-blocking, and Wireguard VPN access +A secure platform for easily standing up and managing your own cloud services: including firewall, ad-blocking, and multi-factor Wireguard VPN access # Table of Contents [[_TOC_]] @@ -13,6 +13,7 @@ Ideal for teams who: - hate internet ads - need to be protected from malicious internet domains - need to collaborate securely +- need multi-factor authentication for Wireguard - want to retain sole ownership of their data - want to easily grant and revoke access to people and devices via a simple web interface - want secure internet access wherever they are @@ -214,6 +215,30 @@ Mistborn makes extra services available. Mistborn functions as a network firewall and provides metrics on blocked probes from the internet. ![Mistborn Metrics](https://gitlab.com/cyber5k/public/-/raw/master/graphics/home.mistborn_metrics.png)*Mistborn Firewall Metrics* +# Authentication +There are multiple ways to authenticate and use the system. + +![Mistborn Multi Factor Authentication - Authenticator App Setup](https://gitlab.com/cyber5k/public/-/raw/master/graphics/mfa_qr.png)*Mistborn Multi Factor Authentication - Authenticator App Setup* + +## Profile: Wireguard Authentication +Mistborn always authenticates with Wireguard. You must have a valid Wireguard configuration file associated with the correct internal IP address. A classic Mistborn profile (Wireguard Only) will allow you to access the internet and all services hosted by Mistborn once you have connected via Wireguard. Note: individual services may require passwords or additional authentication. + +## Profile: Multi Factor Authentication (MFA) +In addition to Wireguard, you may create a Mistborn profile enabling multi-factor authentication (MFA). You must first connect to Mistborn via Wireguard. Then all internet traffic will route you to the Mistborn webserver where you must first setup and thereafter authenticate with an app (Google Authenticator, Authy, etc.). You must go to [http://home.mistborn](http://home.mistborn) to complete the authentication process. + +![Mistborn Multi Factor Authentication](https://gitlab.com/cyber5k/public/-/raw/master/graphics/mfa1.png)*Mistborn Multi Factor Authentication Prompt* + +### MFA Internet Access +Internet access is blocked via iptables until authentication is completed for an MFA profile. You must go to [http://home.mistborn](http://home.mistborn) to complete the authentication process. Click "Sign Out" to re-block internet access until authentication completes again. + +![Mistborn Multi Factor Authentication - Token Prompt](https://gitlab.com/cyber5k/public/-/raw/master/graphics/mfa_token_enter.png)*Mistborn Multi Factor Authentication - Token Prompt* + +### MFA Mistborn Service Access +Mistborn service access is blocked via traefik until Mistborn authentication is complete. You will not be able to access the web pages for pihole, cockpit, or any extra services until authentication is complete for an MFA profile. Attempting to visit one of these pages will redirect you to [http://home.mistborn](http://home.mistborn) where you must complete the authentication process. Click "Sign Out" to re-block access until authentication completes again. + +### Notes +- **Sessions**: Traefik checks the authenticated sessions on the server side to determine whether to allow access to the Mistborn service web pages. If an open session exists for your Mistborn IP address then access will be granted. You may close all sessions by clicking "Sign Out" on the Mistborn home page. Expired sessions are regularly cleaned by the Mistborn system (celery periodic task). + # Mistborn Subdomains Mistborn uses the following domains (that can be reached by all Wireguard clients): @@ -389,6 +414,14 @@ DNS = 10.2.3.1 ``` Close the config and restart the client Wireguard process. +## Troubleshooting Raspberry Pi OS (Raspbian) +Be sure to always reboot after updating the kernel. When the kernel is updated the kernel modules are deleted (for the currently running kernel) and you will have issues with any function requiring kernel modules (e.g. `iptables` or `wireguard`). + +**Note**: The Raspberry Pi OS 64-bit BETA (versions from May 2020 and prior) have a bug where the os-release info indicates that it is Debian. Mistborn proceeds to install as though it were Debian. Since it's not Debian there are errors. + +## Troubleshooting Debian 10 +Run updates and restart before installing Mistborn (`sudo apt-get update && sudo apt-get -y dist-upgrade && sudo shutdown -r now`). Some older Linux kernels will prevent newer Wireguard versions from installing. + # Technical and Security Insights These are some notes regarding the technical design and implementations of Mistborn. Feel free to contact me for additional details. diff --git a/compose/production/traefik/traefik.toml.template b/compose/production/traefik/traefik.toml.template index 19164ad..267d53b 100644 --- a/compose/production/traefik/traefik.toml.template +++ b/compose/production/traefik/traefik.toml.template @@ -96,6 +96,12 @@ defaultEntryPoints = ["http", "https"] [frontends.pihole] backend = "pihole" passHostHeader = true + [frontends.pihole.auth] + [frontends.pihole.auth.forward] + address = "https://home.mistborn/auth/" + trustForwardHeader = false + [frontends.pihole.auth.forward.tls] + insecureSkipVerify = true [frontends.pihole.headers] HostsProxyHeaders = ['X-CSRFToken'] [frontends.pihole.routes.dr1] @@ -104,6 +110,12 @@ defaultEntryPoints = ["http", "https"] [frontends.homeassistant] backend = "homeassistant" passHostHeader = true + [frontends.homeassistant.auth] + [frontends.homeassistant.auth.forward] + address = "https://home.mistborn/auth/" + trustForwardHeader = false + [frontends.homeassistant.auth.forward.tls] + insecureSkipVerify = true [frontends.homeassistant.headers] HostsProxyHeaders = ['X-CSRFToken'] [frontends.homeassistant.routes.dr1] @@ -112,6 +124,12 @@ defaultEntryPoints = ["http", "https"] [frontends.syncthing] backend = "syncthing" passHostHeader = true + [frontends.syncthing.auth] + [frontends.syncthing.auth.forward] + address = "https://home.mistborn/auth/" + trustForwardHeader = false + [frontends.syncthing.auth.forward.tls] + insecureSkipVerify = true [frontends.syncthing.headers] HostsProxyHeaders = ['X-CSRFToken'] [frontends.syncthing.routes.dr1] @@ -120,6 +138,12 @@ defaultEntryPoints = ["http", "https"] [frontends.rocketchat] backend = "rocketchat" passHostHeader = true + [frontends.rocketchat.auth] + [frontends.rocketchat.auth.forward] + address = "https://home.mistborn/auth/" + trustForwardHeader = false + [frontends.rocketchat.auth.forward.tls] + insecureSkipVerify = true [frontends.rocketchat.headers] HostsProxyHeaders = ['X-CSRFToken'] [frontends.rocketchat.routes.dr1] @@ -128,6 +152,12 @@ defaultEntryPoints = ["http", "https"] [frontends.nextcloud] backend = "nextcloud" passHostHeader = true + [frontends.nextcloud.auth] + [frontends.nextcloud.auth.forward] + address = "https://home.mistborn/auth/" + trustForwardHeader = false + [frontends.nextcloud.auth.forward.tls] + insecureSkipVerify = true [frontends.nextcloud.headers] HostsProxyHeaders = ['X-CSRFToken'] [frontends.nextcloud.routes.dr1] @@ -136,6 +166,12 @@ defaultEntryPoints = ["http", "https"] [frontends.onlyoffice] backend = "onlyoffice" passHostHeader = true + [frontends.onlyoffice.auth] + [frontends.onlyoffice.auth.forward] + address = "https://home.mistborn/auth/" + trustForwardHeader = false + [frontends.onlyoffice.auth.forward.tls] + insecureSkipVerify = true [frontends.onlyoffice.headers] HostsProxyHeaders = ['X-CSRFToken'] [frontends.onlyoffice.routes.dr1] @@ -144,6 +180,12 @@ defaultEntryPoints = ["http", "https"] [frontends.bitwarden] backend = "bitwarden" passHostHeader = true + [frontends.bitwarden.auth] + [frontends.bitwarden.auth.forward] + address = "https://home.mistborn/auth/" + trustForwardHeader = false + [frontends.bitwarden.auth.forward.tls] + insecureSkipVerify = true [frontends.bitwarden.headers] HostsProxyHeaders = ['X-CSRFToken'] [frontends.bitwarden.routes.dr1] @@ -152,6 +194,12 @@ defaultEntryPoints = ["http", "https"] [frontends.jellyfin] backend = "jellyfin" passHostHeader = true + [frontends.jellyfin.auth] + [frontends.jellyfin.auth.forward] + address = "https://home.mistborn/auth/" + trustForwardHeader = false + [frontends.jellyfin.auth.forward.tls] + insecureSkipVerify = true [frontends.jellyfin.headers] HostsProxyHeaders = ['X-CSRFToken'] [frontends.jellyfin.routes.dr1] @@ -160,6 +208,12 @@ defaultEntryPoints = ["http", "https"] [frontends.jitsi] backend = "jitsi" passHostHeader = true + [frontends.jitsi.auth] + [frontends.jitsi.auth.forward] + address = "https://home.mistborn/auth/" + trustForwardHeader = false + [frontends.jitsi.auth.forward.tls] + insecureSkipVerify = true [frontends.jitsi.headers] HostsProxyHeaders = ['X-CSRFToken'] [frontends.jitsi.routes.dr1] @@ -168,6 +222,12 @@ defaultEntryPoints = ["http", "https"] [frontends.raspap] backend = "raspap" passHostHeader = true + [frontends.raspap.auth] + [frontends.raspap.auth.forward] + address = "https://home.mistborn/auth/" + trustForwardHeader = false + [frontends.raspap.auth.forward.tls] + insecureSkipVerify = true [frontends.raspap.headers] HostsProxyHeaders = ['X-CSRFToken'] [frontends.raspap.routes.dr1] @@ -176,6 +236,12 @@ defaultEntryPoints = ["http", "https"] [frontends.cockpit] backend = "cockpit" passHostHeader = true + [frontends.cockpit.auth] + [frontends.cockpit.auth.forward] + address = "https://home.mistborn/auth/" + trustForwardHeader = false + [frontends.cockpit.auth.forward.tls] + insecureSkipVerify = true [frontends.cockpit.headers] HostsProxyHeaders = ['X-CSRFToken'] [frontends.cockpit.routes.dr1] diff --git a/scripts/env/setup.sh b/scripts/env/setup.sh index 6b03c5a..8234cd1 100755 --- a/scripts/env/setup.sh +++ b/scripts/env/setup.sh @@ -4,10 +4,10 @@ VAR_FILE=/opt/mistborn/.env source /opt/mistborn/scripts/subinstallers/platform.sh -MISTBORN_DNS_BIND_IP="0.0.0.0" -if [ "$DISTRO" == "ubuntu" ] && [ "$VERSION_ID" == "20.04" ]; then - MISTBORN_DNS_BIND_IP="10.2.3.1" -fi +MISTBORN_DNS_BIND_IP="10.2.3.1" +#if [ "$DISTRO" == "ubuntu" ] && [ "$VERSION_ID" == "20.04" ]; then +# MISTBORN_DNS_BIND_IP="10.2.3.1" +#fi echo "MISTBORN_DNS_BIND_IP=${MISTBORN_DNS_BIND_IP}" | sudo tee ${VAR_FILE} sudo chown mistborn:mistborn ${VAR_FILE} diff --git a/scripts/install.sh b/scripts/install.sh index 0e7812a..d71a6d4 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -206,6 +206,7 @@ sudo mkdir -p ../mistborn_volumes/extra # Traefik final setup (cockpit) cp ./compose/production/traefik/traefik.toml.template ./compose/production/traefik/traefik.toml + # setup tls certs source ./scripts/subinstallers/openssl.sh sudo rm -rf ../mistborn_volumes/base/tls diff --git a/scripts/subinstallers/gen_prod_env.sh b/scripts/subinstallers/gen_prod_env.sh index 45d93b8..ace958e 100755 --- a/scripts/subinstallers/gen_prod_env.sh +++ b/scripts/subinstallers/gen_prod_env.sh @@ -20,6 +20,8 @@ echo "#MAILGUN_API_KEY=" >> $DJANGO_PROD_FILE echo "#MAILGUN_API_URL=" >> $DJANGO_PROD_FILE echo "#SENTRY_DNS=" >> $DJANGO_PROD_FILE echo "MISTBORN_INSTALL_COCKPIT=$MISTBORN_INSTALL_COCKPIT" >> $DJANGO_PROD_FILE +echo "MISTBORN_PORTAL_IP=10.2.3.1" >> $DJANGO_PROD_FILE +echo "MISTBORN_PORTAL_PORT=5000" >> $DJANGO_PROD_FILE # generate production .env file for postgresql POSTGRES_PROD_FILE="./.envs/.production/.postgres" diff --git a/scripts/subinstallers/iptables.sh b/scripts/subinstallers/iptables.sh index 7c59891..a687eb1 100755 --- a/scripts/subinstallers/iptables.sh +++ b/scripts/subinstallers/iptables.sh @@ -46,7 +46,8 @@ sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # if installing over SSH, add SSH rule if [ ! -z "${SSH_CLIENT}" ]; then SSH_SRC=$(echo $SSH_CLIENT | awk '{print $1}') - sudo iptables -A INPUT -p tcp -s $SSH_SRC --dport 22 -j ACCEPT + SSH_PRT=$(echo $SSH_CLIENT | awk '{print $3}') + sudo iptables -A INPUT -p tcp -s $SSH_SRC --dport $SSH_PRT -j ACCEPT fi # docker rules diff --git a/scripts/update.sh b/scripts/update.sh index e901489..40e1c74 100755 --- a/scripts/update.sh +++ b/scripts/update.sh @@ -10,11 +10,15 @@ sudo git -C /opt/mistborn submodule update --init --recursive # ensure mistborn-cli is installed sudo pip3 install -e /opt/mistborn/modules/mistborn-cli +# handle updates to Mistborn systemd scripts iface=$(ip -o -4 route show to default | egrep -o 'dev [^ ]*' | awk 'NR==1{print $2}') sudo cp /opt/mistborn/scripts/services/Mistborn* /etc/systemd/system/ sudo find /etc/systemd/system/ -type f -name 'Mistborn*' | xargs sudo sed -i "s/User=root/User=mistborn/" sudo find /etc/systemd/system/ -type f -name 'Mistborn*' | xargs sudo sed -i "s/DIFACE/$iface/" +# handle updates to traefik +sudo cp /opt/mistborn/compose/production/traefik/traefik.toml.template /opt/mistborn/compose/production/traefik/traefik.toml + sudo systemctl daemon-reload sudo systemctl enable Mistborn-setup.service sudo systemctl restart Mistborn-setup.service