diff --git a/static/configuration.nix b/static/configuration.nix new file mode 100644 index 0000000..d15c13f --- /dev/null +++ b/static/configuration.nix @@ -0,0 +1,26 @@ +{ pkgs, ... }: { + imports = [ + ./hardware-configuration.nix + ./mailserver.nix + ./goss.nix + + ]; + + boot.cleanTmpDir = true; + networking.hostName = "nixos-mailserver"; + networking.firewall.allowPing = true; + networking.firewall.allowedTCPPorts = [ 22 443 80 143 993 587 25 465 ]; + networking.firewall.allowedUDPPorts = [ 443 80 143 993 587 25 465 ]; + services.openssh.enable = true; + users.users.root.openssh.authorizedKeys.keys = [ + + ]; + environment.systemPackages = with pkgs; [ + htop + vim + letsencrypt + opendkim + ]; + system.autoUpgrade.enable = true; + system.autoUpgrade.allowReboot = false; +} diff --git a/static/goss.nix b/static/goss.nix new file mode 100644 index 0000000..1bbfe5e --- /dev/null +++ b/static/goss.nix @@ -0,0 +1,15 @@ +{ pkgs ? import {} }: +pkgs.stdenv.mkDerivation { + name = "goss"; + src = pkgs.fetchurl { + url = "https://github.com/aelsabbahy/goss/releases/download/v0.3.13/goss-linux-amd64"; + sha256 = "1q0kfdbifffszikcl0warzmqvsbx4bg19l9a3vv6yww2jvzj4dgb"; + }; + phases = ["installPhase" "patchPhase"]; + installPhase = '' + mkdir -p $out/bin + cp $src $out/bin/goss + chmod +x $out/bin/goss + cp $out/bin/goss . + ''; +} diff --git a/static/mailserver.nix b/static/mailserver.nix new file mode 100644 index 0000000..b1efa40 --- /dev/null +++ b/static/mailserver.nix @@ -0,0 +1,65 @@ +{ config, pkgs, ... }: +{ + imports = [ + (builtins.fetchTarball { + # Pick a commit from the branch you are interested in + url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/4008d0cb/nixos-mailserver-4008d0cb.tar.gz"; + # And set its hash + sha256 = "1y9svi3nrg24ky1gqbpa3zhnhhin399h0cmnf81hb4yn75mlqiqx"; + }) + ]; + + + mailserver = { + enable = true; + fqdn = "example.com"; + domains = [ "example.com" ]; + + # A list of all login accounts. To create the password hashes, use + # mkpasswd -m sha-512 "super secret password" + loginAccounts = { + "test@example.com" = { + hashedPassword = "$6$ABz9oq7Ha3ddtTeD$qnBACjNEXrwkXdx8UM6sJEM6qeGZSvjNd0KaZEsq.fAHh31Jrxls1OWBgSxSjM200zTqB91v7qlR.hwMESICw1"; + + #aliases = [ + # "mail@example.com" + #]; + + # Make this user the catchAll address for domains blah.com and + # example2.com + catchAll = [ + "example.com" + ]; + }; + + }; + + # Extra virtual aliases. These are email addresses that are forwarded to + # loginAccounts addresses. + extraVirtualAliases = { + # address = forward address; + "admin@example.com" = "test@example.com"; + }; + + # Use Let's Encrypt certificates. Note that this needs to set up a stripped + # down nginx and opens port 80. + certificateScheme = 3; + + # Enable IMAP and POP3 + enableImap = false; + enablePop3 = false; + enableImapSsl = true; + enablePop3Ssl = false; + dkimSelector = "selector"; + + # Enable the ManageSieve protocol + enableManageSieve = false; + + virusScanning = false; + }; + security.acme = { + acceptTerms = true; + # Replace the email here! + email = "test@example.com"; +}; +} diff --git a/static/server.sh b/static/server.sh index e530048..295ba93 100755 --- a/static/server.sh +++ b/static/server.sh @@ -5,24 +5,24 @@ InstallDependencies() { packagesNeeded='curl jq' - if [ -x "$(command -v apk)" ]; then sudo apk add --no-cache $packagesNeeded - elif [ -x "$(command -v apt-get)" ]; then sudo apt-get install $packagesNeeded - elif [ -x "$(command -v dnf)" ]; then sudo dnf install $packagesNeeded - elif [ -x "$(command -v zypper)" ]; then sudo zypper install $packagesNeeded - elif [ -x "$(command -v pacman)" ]; then sudo pacman -S $packagesNeeded - elif [ -x "$(command -v emerge)" ]; then sudo emerge --ask $packagesNeeded + if [ -x "$(command -v apk)" ]; then sudo apk add --no-cache $packagesNeeded # Alpine Linux + elif [ -x "$(command -v apt-get)" ]; then sudo apt-get install $packagesNeeded # Debian/Ubuntu Linux + elif [ -x "$(command -v dnf)" ]; then sudo dnf install $packagesNeeded # Fedora Linux + elif [ -x "$(command -v rpm-ostree)" ]; then sudo rpm-ostree install $packagesNeeded # Fedora Linux Silverblue + elif [ -x "$(command -v zypper)" ]; then sudo zypper install $packagesNeeded # openSUSE Linux + elif [ -x "$(command -v pacman)" ]; then sudo pacman -S $packagesNeeded # Arch/Manjaro Linux + elif [ -x "$(command -v emerge)" ]; then sudo emerge --ask $packagesNeeded # Gentoo Linux + elif [ -x "$(command -v nix-env)" ]; then nix-env -iA $packagesNeeded # NixOS else echo "FAILED TO INSTALL PACKAGE: Package manager not found. You must manually install: $packagesNeeded">&2; fi - wget http://192.168.0.104/configuration.nix - wget http://192.168.0.104/mailserver.nix + wget https://selfprivacy.org/configuration.nix + wget https://selfprivacy.org/mailserver.nix } CollectData() { read -p "Please, paste your Hetzner API token here: " HETZNER_TOKEN echo $HETZNER_TOKEN - read -p "Please paste your CloudFlare global API key here: " CLOUDFLARE_TOKEN + read -p "Please paste your CloudFlare Token: " CLOUDFLARE_TOKEN echo $CLOUDFLARE_TOKEN - read -p "Please enter your CloudFlare e-mail here: " CLOUDFLARE_EMAIL - echo $CLOUDFLARE_EMAIL read -p "Please define your domain there: " DOMAIN echo $DOMAIN read -p "Please define your mail username: " USERNAME @@ -61,7 +61,7 @@ MakeConfig() sed -i '31s/.*/\t\t"'"$DOMAIN"'"/' mailserver.nix sed -i '41s/.*/\t "admin@'"$DOMAIN"'" = "'"$USERNAME"'@'"$DOMAIN"'";/' mailserver.nix sed -i '63s/.*/ email = "'"$USERNAME"'@'"$DOMAIN"'";/' mailserver.nix - sed -i "15s,.*,\t\"${sshKey}\"," configuration.nix + sed -i "16s,.*,\t\"${sshKey}\"," configuration.nix } MakeServer() @@ -89,6 +89,7 @@ ApplyConfig() ssh -i ~/.nix-ms/id_rsa "root@$machineip" echo "Authentificated" scp -i ~/.nix-ms/id_rsa mailserver.nix "root@$machineip:/root" scp -i ~/.nix-ms/id_rsa configuration.nix "root@$machineip:/root" + scp -i ~/.nix-ms/id_rsa goss.yaml "root@$machineip:/root" ssh -i ~/.nix-ms/id_rsa "root@$machineip" cp /root/mailserver.nix /etc/nixos/mailserver.nix ssh -i ~/.nix-ms/id_rsa "root@$machineip" cp /root/configuration.nix /etc/nixos/configuration.nix sleep 3 @@ -119,8 +120,7 @@ ClearTempFiles() GetZoneID() { curl -s -X GET "https://api.cloudflare.com/client/v4/zones" \ - -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \ - -H "X-Auth-Key: $CLOUDFLARE_TOKEN" \ + -H "Authorization: Bearer $CLOUDFLARE_TOKEN" \ -H "Content-Type: application/json" > .cloudflare.json export zoneid=$( for i in {0..24}; do jq 'if .result['$i'].name == "'$DOMAIN'" then .result['$i'].id else null end' .cloudflare.json; done | grep -v null | sed -e 's/^"//' -e 's/"$//' ) } @@ -128,8 +128,7 @@ GetZoneID() CreateARecord() { curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records" \ - -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \ - -H "X-Auth-Key: $CLOUDFLARE_TOKEN" \ + -H "Authorization: Bearer $CLOUDFLARE_TOKEN" \ -H "Content-Type: application/json" \ --data '{"type":"A","name":"'$DOMAIN'","content":"'$machineip'","ttl":3600,"priority":10,"proxied":false}' > /dev/null } @@ -137,8 +136,7 @@ CreateARecord() CreateMXRecord() { curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records" \ - -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \ - -H "X-Auth-Key: $CLOUDFLARE_TOKEN" \ + -H "Authorization: Bearer $CLOUDFLARE_TOKEN" \ -H "Content-Type: application/json" \ --data '{"type":"MX","name":"@","content":"'$DOMAIN'","ttl":3600,"priority":10,"proxied":false}' > /dev/null } @@ -146,8 +144,7 @@ CreateMXRecord() CreateDMARCRecord() { curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records" \ - -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \ - -H "X-Auth-Key: $CLOUDFLARE_TOKEN" \ + -H "Authorization: Bearer $CLOUDFLARE_TOKEN" \ -H "Content-Type: application/json" \ --data '{"type":"TXT","name":"_dmarc","content":"v=DMARC1; p=none","ttl":18000,"priority":10,"proxied":false}' > /dev/null } @@ -155,8 +152,7 @@ CreateDMARCRecord() CreateSPFRecord() { curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records" \ - -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \ - -H "X-Auth-Key: $CLOUDFLARE_TOKEN" \ + -H "Authorization: Bearer $CLOUDFLARE_TOKEN" \ -H "Content-Type: application/json" \ --data '{"type":"TXT","name":"'$DOMAIN'","content":"v=spf1 a mx ip4:'$machineip' -all","ttl":18000,"priority":10,"proxied":false}' > /dev/null } @@ -164,11 +160,27 @@ CreateSPFRecord() CreateDKIMRecord() { export dkim=$( echo $dkim | sed -e 's/^"//' -e 's/"$//' ) - curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records" -H "X-Auth-Email: $CLOUDFLARE_EMAIL" -H "X-Auth-Key: $CLOUDFLARE_TOKEN" -H "Content-Type: application/json" --data '{"type":"TXT","name":"selector._domainkey","content":"v=DKIM1; '$dkim'","ttl":18000,"priority":10,"proxied":false}' > /dev/null + curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records" -H "Authorization: Bearer $CLOUDFLARE_TOKEN" -H "Content-Type: application/json" --data '{"type":"TXT","name":"selector._domainkey","content":"v=DKIM1; '$dkim'","ttl":18000,"priority":10,"proxied":false}' > /dev/null } -CollectData +PostInstallation() +{ + ssh -i ~/.nix-ms/id_rsa "root@$machineip" cp /root/result/bin/goss /root/ + ssh -i ~/.nix-ms/id_rsa "root@$machineip" /root/goss serve --format json & +} + +PerformTests() +{ + curl $machineip:8080/healthz > .healthz.json + for i in {0..24}; do jq 'if .results['$i'].err != null then "FAIL" else "OK" end' .healthz.json; + done +} + +if test -z "$HETZNER_TOKEN" || test -z "$CLOUDFLARE_TOKEN" || test -z "$PASSWORD" +then + CollectData +fi InstallDependencies GenerateSSHKey printf "Importing SSH key into your Hetzner account..." @@ -181,7 +193,7 @@ printf "Waiting for the server to create...\n" MakeServer sleep 30 printf "Waiting for nixos-infect to replace system files(this may take some time)...\n" -sleep 180 +sleep 200 GetMachineIP ApplyConfig GetDKIM @@ -194,7 +206,13 @@ CreateMXRecord CreateDMARCRecord CreateSPFRecord CreateDKIMRecord -echo "done" +printf "done\n" +PostInstallation +PerformTests +#while ! ping -c1 192.168.0.107 &>/dev/null +# do echo "Ping Fail - `date`" +#done +#echo "Host Found - `date`" printf "Clearing temporary files..." ClearTempFiles printf "done\n"