diff --git a/LICENSE b/LICENSE index 2071b23..260902c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) +Copyright (c) 2021 stubbfel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index 3049c9a..176f4db 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,24 @@ -# mailcow +# MailCow +## Example + +### shell + +```sh +nix-shell mailcow_nix-shell.nix --run configureMailCow +nix-shell mailcow_nix-shell.nix --run runMailCow +nix-shell mailcow_nix-shell.nix --run updateMailCow +``` + +### build + +```sh +nix-build mailcow_nix-build.nix +result/bin/configureMailCow +result/bin/runMailCow +result/bin/updateMailCow +``` + +### nixos + +see `examples/mailcow_nixos.nix` \ No newline at end of file diff --git a/examples/mailcow_nix-build.nix b/examples/mailcow_nix-build.nix new file mode 100644 index 0000000..fc1700b --- /dev/null +++ b/examples/mailcow_nix-build.nix @@ -0,0 +1,20 @@ +{ pkgs ? import {}}: +let + +mc = pkgs.callPackage ../mailcow.nix {}; + +in + +pkgs.stdenv.mkDerivation rec { + name = "mailcow"; + phases = "installPhase"; + installPhase = '' + mkdir -p $out/bin + cp ${mc.runMailCow.command}/bin/runMailCow $out/bin/runMailCow + cp ${mc.configureMailCow.command}/bin/configureMailCow $out/bin/configureMailCow + cp ${mc.updateMailCow.command}/bin/updateMailCow $out/bin/updateMailCow + ''; +} + + + diff --git a/examples/mailcow_nix-shell.nix b/examples/mailcow_nix-shell.nix new file mode 100644 index 0000000..4c60f15 --- /dev/null +++ b/examples/mailcow_nix-shell.nix @@ -0,0 +1,17 @@ +{ pkgs ? import {}}: +let + +mc = pkgs.callPackage ../mailcow.nix {}; + +in + +pkgs.mkShell { + name = "mailcow-shell"; + buildInputs = mc.runMailCow.paths ++ mc.configureMailCow.paths ++ [ + mc.runMailCow.command + mc.configureMailCow.command + mc.updateMailCow.command + pkgs.nano + ]; +} + diff --git a/examples/mailcow_nixos.nix b/examples/mailcow_nixos.nix new file mode 100644 index 0000000..207b9bf --- /dev/null +++ b/examples/mailcow_nixos.nix @@ -0,0 +1,43 @@ +{ config, pkgs, ...}: + +let + mc = pkgs.callPackage ../mailcow.nix { + ptr = "mail.devel-nixos.org"; + httpPort = "7780"; + httpBind = "127.0.0.1"; + httpsPort = "7443"; + httpsBind = "127.0.0.1"; + skipMailCowAcme = true; + }; +in +{ + + networking.firewall.allowedTCPPorts = [80 443]; + + services.nginx = { + enable = true; + appendHttpConfig = '' + server_names_hash_bucket_size 64; + ''; + sslProtocols = "TLSv1 TLSv1.1 TLSv1.2"; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = false; + virtualHosts."mailcow.*" = mc.nginx.virtualHosts.mailCow; + }; + + systemd = { + services = { + mailcow = mc.systemd.services.mailcow; + mailcow-update = mc.systemd.services.mailcow-update; + }; + timers.mailcow-update = mc.systemd.timers.mailcow-update; + }; + + security.acme = { + acceptTerms = true; + email = "acme@devel-nixos.org"; + certs."${mc.acme.certName}".postRun = mc.acme.postRun; + }; +} diff --git a/examples/result b/examples/result new file mode 120000 index 0000000..fe46d3b --- /dev/null +++ b/examples/result @@ -0,0 +1 @@ +/nix/store/m6f559ba42nih6knkl99dqy464v75c0i-mailcow \ No newline at end of file diff --git a/mailcow.nix b/mailcow.nix new file mode 100644 index 0000000..3897cfc --- /dev/null +++ b/mailcow.nix @@ -0,0 +1,143 @@ +# nix-build --expr 'with import {}; callPackage ./mailcow.nix {}' +{ + pkgs ? import {}, + stateDir ? "/opt/mailcow-dockerized", + ptr ? "mail.example.org", + timeZone ? "Europe/Berlin", + httpPort ? "80", + httpBind ? "0.0.0.0", + httpsPort ? "443", + httpsBind ? "0.0.0.0", + skipMailCowAcme ? false, + nginxEnableACME ? true, + nginxForceSSL ? true, + nginxIsDefault ? true, + gitUrl ? "https://github.com/mailcow/mailcow-dockerized.git", + gitRef ? "master" +}: +let + +configureMailCowPaths = [ + pkgs.gnused +]; + +runMailCowPaths = configureMailCowPaths ++ [ + pkgs.bash + pkgs.git + pkgs.curl + pkgs.gawk + pkgs.docker + pkgs.docker-compose + pkgs.which + pkgs.coreutils-full + pkgs.unixtools.ping + pkgs.iptables + pkgs.openssl +]; + +configureMailCow = pkgs.writeShellScriptBin "configureMailCow" '' + ${pkgs.gnused}/bin/sed -i 's/HTTP_PORT=.*/HTTP_PORT=${httpPort}/' ${stateDir}/mailcow.conf + ${pkgs.gnused}/bin/sed -i 's/HTTP_BIND=.*/HTTP_BIND=${httpBind}/' ${stateDir}/mailcow.conf + ${pkgs.gnused}/bin/sed -i 's/HTTPS_PORT=.*/HTTPS_PORT=${httpsPort}/' ${stateDir}/mailcow.conf + ${pkgs.gnused}/bin/sed -i 's/HTTPS_BIND=.*/HTTPS_BIND=${httpsBind}/' ${stateDir}/mailcow.conf + ${pkgs.gnused}/bin/sed -i 's/SKIP_LETS_ENCRYPT=.*/SKIP_LETS_ENCRYPT=${ if skipMailCowAcme then "y" else "n"}/' ${stateDir}/mailcow.conf +''; + +updateMailCow = pkgs.writeShellScriptBin "updateMailCow" '' + cd ${stateDir} + ./update.sh --no-update-compose --force +''; + +runMailCow = pkgs.writeShellScriptBin "runMailCow" '' + if [ -d "${stateDir}" ] + then + cd ${stateDir} + ${configureMailCow}/bin/configureMailCow + ${pkgs.docker-compose}/bin/docker-compose up + else + git clone ${gitUrl} "${stateDir}" + cd "${stateDir}" + git checkout ${gitRef} + git reset --hard + export MAILCOW_HOSTNAME="${ptr}" + export MAILCOW_TZ="Europe/Berlin" + ./generate_config.sh + ${configureMailCow}/bin/configureMailCow + ./update.sh --no-update-compose --force + fi +''; + +in +{ + runMailCow = { + command = runMailCow; + paths = runMailCowPaths; + }; + + configureMailCow = { + command = configureMailCow; + paths = configureMailCowPaths; + }; + + updateMailCow = { + command = updateMailCow; + paths = runMailCowPaths; + }; + + systemd = { + services = { + mailcow = { + path = runMailCowPaths; + serviceConfig.Type = "oneshot"; + wantedBy = ["multi-user.target"]; + after = [ "docker-service"]; + script = '' + ${runMailCow}/bin/runMailCow + ''; + }; + mailcow-update = { + path = runMailCowPaths; + serviceConfig.Type = "oneshot"; + script = '' + ${updateMailCow}/bin/updateMailCow + ''; + }; + }; + timers = { + mailcow-update = { + wantedBy = [ "timers.target" ]; + partOf = [ "mailcow-update.service" ]; + timerConfig.OnCalendar = "weekly"; + }; + }; + }; + + nginx = { + virtualHosts = { + mailCow = { + enableACME = nginxEnableACME; + forceSSL = nginxForceSSL; + default = nginxIsDefault; + locations."/".proxyPass = "http://localhost:${httpPort}"; + serverName = "${ptr}"; + }; + }; + }; + + acme = { + certName = "${ptr}"; + postRun ='' + cp fullchain.pem ${stateDir}/data/assets/ssl/cert.pem + cp key.pem ${stateDir}/data/assets/ssl/key.pem + cp chain.pem ${stateDir}/data/assets/ssl/chain.pem + ''; + }; + + meta = { + description = "The mailserver suite with the 'moo' "; + homepage = https://mailcow.email; + maintainers = "stubbfel"; + license = pkgs.lib.licenses.gpl3; + platforms = pkgs.lib.platforms.unix; + }; +} \ No newline at end of file