Self-host your own digital island

Compare changes

Choose any two refs to compare.

+41 -59
flake.lock
···
"nixpkgs": [
"nixpkgs"
],
-
"opam-nix": "opam-nix",
-
"opam-repository": "opam-repository"
},
"locked": {
-
"lastModified": 1718122335,
-
"narHash": "sha256-ooeplCUj5dY2KT840ecFtR+iDq1V2iB5rDsFqjbdFSs=",
"owner": "RyanGibb",
"repo": "eon",
-
"rev": "87b7ec1cd6cb7dc0f950d8d37a91845465780faf",
"type": "github"
},
"original": {
···
"flake-compat": {
"flake": false,
"locked": {
-
"lastModified": 1627913399,
-
"narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=",
"owner": "edolstra",
"repo": "flake-compat",
-
"rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2",
"type": "github"
},
"original": {
···
"systems": "systems"
},
"locked": {
-
"lastModified": 1710146030,
-
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
-
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
···
"mirage-opam-overlays": {
"flake": false,
"locked": {
-
"lastModified": 1661959605,
-
"narHash": "sha256-CPTuhYML3F4J58flfp3ZbMNhkRkVFKmBEYBZY5tnQwA=",
"owner": "dune-universe",
"repo": "mirage-opam-overlays",
-
"rev": "05f1c1823d891ce4d8adab91f5db3ac51d86dc0b",
"type": "github"
},
"original": {
···
"inputs": {
"blobs": "blobs",
"flake-compat": "flake-compat_2",
-
"nixpkgs": "nixpkgs",
"nixpkgs-24_05": "nixpkgs-24_05",
"utils": "utils"
},
"locked": {
-
"lastModified": 1718182050,
"narHash": "sha256-m5JQT/RIegSLZJx41Cv7d8Xoa2KKq+5uLkgB5KJR5D0=",
"owner": "RyanGibb",
"repo": "nixos-mailserver",
-
"rev": "fe7d01cbded4ab866d2ca42ea9374b41ab753e3f",
-
"type": "github"
},
"original": {
"owner": "RyanGibb",
"ref": "fork-24.05",
"repo": "nixos-mailserver",
-
"type": "github"
}
},
"nixpkgs": {
"locked": {
-
"lastModified": 1709703039,
-
"narHash": "sha256-6hqgQ8OK6gsMu1VtcGKBxKQInRLHtzulDo9Z5jxHEFY=",
-
"owner": "NixOS",
"repo": "nixpkgs",
-
"rev": "9df3e30ce24fd28c7b3e2de0d986769db5d6225d",
"type": "github"
},
"original": {
-
"id": "nixpkgs",
-
"ref": "nixos-unstable",
-
"type": "indirect"
}
},
"nixpkgs-24_05": {
···
"type": "indirect"
}
},
-
"nixpkgs_2": {
-
"locked": {
-
"lastModified": 1717952948,
-
"narHash": "sha256-mJi4/gjiwQlSaxjA6AusXBN/6rQRaPCycR7bd8fydnQ=",
-
"owner": "nixos",
-
"repo": "nixpkgs",
-
"rev": "2819fffa7fa42156680f0d282c60d81e8fb185b7",
-
"type": "github"
-
},
-
"original": {
-
"owner": "nixos",
-
"ref": "nixos-24.05",
-
"repo": "nixpkgs",
-
"type": "github"
-
}
-
},
"opam-nix": {
"inputs": {
"flake-compat": "flake-compat",
···
"nixpkgs"
],
"opam-overlays": "opam-overlays",
-
"opam-repository": [
-
"eon",
-
"opam-repository"
-
],
"opam2json": "opam2json"
},
"locked": {
-
"lastModified": 1703105504,
-
"narHash": "sha256-z7X1i2T1H37Lj9hEIJA5T0+sdE5E+PSWiiSyvYGyGSY=",
-
"owner": "RyanGibb",
"repo": "opam-nix",
-
"rev": "ccf2e75e8854aefe933c4e504f436a3b315802ee",
"type": "github"
},
"original": {
-
"owner": "RyanGibb",
-
"ref": "pin-depends-path",
"repo": "opam-nix",
"type": "github"
}
···
"opam-overlays": {
"flake": false,
"locked": {
-
"lastModified": 1654162756,
-
"narHash": "sha256-RV68fUK+O3zTx61iiHIoS0LvIk0E4voMp+0SwRg6G6c=",
"owner": "dune-universe",
"repo": "opam-overlays",
-
"rev": "c8f6ef0fc5272f254df4a971a47de7848cc1c8a4",
"type": "github"
},
"original": {
···
"opam-repository": {
"flake": false,
"locked": {
-
"lastModified": 1712915335,
-
"narHash": "sha256-CLxKnc9GgeNom5LzGhDyq4ZP8Mx8NtwYsg2YQfcSk3U=",
"owner": "ocaml",
"repo": "opam-repository",
-
"rev": "03178cf5192dd1a55105844365e56a2294cd9225",
"type": "github"
},
"original": {
···
"inputs": {
"eon": "eon",
"nixos-mailserver": "nixos-mailserver",
-
"nixpkgs": "nixpkgs_2"
}
},
"systems": {
···
"nixpkgs": [
"nixpkgs"
],
+
"opam-nix": "opam-nix"
},
"locked": {
+
"lastModified": 1738666931,
+
"narHash": "sha256-dTF+etN5ZDPVwK8XV/huQByY6JohiVgpCfzVJWAZY1I=",
"owner": "RyanGibb",
"repo": "eon",
+
"rev": "42523d1d8f720215ab5108a1b42e9c5b7d17d4bf",
"type": "github"
},
"original": {
···
"flake-compat": {
"flake": false,
"locked": {
+
"lastModified": 1696426674,
+
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
+
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
···
"systems": "systems"
},
"locked": {
+
"lastModified": 1731533236,
+
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
+
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
···
"mirage-opam-overlays": {
"flake": false,
"locked": {
+
"lastModified": 1710922379,
+
"narHash": "sha256-j4QREQDUf8oHOX7qg6wAOupgsNQoYlufxoPrgagD+pY=",
"owner": "dune-universe",
"repo": "mirage-opam-overlays",
+
"rev": "797cb363df3ff763c43c8fbec5cd44de2878757e",
"type": "github"
},
"original": {
···
"inputs": {
"blobs": "blobs",
"flake-compat": "flake-compat_2",
+
"nixpkgs": [
+
"nixpkgs"
+
],
"nixpkgs-24_05": "nixpkgs-24_05",
"utils": "utils"
},
"locked": {
+
"lastModified": 1718183756,
"narHash": "sha256-m5JQT/RIegSLZJx41Cv7d8Xoa2KKq+5uLkgB5KJR5D0=",
"owner": "RyanGibb",
"repo": "nixos-mailserver",
+
"rev": "9dc7a8d40232f600e6ca1e78356cd4398665b46b",
+
"type": "gitlab"
},
"original": {
"owner": "RyanGibb",
"ref": "fork-24.05",
"repo": "nixos-mailserver",
+
"type": "gitlab"
}
},
"nixpkgs": {
"locked": {
+
"lastModified": 1732981179,
+
"narHash": "sha256-F7thesZPvAMSwjRu0K8uFshTk3ZZSNAsXTIFvXBT+34=",
+
"owner": "nixos",
"repo": "nixpkgs",
+
"rev": "62c435d93bf046a5396f3016472e8f7c8e2aed65",
"type": "github"
},
"original": {
+
"owner": "nixos",
+
"ref": "nixos-24.11",
+
"repo": "nixpkgs",
+
"type": "github"
}
},
"nixpkgs-24_05": {
···
"type": "indirect"
}
},
"opam-nix": {
"inputs": {
"flake-compat": "flake-compat",
···
"nixpkgs"
],
"opam-overlays": "opam-overlays",
+
"opam-repository": "opam-repository",
"opam2json": "opam2json"
},
"locked": {
+
"lastModified": 1732617437,
+
"narHash": "sha256-jj25fziYrES8Ix6HkfSiLzrN6MZjiwlHUxFSIuLRjgE=",
+
"owner": "tweag",
"repo": "opam-nix",
+
"rev": "ea8b9cb81fe94e1fc45c6376fcff15f17319c445",
"type": "github"
},
"original": {
+
"owner": "tweag",
"repo": "opam-nix",
"type": "github"
}
···
"opam-overlays": {
"flake": false,
"locked": {
+
"lastModified": 1726822209,
+
"narHash": "sha256-bwM18ydNT9fYq91xfn4gmS21q322NYrKwfq0ldG9GYw=",
"owner": "dune-universe",
"repo": "opam-overlays",
+
"rev": "f2bec38beca4aea9e481f2fd3ee319c519124649",
"type": "github"
},
"original": {
···
"opam-repository": {
"flake": false,
"locked": {
+
"lastModified": 1732612513,
+
"narHash": "sha256-kju4NWEQo4xTxnKeBIsmqnyxIcCg6sNZYJ1FmG/gCDw=",
"owner": "ocaml",
"repo": "opam-repository",
+
"rev": "3d52b66b04788999a23f22f0d59c2dfc831c4f32",
"type": "github"
},
"original": {
···
"inputs": {
"eon": "eon",
"nixos-mailserver": "nixos-mailserver",
+
"nixpkgs": "nixpkgs"
}
},
"systems": {
+11 -6
flake.nix
···
{
inputs = {
-
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05";
-
nixos-mailserver.url = "github:RyanGibb/nixos-mailserver/fork-24.05";
eon.url = "github:RyanGibb/eon";
eon.inputs.nixpkgs.follows = "nixpkgs";
};
-
outputs = { self, nixpkgs, nixos-mailserver, eon, ... }: rec {
packages = nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed (system:
let pkgs = nixpkgs.legacyPackages.${system};
-
in { manpage = import ./man { inherit pkgs system nixos-mailserver; }; });
nixosModules.default = {
imports = [
···
nixos-mailserver.nixosModule
eon.nixosModules.default
eon.nixosModules.acme
-
({ pkgs, config, ... }: {
nixpkgs.overlays = [
(final: prev: {
mautrix-meta = (prev.callPackage ./pkgs/mautrix-meta.nix { });
})
];
-
})
];
};
defaultTemplate.path = ./template;
···
{
inputs = {
+
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11";
+
nixos-mailserver.url = "gitlab:RyanGibb/nixos-mailserver/fork-24.05";
eon.url = "github:RyanGibb/eon";
+
eon.inputs.nixpkgs.follows = "nixpkgs";
+
nixos-mailserver.inputs.nixpkgs.follows = "nixpkgs";
};
+
outputs = { nixpkgs, nixos-mailserver, eon, ... }: {
packages = nixpkgs.lib.genAttrs nixpkgs.lib.systems.flakeExposed (system:
let pkgs = nixpkgs.legacyPackages.${system};
+
in {
+
manpage = import ./man { inherit pkgs system nixos-mailserver; };
+
packages.mautrix-meta = (pkgs.callPackage ./pkgs/mautrix-meta.nix { });
+
});
nixosModules.default = {
imports = [
···
nixos-mailserver.nixosModule
eon.nixosModules.default
eon.nixosModules.acme
+
{
nixpkgs.overlays = [
(final: prev: {
mautrix-meta = (prev.callPackage ./pkgs/mautrix-meta.nix { });
})
];
+
}
];
};
defaultTemplate.path = ./template;
+1
modules/default.nix
···
./mailserver.nix
./gitea.nix
./dns.nix
./matrix/synapse.nix
./matrix/mautrix-instagram.nix
./matrix/mautrix-messenger.nix
···
./mailserver.nix
./gitea.nix
./dns.nix
+
./fail2ban.nix
./matrix/synapse.nix
./matrix/mautrix-instagram.nix
./matrix/mautrix-messenger.nix
+42
modules/fail2ban.nix
···
···
+
{ config, pkgs, lib, ... }:
+
+
with lib;
+
let cfg = config.eilean;
+
in {
+
options.eilean.fail2ban = {
+
enable = mkEnableOption "TURN server";
+
radicale = mkOption {
+
type = types.bool;
+
default = cfg.radicale.enable;
+
};
+
};
+
+
config = mkIf cfg.fail2ban.enable {
+
services.fail2ban = {
+
enable = true;
+
bantime = "24h";
+
bantime-increment = {
+
enable = true;
+
multipliers = "1 2 4 8 16 32 64";
+
maxtime = "168h";
+
overalljails = true;
+
};
+
jails."radicale".settings = mkIf cfg.fail2ban.radicale {
+
port = "5232";
+
filter = "radicale";
+
banaction = "%(banaction_allports)s[name=radicale]";
+
backend = "systemd";
+
journalmatch = "_SYSTEMD_UNIT=radicale.service";
+
maxRetry = 2;
+
bantime = -1;
+
findtime = 14400;
+
};
+
};
+
environment.etc = {
+
"fail2ban/filter.d/radicale.local".text = mkIf cfg.fail2ban.radicale ''
+
[Definition]
+
failregex = ^.*Failed\slogin\sattempt\sfrom\s.*\(forwarded for \'<HOST>\'.*\):\s.*
+
'';
+
};
+
};
+
}
-5
modules/headscale.nix
···
server_url = "https://${cfg.headscale.domain}";
logtail.enabled = false;
ip_prefixes = [ "100.64.0.0/10" "fd7a:115c:a1e0::/48" ];
-
dns_config = {
-
# magicDns = true;
-
nameservers = config.networking.nameservers;
-
base_domain = "${cfg.headscale.zone}";
-
};
};
};
···
server_url = "https://${cfg.headscale.domain}";
logtail.enabled = false;
ip_prefixes = [ "100.64.0.0/10" "fd7a:115c:a1e0::/48" ];
};
};
+12 -7
modules/matrix/synapse.nix
···
'';
# forward all Matrix API calls to the synapse Matrix homeserver
-
locations."/_matrix" = {
-
proxyPass = "http://127.0.0.1:8008"; # without a trailing /
-
#proxyPassReverse = "http://127.0.0.1:8008"; # without a trailing /
};
};
};
···
}];
}];
max_upload_size = "100M";
-
app_service_config_files = (optional cfg.matrix.bridges.whatsapp
-
"/var/lib/mautrix-whatsapp/whatsapp-registration.yaml")
-
++ (optional cfg.matrix.bridges.instagram
-
"/var/lib/mautrix-instagram/instagram-registration.yaml")
++ (optional cfg.matrix.bridges.messenger
"/var/lib/mautrix-messenger/messenger-registration.yaml");
}
···
settings.bridge.history_sync.backfill = false;
settings.bridge.permissions."@${config.eilean.username}:${domain}" =
"admin";
};
# using https://github.com/NixOS/nixpkgs/pull/277368
services.mautrix-signal = mkIf cfg.matrix.bridges.signal {
···
settings.bridge.personal_filtering_spaces = true;
settings.bridge.permissions."@${config.eilean.username}:${domain}" =
"admin";
};
# TODO replace with upstreamed mautrix-meta
services.mautrix-instagram = mkIf cfg.matrix.bridges.instagram {
···
settings.bridge.backfill.enabled = false;
settings.bridge.permissions."@${config.eilean.username}:${domain}" =
"admin";
};
services.mautrix-messenger = mkIf cfg.matrix.bridges.messenger {
enable = true;
···
settings.bridge.backfill.enabled = false;
settings.bridge.permissions."@${config.eilean.username}:${domain}" =
"admin";
};
eilean.turn.enable = mkIf cfg.matrix.turn true;
···
'';
# forward all Matrix API calls to the synapse Matrix homeserver
+
locations."~ ^(\\/_matrix|\\/_synapse\\/client)" = {
+
proxyPass = "http://127.0.0.1:8008";
};
};
};
···
}];
}];
max_upload_size = "100M";
+
app_service_config_files = (optional cfg.matrix.bridges.instagram
+
"/var/lib/mautrix-instagram/instagram-registration.yaml")
++ (optional cfg.matrix.bridges.messenger
"/var/lib/mautrix-messenger/messenger-registration.yaml");
}
···
settings.bridge.history_sync.backfill = false;
settings.bridge.permissions."@${config.eilean.username}:${domain}" =
"admin";
+
settings.bridge.encryption.allow = true;
+
settings.bridge.encryption.default = true;
};
# using https://github.com/NixOS/nixpkgs/pull/277368
services.mautrix-signal = mkIf cfg.matrix.bridges.signal {
···
settings.bridge.personal_filtering_spaces = true;
settings.bridge.permissions."@${config.eilean.username}:${domain}" =
"admin";
+
settings.bridge.encryption.allow = true;
+
settings.bridge.encryption.default = true;
};
# TODO replace with upstreamed mautrix-meta
services.mautrix-instagram = mkIf cfg.matrix.bridges.instagram {
···
settings.bridge.backfill.enabled = false;
settings.bridge.permissions."@${config.eilean.username}:${domain}" =
"admin";
+
settings.bridge.encryption.allow = true;
+
settings.bridge.encryption.default = true;
};
services.mautrix-messenger = mkIf cfg.matrix.bridges.messenger {
enable = true;
···
settings.bridge.backfill.enabled = false;
settings.bridge.permissions."@${config.eilean.username}:${domain}" =
"admin";
+
settings.bridge.encryption.allow = true;
+
settings.bridge.encryption.default = true;
};
eilean.turn.enable = mkIf cfg.matrix.turn true;
+2 -2
modules/radicale.nix
···
options.eilean.radicale = {
enable = mkEnableOption "radicale";
users = mkOption {
-
type = with types; attrsOf (submodule userOps);
default = { };
};
};
···
systemd.services.radicale = {
serviceConfig.ReadWritePaths = [ "/var/lib/radicale" ];
-
preStart = ''
if (! test -d "${passwdDir}"); then
mkdir "${passwdDir}"
chmod 755 "${passwdDir}"
···
options.eilean.radicale = {
enable = mkEnableOption "radicale";
users = mkOption {
+
type = with types; nullOr (attrsOf (submodule userOps));
default = { };
};
};
···
systemd.services.radicale = {
serviceConfig.ReadWritePaths = [ "/var/lib/radicale" ];
+
preStart = lib.mkIf (cfg.radicale.users != null) ''
if (! test -d "${passwdDir}"); then
mkdir "${passwdDir}"
chmod 755 "${passwdDir}"
+26
modules/services/dns/eon.nix
···
}/${zonename}";
in lib.attrsets.mapAttrsToList mapZonefile cfg.zones;
};
}
···
}/${zonename}";
in lib.attrsets.mapAttrsToList mapZonefile cfg.zones;
};
+
+
users.users = { eon.extraGroups = [ config.services.opendkim.group ]; };
+
+
### bind prestart copy zonefiles
+
systemd.services.eon.postStart = let
+
update = ''
+
update() {
+
local file="$1"
+
local domain="$2"
+
local input=$(tr -d '\n' < "$file")
+
local record_name=$(echo "$input" | ${pkgs.gawk}/bin/awk '{print $1}')
+
local record_type=$(echo "$input" | ${pkgs.gawk}/bin/awk '{print $3}')
+
local ttl=3600
+
local record_value=$(echo "$input" | ${pkgs.gnused}/bin/sed -E 's/[^"]*"([^"]*)"[^"]*/\1/g')
+
${config.services.eon.package}/bin/capc update /var/lib/eon/caps/domain/''${domain}.cap -u "add|''${record_name}.''${domain}|''${record_type}|''${record_value}|''${ttl}" || exit 0
+
}
+
shopt -s nullglob
+
'';
+
ops = let
+
mapZones = zonename: zone: ''
+
for f in ${config.mailserver.dkimKeyDirectory}/${zonename}.*.txt; do
+
update $f ${zonename}
+
done
+
'';
+
in lib.attrsets.mapAttrsToList mapZones cfg.zones;
+
in update + builtins.concatStringsSep "\n" ops;
}
+3 -1
modules/turn.nix
···
script = ''
if [ ! -f '${staticAuthSecretFile}' ]; then
umask 077
tr -dc A-Za-z0-9 </dev/urandom | head -c 32 > '${staticAuthSecretFile}'
-
chown ${config.systemd.services.coturn.serviceConfig.User}:${config.systemd.services.coturn.serviceConfig.Group} '${staticAuthSecretFile}'
fi
'';
serviceConfig.Type = "oneshot";
···
script = ''
if [ ! -f '${staticAuthSecretFile}' ]; then
umask 077
+
DIR="$(dirname '${staticAuthSecretFile}')"
+
mkdir -p "$DIR"
tr -dc A-Za-z0-9 </dev/urandom | head -c 32 > '${staticAuthSecretFile}'
+
chown -R ${config.systemd.services.coturn.serviceConfig.User}:${config.systemd.services.coturn.serviceConfig.Group} "$DIR"
fi
'';
serviceConfig.Type = "oneshot";
+6 -4
pkgs/mautrix-meta.nix
···
{ lib, buildGoModule, fetchFromGitHub, olm }:
-
buildGoModule rec {
name = "mautrix-meta";
src = fetchFromGitHub {
owner = "mautrix";
repo = "meta";
-
rev = "7941e937055b792d2cbfde5d9c8c4df75e68ff0a";
-
hash = "sha256-QDqN6AAaEngWo4UxKAyIXB7BwCEJqsMTeuMb2fKu/9o=";
};
buildInputs = [ olm ];
-
vendorHash = "sha256-ClHg3OEKgXYsmBm/aFKWZXbaLOmKdNyvw42QGhtTRik=";
doCheck = false;
···
{ lib, buildGoModule, fetchFromGitHub, olm }:
+
let version = "0.4.4";
+
in buildGoModule rec {
name = "mautrix-meta";
+
inherit version;
src = fetchFromGitHub {
owner = "mautrix";
repo = "meta";
+
rev = "v${version}";
+
hash = "sha256-S8x3TGQEs+oh/3Q1Gz00M8dOcjjuHSgzVhqlbikZ8QE=";
};
buildInputs = [ olm ];
+
vendorHash = "sha256-sUnvwPJQOoVzxbo2lS3CRcTrWsPjgYPsKClVw1wZJdM=";
doCheck = false;