summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--bragi.nix157
-rw-r--r--bragi/bar/default.nix33
-rw-r--r--bragi/bar/generated.nix34
-rw-r--r--bragi/bar/generated.nix.gup5
-rw-r--r--bragi/thermoprint-server/thermoprint-server.hs45
m---------custom/thermoprint0
-rw-r--r--custom/tinc/def.nix145
m---------custom/trivmix0
-rw-r--r--custom/trivmix-service.nix41
l---------custom/trivmix.nix1
-rw-r--r--custom/uucp.nix18
-rw-r--r--customized/prosody.nix8
-rw-r--r--hel.nix104
-rw-r--r--hel/recv-media.nix3
m---------musnix0
-rw-r--r--users.nix1
-rw-r--r--users/gkleen@ymir.nix1
-rw-r--r--users/mherold.nix2
-rw-r--r--users/some.nix8
m---------utils0
-rw-r--r--ymir.nix130
-rw-r--r--ymir/mlmmj-expose.hs182
-rw-r--r--ymir/mlmmj-expose.nix112
-rw-r--r--ymir/zones/email.nights.soa34
-rw-r--r--ymir/zones/index.nix3
-rw-r--r--ymir/zones/li.kleen.soa (renamed from ymir/zones/li.lmu.soa)17
27 files changed, 773 insertions, 315 deletions
diff --git a/.gitignore b/.gitignore
index 3b10a887..eb514beb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
1configuration.nix 1configuration.nix
2config.nix 2config.nix
3**/\#*\# \ No newline at end of file 3**/\#*\#
4**/.gup/
5**/result
diff --git a/bragi.nix b/bragi.nix
index fe447e2d..f0817580 100644
--- a/bragi.nix
+++ b/bragi.nix
@@ -3,6 +3,7 @@
3let 3let
4 trivmixService = opts: (pkgs.callPackage ./custom/trivmix-service.nix opts).out; 4 trivmixService = opts: (pkgs.callPackage ./custom/trivmix-service.nix opts).out;
5 thermoprint-servant = (pkgs.callPackage ./custom/thermoprint {}).thermoprint-servant; 5 thermoprint-servant = (pkgs.callPackage ./custom/thermoprint {}).thermoprint-servant;
6 inherit (pkgs) lib;
6in rec { 7in rec {
7 imports = 8 imports =
8 [ ./musnix 9 [ ./musnix
@@ -31,29 +32,22 @@ in rec {
31 overrides = self: super: let 32 overrides = self: super: let
32 callPackage = pkgs.lib.callPackageWith ( pkgs // self ); 33 callPackage = pkgs.lib.callPackageWith ( pkgs // self );
33 in { 34 in {
34 trivmix = callPackage ./custom/trivmix.nix {}; 35 trivmix = callPackage ./custom/trivmix {};
35 # filelock = callPackage ./custom/filelock.nix {};
36 }; 36 };
37 } 37 }
38 ); 38 );
39 39
40 jack2Full = pkgs.jack2Full.override { dbus = null; }; 40 jack2Full = pkgs.jack2Full.override { dbus = null; };
41 41
42 mpd = pkgs.symlinkJoin { 42 mpd = pkgs.mpd.override { gmeSupport = false; pulseaudioSupport = false; };
43 name = "mpd";
44 paths = [ (pkgs.mpd.override { gmeSupport = false; pulseaudioSupport = false; }) ];
45 buildInputs = [ pkgs.makeWrapper ];
46 postBuild = ''
47 wrapProgram $out/bin/mpd \
48 --run "umask 0"
49 '';
50 };
51 43
52 inherit (pkgs.callPackage ./custom/thermoprint {}) thermoprint-server thermoprint-webgui tprint; 44 inherit (pkgs.callPackage ./custom/thermoprint { extraPackages = (p: with p; [ persistent-postgresql ]); }) thermoprint-server thermoprint-webgui tprint;
53 45
54 inherit (haskellPackages) trivmix; 46 inherit (haskellPackages) trivmix;
55 }; 47 };
56 48
49 nixpkgs.config.allowUnfree = true;
50
57 environment.systemPackages = with pkgs; [ 51 environment.systemPackages = with pkgs; [
58 git 52 git
59 mosh 53 mosh
@@ -124,17 +118,20 @@ in rec {
124 }; 118 };
125 }; 119 };
126 120
127 systemd.services."mpdmix0" = trivmixService { name = "mpdmix0"; connectOut = "system:playback_3"; group = "mpd"; }; 121 systemd.services."mpdmix0" = trivmixService { name = "mpdmix0"; connectOut = "system:playback_3"; group = "mpd"; initial = "-35dB"; };
128 systemd.services."mpdmix1" = trivmixService { name = "mpdmix1"; connectOut = "system:playback_4"; group = "mpd"; }; 122 systemd.services."mpdmix1" = trivmixService { name = "mpdmix1"; connectOut = "system:playback_4"; group = "mpd"; initial = "-35dB"; };
123
124 systemd.services."passmix0" = trivmixService { name = "passmix0"; connectOut = "system:playback_3"; connectIn = "system:capture_5"; group = "vali_out"; initial = "-20dB"; };
125 systemd.services."passmix1" = trivmixService { name = "passmix1"; connectOut = "system:playback_4"; connectIn = "system:capture_6"; group = "vali_out"; initial = "-20dB"; };
129 126
130 systemd.services."passmix0" = trivmixService { name = "passmix0"; connectOut = "system:playback_3"; connectIn = "system:capture_5"; group = "vali_out"; }; 127 systemd.services."passmix2" = trivmixService { name = "passmix2"; connectOut = "system:playback_5"; connectIn = "system:capture_1"; group = "vali_in"; initial = "1"; };
131 systemd.services."passmix1" = trivmixService { name = "passmix1"; connectOut = "system:playback_4"; connectIn = "system:capture_6"; group = "vali_out"; }; 128 systemd.services."passmix3" = trivmixService { name = "passmix3"; connectOut = "system:playback_6"; connectIn = "system:capture_1"; group = "vali_in"; initial = "1"; };
132 129
133 systemd.services."passmix2" = trivmixService { name = "passmix2"; connectOut = "system:playback_5"; connectIn = "system:capture_1"; group = "vali_in"; }; 130 systemd.services."passmix4" = trivmixService { name = "passmix4"; connectOut = "system:playback_3"; connectIn = "system:capture_7"; group = "hel_out"; initial = "-17.5dB"; };
134 systemd.services."passmix3" = trivmixService { name = "passmix3"; connectOut = "system:playback_6"; connectIn = "system:capture_1"; group = "vali_in"; }; 131 systemd.services."passmix5" = trivmixService { name = "passmix5"; connectOut = "system:playback_4"; connectIn = "system:capture_8"; group = "hel_out"; initial = "-17.5dB"; };
135 132
136 systemd.services."passmix4" = trivmixService { name = "passmix4"; connectOut = "system:playback_3"; connectIn = "system:capture_7"; group = "hel_out"; }; 133 systemd.services."passmix6" = trivmixService { name = "passmix6"; connectOut = "system:playback_7"; connectIn = "system:capture_1"; group = "hel_in"; initial = "1"; };
137 systemd.services."passmix5" = trivmixService { name = "passmix5"; connectOut = "system:playback_4"; connectIn = "system:capture_8"; group = "hel_out"; }; 134 systemd.services."passmix7" = trivmixService { name = "passmix7"; connectOut = "system:playback_8"; connectIn = "system:capture_1"; group = "hel_in"; initial = "1"; };
138 135
139 services.mpd = { 136 services.mpd = {
140 enable = true; 137 enable = true;
@@ -159,6 +156,9 @@ in rec {
159 systemd.services."mpd".requires = [ "jack.service" ]; 156 systemd.services."mpd".requires = [ "jack.service" ];
160 systemd.services."mpd".serviceConfig = { 157 systemd.services."mpd".serviceConfig = {
161 LimitMEMLOCK = "infinity"; 158 LimitMEMLOCK = "infinity";
159 Nice = "-5";
160 LimitRTPRIO = "95:95";
161 UMask = "0000";
162 }; 162 };
163 163
164 users.extraUsers.jack = { 164 users.extraUsers.jack = {
@@ -167,7 +167,7 @@ in rec {
167 group = "audio"; 167 group = "audio";
168 }; 168 };
169 169
170 security.setuidPrograms = ["mount.nfs"]; 170 security.wrappers = { "mount.nfs".source = "${pkgs.nfs-utils}/bin/mount.nfs"; };
171 171
172 programs.bash.promptInit = '' 172 programs.bash.promptInit = ''
173 PROMPT_COLOR="1;31m" 173 PROMPT_COLOR="1;31m"
@@ -208,6 +208,7 @@ in rec {
208 allowPing = true; 208 allowPing = true;
209 allowedTCPPorts = [ 22 # SSH 209 allowedTCPPorts = [ 22 # SSH
210 80 # HTTP 210 80 # HTTP
211 5432 # PostgreSQL
211 6600 # MPD 212 6600 # MPD
212 ]; 213 ];
213 allowedUDPPortRanges = [ { from = 60000; to = 61000; } # mosh 214 allowedUDPPortRanges = [ { from = 60000; to = 61000; } # mosh
@@ -220,7 +221,14 @@ in rec {
220 ''; 221 '';
221 }; 222 };
222 223
223 services.dhcpd = { 224 networking.defaultMailServer = {
225 directDelivery = true;
226 hostName = "ymir.niflheim.yggdrasil";
227 useSTARTTLS = true;
228 setSendmail = true;
229 };
230
231 services.dhcpd4 = {
224 enable = true; 232 enable = true;
225 interfaces = [ "enp1s0" 233 interfaces = [ "enp1s0"
226 ]; 234 ];
@@ -249,14 +257,6 @@ in rec {
249 ''; 257 '';
250 }; 258 };
251 259
252 services.ntp = {
253 enable = false;
254 };
255
256 services.chrony = {
257 enable = true;
258 };
259
260 users.extraUsers.root = let 260 users.extraUsers.root = let
261 template = (import users/gkleen.nix); 261 template = (import users/gkleen.nix);
262 in { 262 in {
@@ -272,56 +272,19 @@ in rec {
272 home = "/var/lib/thermoprint"; 272 home = "/var/lib/thermoprint";
273 }; 273 };
274 274
275 environment.etc."thermoprint-server/thermoprint-server.hs" = {
276 text = ''
277 {-# LANGUAGE OverloadedStrings #-}
278 {-# LANGUAGE ImpredicativeTypes #-}
279
280 module Main (main) where
281
282 import Thermoprint.Server
283
284 import Thermoprint.Server.Printer.Generic
285
286 import Control.Monad.Trans.Resource
287 import Control.Monad.Logger
288 import Control.Monad.Reader
289
290 import Database.Persist.Sqlite
291
292 import qualified Network.Wai.Handler.Warp as Warp
293
294 main :: IO ()
295 main = thermoprintServer True (Nat runSqlite) $ (\c -> c { queueManagers = queueManagers, warpSettings = wSettings }) <$> def `withPrinters` printers
296 where
297 runSqlite :: ReaderT ConnectionPool (LoggingT IO) a -> IO a
298 runSqlite = runStderrLoggingT . withSqlitePool "${users.extraUsers."thermoprint".home}/thermoprint.sqlite" 1 . runReaderT
299
300 printers = [ (pure $ genericPrint "/dev/usb/lp0", def :: QMConfig (ResourceT (ReaderT ConnectionPool (LoggingT IO))))
301 ]
302
303 queueManagers _ = QMConfig
304 { manager = union [ limitHistorySize 100
305 , limitHistoryAge 3600
306 ]
307 , collapse = standardCollapse
308 }
309
310 wSettings = Warp.setHost "127.0.0.1" . Warp.setPort 8080 $ Warp.defaultSettings
311 '';
312 };
313
314 systemd.services."thermoprint" = { 275 systemd.services."thermoprint" = {
315 environment = { 276 environment = {
316 THERMOPRINT_CONFIG = "/etc/thermoprint-server"; 277 THERMOPRINT_CONFIG = ./bragi/thermoprint-server;
317 THERMOPRINT_CACHE = ''${users.extraUsers."thermoprint".home}/dyre''; 278 THERMOPRINT_CACHE = ''${users.extraUsers."thermoprint".home}/dyre'';
318 }; 279 };
280 requires = [ "postgresql.service" ];
319 wantedBy = [ "default.target" ]; 281 wantedBy = [ "default.target" ];
320 serviceConfig = { 282 serviceConfig = {
321 Type = "simple"; 283 Type = "simple";
322 ExecStart = ''${pkgs.thermoprint-server}/bin/thermoprint-server --force-reconf''; 284 ExecStart = ''${pkgs.thermoprint-server}/bin/thermoprint-server --force-reconf'';
323 User = users.extraUsers."thermoprint".name; 285 User = users.extraUsers."thermoprint".name;
324 Group = users.extraUsers."thermoprint".group; 286 Group = users.extraUsers."thermoprint".group;
287 WorkingDirectory = "~";
325 }; 288 };
326 }; 289 };
327 290
@@ -332,6 +295,35 @@ in rec {
332 ExecStart = ''${pkgs.thermoprint-webgui}/bin/thermoprint-webgui -P 80 -A localhost -F /thermoprint/api/ -a "localhost" -p 8081''; 295 ExecStart = ''${pkgs.thermoprint-webgui}/bin/thermoprint-webgui -P 80 -A localhost -F /thermoprint/api/ -a "localhost" -p 8081'';
333 User = users.extraUsers."thermoprint".name; 296 User = users.extraUsers."thermoprint".name;
334 Group = users.extraUsers."thermoprint".group; 297 Group = users.extraUsers."thermoprint".group;
298 WorkingDirectory = "~";
299 };
300 };
301
302 users.extraUsers."bar" = {
303 name = "bar";
304 group = "nogroup";
305 isSystemUser = true;
306 createHome = true;
307 home = "/var/lib/bar";
308 };
309
310 systemd.services."bar" = let
311 ghc = pkgs.haskellPackages.ghcWithPackages (p: with p; [yesod persistent-postgresql]);
312 in {
313 environment = {
314 PORT = "8082";
315 HOST = "::1";
316 };
317 requires = [ "postgresql.service" ];
318 wantedBy = [ "default.target" ];
319 serviceConfig = {
320 Type = "simple";
321 ExecStart = ''
322 ${pkgs.callPackage ./bragi/bar {}}/bin/bar
323 '';
324 User = users.extraUsers."bar".name;
325 Group = users.extraUsers."bar".group;
326 WorkingDirectory = "~";
335 }; 327 };
336 }; 328 };
337 329
@@ -379,7 +371,7 @@ in rec {
379 server_name _; 371 server_name _;
380 372
381 location /thermoprint/api/ { 373 location /thermoprint/api/ {
382 proxy_pass http://localhost:8080/; 374 proxy_pass http://[::1]:8080/;
383 proxy_http_version 1.1; 375 proxy_http_version 1.1;
384 proxy_set_header Upgrade $http_upgrade; 376 proxy_set_header Upgrade $http_upgrade;
385 proxy_set_header Connection "upgrade"; 377 proxy_set_header Connection "upgrade";
@@ -388,10 +380,33 @@ in rec {
388 location /thermoprint/ { 380 location /thermoprint/ {
389 proxy_pass http://localhost:8081/; 381 proxy_pass http://localhost:8081/;
390 } 382 }
383
384 location /bar/ {
385 proxy_set_header AppRoot "http://$host/bar";
386 proxy_pass http://[::1]:8082/;
387 }
391 } 388 }
392 ''; 389 '';
393 }; 390 };
394 391
392 services.postgresql = {
393 enable = true;
394 enableTCPIP = true;
395 authentication = lib.mkForce ''
396 local all all peer
397 host all all 10.141.0.0/16 md5
398 '';
399 initialScript = pkgs.writeText "schema.sql" ''
400 CREATE USER thermoprint;
401 CREATE DATABASE thermoprint WITH OWNER = thermoprint;
402 GRANT ALL ON DATABASE thermoprint TO thermoprint;
403
404 CREATE USER bar;
405 CREATE DATABASE bar WITH OWNER = bar;
406 GRANT ALL ON DATABASE bar TO bar;
407 '';
408 };
409
395 nix = { 410 nix = {
396 daemonIONiceLevel = 3; 411 daemonIONiceLevel = 3;
397 daemonNiceLevel = 10; 412 daemonNiceLevel = 10;
diff --git a/bragi/bar/default.nix b/bragi/bar/default.nix
new file mode 100644
index 00000000..bbfa170c
--- /dev/null
+++ b/bragi/bar/default.nix
@@ -0,0 +1,33 @@
1{ haskellPackages
2, stdenv
3, fetchFromGitHub
4, jquery
5}:
6
7let
8 pkg = haskellPackages.callPackage ./generated.nix {};
9 webshim = stdenv.mkDerivation rec {
10 name = "webshim-${version}";
11 version = "1.16.0";
12 src = fetchFromGitHub {
13 owner = "aFarkas";
14 repo = "webshim";
15 rev = "1.16.0";
16 sha256 = "14pk7hljqipzp0n7vpgcfxr3w4bla57cwyd7bmwmmxrm2zn62cyh";
17 };
18
19 installPhase = ''
20 mkdir -p $out/js
21 cp -r $src/js-webshim/dev/* $out/js/
22 '';
23 };
24in stdenv.lib.overrideDerivation pkg (drv: {
25 postUnpack = ''
26 (
27 cd bar-*/static
28 rm -rf jquery.js webshim
29 ln -vs ${jquery}/js/jquery.js .
30 ln -vs ${webshim}/js webshim
31 )
32 '';
33})
diff --git a/bragi/bar/generated.nix b/bragi/bar/generated.nix
new file mode 100644
index 00000000..4243ad4d
--- /dev/null
+++ b/bragi/bar/generated.nix
@@ -0,0 +1,34 @@
1{ mkDerivation, aeson, base, bytestring, case-insensitive
2, classy-prelude, classy-prelude-conduit, classy-prelude-yesod
3, conduit, containers, data-default, directory, fast-logger
4, fetchgit, file-embed, hjsmin, http-conduit, lens, monad-control
5, monad-logger, mtl, persistent, persistent-postgresql
6, persistent-template, safe, shakespeare, stdenv, template-haskell
7, text, time, unordered-containers, vector, wai, wai-extra
8, wai-logger, warp, yaml, yesod, yesod-auth, yesod-core, yesod-form
9, yesod-static
10}:
11mkDerivation {
12 pname = "bar";
13 version = "0.0.0";
14 src = fetchgit {
15 url = "git://git.yggdrasil.li/gkleen/pub/bar";
16 sha256 = "13h5hxwx4y79jr19l894zq4ynvkmhfds52xm8dlsdl5j69gg7laa";
17 rev = "53fcf55c02f9335518c28d26429913258fc28f87";
18 };
19 isLibrary = true;
20 isExecutable = true;
21 libraryHaskellDepends = [
22 aeson base bytestring case-insensitive classy-prelude
23 classy-prelude-conduit classy-prelude-yesod conduit containers
24 data-default directory fast-logger file-embed hjsmin http-conduit
25 lens monad-control monad-logger mtl persistent
26 persistent-postgresql persistent-template safe shakespeare
27 template-haskell text time unordered-containers vector wai
28 wai-extra wai-logger warp yaml yesod yesod-auth yesod-core
29 yesod-form yesod-static
30 ];
31 executableHaskellDepends = [ base ];
32 doHaddock = false;
33 license = stdenv.lib.licenses.unfree;
34}
diff --git a/bragi/bar/generated.nix.gup b/bragi/bar/generated.nix.gup
new file mode 100644
index 00000000..eeb13ad2
--- /dev/null
+++ b/bragi/bar/generated.nix.gup
@@ -0,0 +1,5 @@
1#!/usr/bin/env zsh
2
3gup -u ${2:r}.cabal
4cd ${2:h}
5cabal2nix --no-haddock "git://git.yggdrasil.li/gkleen/pub/bar" >! ${1}
diff --git a/bragi/thermoprint-server/thermoprint-server.hs b/bragi/thermoprint-server/thermoprint-server.hs
new file mode 100644
index 00000000..4635dd0a
--- /dev/null
+++ b/bragi/thermoprint-server/thermoprint-server.hs
@@ -0,0 +1,45 @@
1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE ImpredicativeTypes #-}
3
4module Main (main) where
5
6import Thermoprint.Server
7
8import Thermoprint.Server.Printer.Generic
9
10import Control.Monad.Trans.Resource
11import Control.Monad.Logger
12import Control.Monad.Reader
13
14import Data.Function ((&))
15
16import Database.Persist.Postgresql
17
18import qualified Network.Wai.Handler.Warp as Warp
19
20type ServerM = ReaderT ConnectionPool (LoggingT IO)
21
22main :: IO ()
23main = thermoprintServer True (Nat runDb) $ configure <$> def `withPrinters` printers'
24 where
25 runDb :: ServerM a -> IO a
26 runDb = runStderrLoggingT . withPostgresqlPool "" 5 . runReaderT
27
28 printers' = [ (pure $ genericPrint "/dev/usb/lp0", def :: QMConfig (ResourceT ServerM))
29 ]
30
31 configure c = c
32 { queueManagers = queueManagers
33 , warpSettings = warpSettings
34 }
35
36 queueManagers _ = QMConfig
37 { manager = union [ limitHistorySize 100
38 , limitHistoryAge 3600
39 ]
40 , collapse = standardCollapse
41 }
42
43 warpSettings = Warp.defaultSettings
44 & Warp.setHost "::1"
45 & Warp.setPort 8080
diff --git a/custom/thermoprint b/custom/thermoprint
Subproject e95dac748371afcad3ffddf5c98e5fcb0a8302b Subproject ba2e44af40746f339e1ed652ea233c739790556
diff --git a/custom/tinc/def.nix b/custom/tinc/def.nix
index 58c5237c..563335ad 100644
--- a/custom/tinc/def.nix
+++ b/custom/tinc/def.nix
@@ -6,6 +6,77 @@ let
6 6
7 cfg = config.services.customTinc; 7 cfg = config.services.customTinc;
8 8
9 networkModule = {
10 extraConfig = mkOption {
11 default = ''
12 PingTimeout = 10
13 '';
14 type = types.lines;
15 description = ''
16 Extra lines to add to the tinc service configuration file.
17 '';
18 };
19
20 name = mkOption {
21 default = null;
22 type = types.nullOr types.str;
23 description = ''
24 The name of the node which is used as an identifier when communicating
25 with the remote nodes in the mesh. If null then the hostname of the system
26 is used.
27 '';
28 };
29
30 debugLevel = mkOption {
31 default = 0;
32 type = types.addCheck types.int (l: l >= 0 && l <= 5);
33 description = ''
34 The amount of debugging information to add to the log. 0 means little
35 logging while 5 is the most logging. <command>man tincd</command> for
36 more details.
37 '';
38 };
39
40 hosts = mkOption {
41 default = { };
42 type = types.loaOf types.lines;
43 description = ''
44 The name of the host in the network as well as the configuration for that host.
45 This name should only contain alphanumerics and underscores.
46 '';
47 };
48
49 interfaceType = mkOption {
50 default = "tun";
51 type = types.addCheck types.str (n: n == "tun" || n == "tap");
52 description = ''
53 The type of virtual interface used for the network connection
54 '';
55 };
56
57 interfaceConfig = mkOption {
58 default = { };
59 description = ''
60 Additional configuration for the generated network interface
61 '';
62 };
63
64 package = mkOption {
65 default = pkgs.tinc_pre;
66 description = ''
67 The package to use for the tinc daemon's binary.
68 '';
69 };
70
71 scripts = mkOption {
72 default = { };
73 type = types.loaOf (types.nullOr types.str);
74 description = ''
75 Hook scripts
76 '';
77 };
78
79 };
9in 80in
10 81
11{ 82{
@@ -18,83 +89,11 @@ in
18 89
19 networks = mkOption { 90 networks = mkOption {
20 default = { }; 91 default = { };
21 type = types.loaOf types.optionSet; 92 type = types.loaOf (types.submodule { options = networkModule; });
22 description = '' 93 description = ''
23 Defines the tinc networks which will be started. 94 Defines the tinc networks which will be started.
24 Each network invokes a different daemon. 95 Each network invokes a different daemon.
25 ''; 96 '';
26 options = {
27
28 extraConfig = mkOption {
29 default = ''
30 PingTimeout = 10
31 '';
32 type = types.lines;
33 description = ''
34 Extra lines to add to the tinc service configuration file.
35 '';
36 };
37
38 name = mkOption {
39 default = null;
40 type = types.nullOr types.str;
41 description = ''
42 The name of the node which is used as an identifier when communicating
43 with the remote nodes in the mesh. If null then the hostname of the system
44 is used.
45 '';
46 };
47
48 debugLevel = mkOption {
49 default = 0;
50 type = types.addCheck types.int (l: l >= 0 && l <= 5);
51 description = ''
52 The amount of debugging information to add to the log. 0 means little
53 logging while 5 is the most logging. <command>man tincd</command> for
54 more details.
55 '';
56 };
57
58 hosts = mkOption {
59 default = { };
60 type = types.loaOf types.lines;
61 description = ''
62 The name of the host in the network as well as the configuration for that host.
63 This name should only contain alphanumerics and underscores.
64 '';
65 };
66
67 interfaceType = mkOption {
68 default = "tun";
69 type = types.addCheck types.str (n: n == "tun" || n == "tap");
70 description = ''
71 The type of virtual interface used for the network connection
72 '';
73 };
74
75 interfaceConfig = mkOption {
76 default = { };
77 description = ''
78 Additional configuration for the generated network interface
79 '';
80 };
81
82 package = mkOption {
83 default = pkgs.tinc_pre;
84 description = ''
85 The package to use for the tinc daemon's binary.
86 '';
87 };
88
89 scripts = mkOption {
90 default = { };
91 type = types.loaOf (types.nullOr types.str);
92 description = ''
93 Hook scripts
94 '';
95 };
96
97 };
98 }; 97 };
99 }; 98 };
100 99
diff --git a/custom/trivmix b/custom/trivmix
Subproject 72467d55a7b6e3afcafc2cd1527da10574cf636 Subproject 70e600346fb5875defe14d578883c9838695d53
diff --git a/custom/trivmix-service.nix b/custom/trivmix-service.nix
index 3c3cded7..e9120f88 100644
--- a/custom/trivmix-service.nix
+++ b/custom/trivmix-service.nix
@@ -3,43 +3,40 @@
3, connectOut ? null 3, connectOut ? null
4, connectIn ? null 4, connectIn ? null
5, group ? null 5, group ? null
6, initial ? null
6, trivmix 7, trivmix
7, stdenv 8, stdenv
8, makeWrapper 9, makeWrapper
9, jack2Full 10, jack2Full
10, coreutils 11, coreutils
12, writeScript
11}: 13}:
12 14
13let 15let
14 genRun = if ! isNull run then run else ( 16 connect = (! isNull connectOut) || (! isNull connectIn);
15 "${derivRun}/bin/run.sh" 17 connectScript = writeScript "connect" ''
16 ); 18 #!${stdenv.shell}
17 derivRun = stdenv.mkDerivation {
18 name = "trivmix-run";
19 src = builtins.toFile "run.sh" ''
20 #!/bin/sh
21 19
22 ${if ! isNull connectIn then "jack_connect ${connectIn} $1" else ""} 20 PATH=${jack2Full}/bin:$PATH
23 ${if ! isNull connectOut then "jack_connect $2 ${connectOut}" else ""} 21
24 ''; 22 ${optionalString (! isNull connectIn) "jack_connect ${connectIn} $1"}
25 unpackPhase = "cat"; 23 ${optionalString (! isNull connectOut) "jack_connect $2 ${connectOut}"}
26 buildInputs = [ makeWrapper ]; 24 '';
27 installPhase = '' 25 inherit (stdenv.lib) optionalString;
28 mkdir -p $out/bin 26in {
29 cp $src $out/bin/run.sh
30 chmod 755 $out/bin/run.sh
31 wrapProgram $out/bin/run.sh \
32 --prefix PATH : ${jack2Full}/bin
33 '';
34 };
35in rec {
36 out = { 27 out = {
37 wantedBy = [ "sound.target" ]; 28 wantedBy = [ "sound.target" ];
38 requires = [ "jack.service" ]; 29 requires = [ "jack.service" ];
39 before = [ "mpd.service" ]; 30 before = [ "mpd.service" ];
40 serviceConfig = { 31 serviceConfig = {
41 Type = "simple"; 32 Type = "simple";
42 ExecStart = ''${trivmix}/bin/trivmix --client ${name} --run ${genRun} /dev/shm/mix/${name}/level${if ! isNull group then " /dev/shm/mix/${group}/level" else ""}''; 33 ExecStart = ''${trivmix}/bin/trivmix --client ${name} \
34 ${optionalString connect "--run ${connectScript}"} \
35 ${optionalString (! isNull run) "--run ${run}"} \
36 ${optionalString (! isNull initial) "--level ${initial}"} \
37 /dev/shm/mix/${name}/level \
38 ${optionalString (! isNull group) "/dev/shm/mix/${group}/level"}
39 '';
43 User = "jack"; 40 User = "jack";
44 Group = "audio"; 41 Group = "audio";
45 Nice = "-10"; 42 Nice = "-10";
diff --git a/custom/trivmix.nix b/custom/trivmix.nix
deleted file mode 120000
index c2f64840..00000000
--- a/custom/trivmix.nix
+++ /dev/null
@@ -1 +0,0 @@
1trivmix/package.nix \ No newline at end of file
diff --git a/custom/uucp.nix b/custom/uucp.nix
index d7c2aae2..0b4b1306 100644
--- a/custom/uucp.nix
+++ b/custom/uucp.nix
@@ -208,7 +208,17 @@ in {
208 text = config.services.uucp.extraSys + "\n" + concatStringsSep "\n" (map sysSpec config.services.uucp.remoteNodes); 208 text = config.services.uucp.extraSys + "\n" + concatStringsSep "\n" (map sysSpec config.services.uucp.remoteNodes);
209 }; 209 };
210 210
211 security.setuidOwners = map (p: {program = p; owner = "root"; group = "root"; setuid = true; setgid = false;}) ["uucico" "uuxqt" "cu" "uucp" "uuname" "uustat" "uux"]; 211 security.wrappers = let
212 wrapper = p: { name = p;
213 value = {
214 source = "${pkgs.uucp}/bin/${p}";
215 owner = "root";
216 group = "root";
217 setuid = true;
218 setgid = false;
219 };
220 };
221 in listToAttrs (map wrapper ["uucico" "uuxqt" "cu" "uucp" "uuname" "uustat" "uux"]);
212 222
213 nixpkgs.config.packageOverrides = pkgs: with pkgs; { 223 nixpkgs.config.packageOverrides = pkgs: with pkgs; {
214 uucp = stdenv.lib.overrideDerivation uucp (oldAttrs: { 224 uucp = stdenv.lib.overrideDerivation uucp (oldAttrs: {
@@ -227,7 +237,7 @@ in {
227 choices as appropriate. */ 237 choices as appropriate. */
228 #if 1 238 #if 1
229 -#define MAIL_PROGRAM "/usr/lib/sendmail -t" 239 -#define MAIL_PROGRAM "/usr/lib/sendmail -t"
230 +#define MAIL_PROGRAM "/var/setuid-wrappers/sendmail -t" 240 +#define MAIL_PROGRAM "${config.security.wrapperDir}/sendmail -t"
231 /* #define MAIL_PROGRAM "/usr/sbin/sendmail -t" */ 241 /* #define MAIL_PROGRAM "/usr/sbin/sendmail -t" */
232 #define MAIL_PROGRAM_TO_BODY 1 242 #define MAIL_PROGRAM_TO_BODY 1
233 #define MAIL_PROGRAM_SUBJECT_BODY 1 243 #define MAIL_PROGRAM_SUBJECT_BODY 1
@@ -246,7 +256,7 @@ in {
246 *) from="$from@$relay";; 256 *) from="$from@$relay";;
247 esac 257 esac
248 258
249 exec /var/setuid-wrappers/sendmail -i -f "$from" -- "$@" 259 exec ${config.security.wrapperDir}/sendmail -G -i -f "$from" -- "$@"
250 ''; 260 '';
251 }; 261 };
252 262
@@ -254,6 +264,6 @@ in {
254 uucp 264 uucp
255 ]; 265 ];
256 266
257 services.cron.systemCronJobs = (map (name: "${config.services.uucp.interval} /var/setuid-wrappers/uucico -D -S ${name}") (if (config.services.uucp.interval != null) then config.services.uucp.remoteNodes else [])); 267 services.cron.systemCronJobs = (map (name: "${config.services.uucp.interval} ${config.security.wrapperDir}/uucico -D -S ${name}") (if (config.services.uucp.interval != null) then config.services.uucp.remoteNodes else []));
258 }; 268 };
259} 269}
diff --git a/customized/prosody.nix b/customized/prosody.nix
index a3445517..2a23b651 100644
--- a/customized/prosody.nix
+++ b/customized/prosody.nix
@@ -21,7 +21,7 @@ let
21 copyExtraModule = path: "n=0; for i in ${path}/*; do n=1; done; if [[ $n -gt 0 ]]; then cp -rv ${path}/* $out/lib/prosody/modules/; fi"; 21 copyExtraModule = path: "n=0; for i in ${path}/*; do n=1; done; if [[ $n -gt 0 ]]; then cp -rv ${path}/* $out/lib/prosody/modules/; fi";
22 luaPath = concatStringsSep ";" (map getLuaPath libs); 22 luaPath = concatStringsSep ";" (map getLuaPath libs);
23 luaCPath = concatStringsSep ";" (map getLuaCPath libs); 23 luaCPath = concatStringsSep ";" (map getLuaCPath libs);
24 copyModules = concatStringsSep ";" (map copyModule (communityModules ++ ["mod_websocket"])); 24 copyModules = concatStringsSep ";" (map copyModule communityModules);
25 copyExtraModules = concatStringsSep ";" (map copyExtraModule extraModules); 25 copyExtraModules = concatStringsSep ";" (map copyExtraModule extraModules);
26in 26in
27 27
@@ -35,9 +35,9 @@ stdenv.mkDerivation rec {
35 }; 35 };
36 36
37 communityModules = fetchhg { 37 communityModules = fetchhg {
38 url = "http://prosody-modules.googlecode.com/hg/"; 38 url = "https://hg.prosody.im/prosody-modules/";
39 rev = "4b55110b0aa8"; 39 rev = "5ca2470a7755";
40 sha256 = "0010x2rl9f9ihy2nwqan2jdlz25433srj2zna1xh10490mc28hij"; 40 sha256 = "06f3ndj15zhjwx8vjdyn73h3minw9wb37l9r753h6db56db2c0zl";
41 }; 41 };
42 42
43 buildInputs = [ lua5 luasocket luasec luaexpat luabitop libidn openssl makeWrapper ] 43 buildInputs = [ lua5 luasocket luasec luaexpat luabitop libidn openssl makeWrapper ]
diff --git a/hel.nix b/hel.nix
index 3753a8df..7a3a3af7 100644
--- a/hel.nix
+++ b/hel.nix
@@ -45,7 +45,6 @@
45 git 45 git
46 slock 46 slock
47 shadow 47 shadow
48 (callPackage ./custom/thinklight.nix { thinklight = "kbd_backlight"; })
49 (callPackage ./utils/nix/rebuild-system.nix {}) 48 (callPackage ./utils/nix/rebuild-system.nix {})
50 rewacom 49 rewacom
51 ]; 50 ];
@@ -58,7 +57,22 @@
58 ''; 57 '';
59 58
60 samsung-unified-linux-driver = pkgs.stdenv.lib.overrideDerivation pkgs.samsung-unified-linux-driver (oldAttrs: { 59 samsung-unified-linux-driver = pkgs.stdenv.lib.overrideDerivation pkgs.samsung-unified-linux-driver (oldAttrs: {
61 buildInputs = with pkgs; [cups]; 60 buildInputs = oldAttrs.buildInputs ++ [ pkgs.makeWrapper ];
61 builder = pkgs.writeScript "builder.sh" ''
62 #!${pkgs.stdenv.shell}
63
64 source ${pkgs.stdenv}/setup
65
66 ${oldAttrs.builder} ${pkgs.lib.concatStringsSep " " oldAttrs.args}
67
68 export PATH=${pkgs.makeWrapper}/bin:$PATH
69
70 echo "Wrapping samsung filters"
71 wrapProgram $out/lib/cups/filter/rastertosamsungspl \
72 --prefix PATH : ${pkgs.ghostscript}/bin
73 wrapProgram $out/lib/cups/filter/rastertosamsungsplc \
74 --prefix PATH : ${pkgs.ghostscript}/bin
75 '';
62 }); 76 });
63 }; 77 };
64 78
@@ -162,8 +176,8 @@
162 nodeName = "hel"; 176 nodeName = "hel";
163 remoteNodes = ["isaac" "ymir"]; # legacy name for odin 177 remoteNodes = ["isaac" "ymir"]; # legacy name for odin
164 sshUser = { 178 sshUser = {
165 openssh.authorizedKeys.keys = [ ''no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="/var/setuid-wrappers/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFH1QWdgoC03nzW5GBuCl2pqASHeIXIYtE9IInHdaKcO uucp@ymir'' 179 openssh.authorizedKeys.keys = [ ''no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFH1QWdgoC03nzW5GBuCl2pqASHeIXIYtE9IInHdaKcO uucp@ymir''
166 ''no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="${pkgs.writeScript "odin.sh" "#!${pkgs.stdenv.shell}\necho .\nexec -a uucico /var/setuid-wrappers/uucico\n"}" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJhACtnt9+3j2ev4QVA2QBlPtblPnu7yol2njgfMlHtC uucp@odin'' 180 ''no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="${pkgs.writeScript "odin.sh" "#!${pkgs.stdenv.shell}\necho .\nexec -a uucico ${config.security.wrapperDir}/uucico\n"}" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJhACtnt9+3j2ev4QVA2QBlPtblPnu7yol2njgfMlHtC uucp@odin''
167 ]; 181 ];
168 }; 182 };
169 sshConfig = '' 183 sshConfig = ''
@@ -174,7 +188,7 @@
174 Hostname ymir.niflheim.yggdrasil 188 Hostname ymir.niflheim.yggdrasil
175 IdentityFile ~/.ssh/ymir 189 IdentityFile ~/.ssh/ymir
176 ''; 190 '';
177 commandPath = [ "${pkgs.callPackage ./hel/recv-media.nix {}}/bin" "/var/setuid-wrappers/" ]; 191 commandPath = [ "${pkgs.callPackage ./hel/recv-media.nix {}}/bin" config.security.wrapperDir ];
178 defaultCommands = []; 192 defaultCommands = [];
179 commands = { 193 commands = {
180 "isaac" = ["recv-media" "notify-gkleen"]; 194 "isaac" = ["recv-media" "notify-gkleen"];
@@ -195,12 +209,17 @@
195 relayHost = "uucp:ymir"; 209 relayHost = "uucp:ymir";
196 recipientDelimiter = "+"; 210 recipientDelimiter = "+";
197 extraMasterConf = '' 211 extraMasterConf = ''
198 uucp unix - n n - - pipe flags=Fqhu user=uucp argv=/var/setuid-wrappers/uux -z -a $sender - $nexthop!rmail ($recipient) 212 uucp unix - n n - - pipe flags=Fqhu user=uucp argv=${config.security.wrapperDir}/uux -z -a $sender - $nexthop!rmail ($recipient)
199 sshsendmail unix - n n - - pipe flags=Fq user=postfix_ssh argv=${pkgs.openssh}/bin/ssh -F /var/db/postfix_ssh/ssh.config $nexthop sendmail -f $sender -G $recipient 213 sshsendmail unix - n n - - pipe flags=Fq user=postfix_ssh argv=${pkgs.openssh}/bin/ssh -F /var/db/postfix_ssh/ssh.config $nexthop sendmail -f $sender -G $recipient
200 ''; 214 '';
215 transport = ''
216 gkleen+sent@yggdrasil.li uucp:isaac
217 '';
201 extraConfig = '' 218 extraConfig = ''
202 default_transport = uucp:ymir 219 always_bcc = gkleen+sent@yggdrasil.li
203 220
221 default_transport = uucp:ymir
222
204 inet_interfaces = loopback-only 223 inet_interfaces = loopback-only
205 224
206 authorized_submit_users = !uucp, static:anyone 225 authorized_submit_users = !uucp, static:anyone
@@ -265,6 +284,34 @@
265 upower = { 284 upower = {
266 enable = true; 285 enable = true;
267 }; 286 };
287
288 locate = {
289 enable = true;
290 interval = "hourly";
291 locate = pkgs.mlocate;
292 localuser = null;
293 prunePaths = ["/tmp" "/var/tmp" "/var/cache" "/var/lock" "/var/run" "/var/spool"];
294 };
295
296 dbus = {
297 enable = true;
298 packages = [ (pkgs.writeTextFile {
299 name = "eavesdrop.conf";
300 text = ''
301 <!DOCTYPE busconfig PUBLIC
302 "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
303 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
304 <busconfig>
305 <policy user="root">
306 <allow eavesdrop="true"/>
307 <allow eavesdrop="true" send_destination="*"/>
308 </policy>
309 </busconfig>
310 '';
311 destination = "/etc/dbus-1/system.d/eavesdrop.conf";
312 })
313 ];
314 };
268 }; 315 };
269 316
270 users = { 317 users = {
@@ -304,17 +351,21 @@
304 %wheel ALL=(ALL) NOPASSWD: SYSCTRL 351 %wheel ALL=(ALL) NOPASSWD: SYSCTRL
305 ''; 352 '';
306 353
307 setuidPrograms = ["slock" "mount" "mount.nfs" "umount" "newgrp" "thinklight"]; 354 wrappers = { "slock".source = "${pkgs.slock}/bin/slock";
308 355 "mount".source = "${pkgs.utillinux.bin}/bin/mount";
309 setuidOwners = [ { group = "users"; 356 "umount".source = "${pkgs.utillinux.bin}/bin/umount";
310 owner = "gkleen"; 357 "newgrp".source = "${pkgs.shadow}/bin/newgrp";
311 permissions = "u+rx,g+x,o+x"; 358 "thinklight".source =
312 program = "notify-gkleen"; 359 "${(pkgs.callPackage ./custom/thinklight.nix { thinklight = "kbd_backlight"; })}/bin/thinklight";
313 setgid = true; 360 "notify-gkleen" = {
314 setuid = true; 361 group = "users";
315 source = ''${pkgs.callPackage ./custom/notify-user.nix { inherit (pkgs.haskellPackages) ghcWithPackages; }}/bin/notify-gkleen''; 362 owner = "gkleen";
316 } 363 setgid = true;
317 ]; 364 setuid = true;
365 permissions = "u+rx,g+x,o+x";
366 source = ''${pkgs.callPackage ./custom/notify-user.nix { inherit (pkgs.haskellPackages) ghcWithPackages; }}/bin/notify-gkleen'';
367 };
368 };
318 369
319 polkit = { 370 polkit = {
320 enable = true; 371 enable = true;
@@ -347,11 +398,11 @@
347 398
348 bluetooth.enable = true; 399 bluetooth.enable = true;
349 400
350 sane = { 401 # sane = {
351 enable = true; 402 # enable = true;
352 extraBackends = with pkgs; [ samsung-unified-linux-driver ]; 403 # extraBackends = with pkgs; [ samsung-unified-linux-driver ];
353 configDir = "/etc/sane.d"; 404 # configDir = "/etc/sane.d";
354 }; 405 # };
355 }; 406 };
356 407
357 sound.enable = true; 408 sound.enable = true;
@@ -374,6 +425,13 @@
374 environment.etc."sane.d/dll.conf".text = "xerox_mfp"; 425 environment.etc."sane.d/dll.conf".text = "xerox_mfp";
375 environment.etc."sane.d/xerox_mfp.conf".text = "tcp printer.asgard.yggdrasil"; 426 environment.etc."sane.d/xerox_mfp.conf".text = "tcp printer.asgard.yggdrasil";
376 427
428 environment.sessionVariables = {
429 "SANE_CONFIG_DIR" = "/etc/sane.d";
430 "TPRINT_BASEURL" = "http://bragi.asgard.yggdrasil/thermoprint/api";
431 "MPD_HOST" = "bragi.asgard.yggdrasil";
432 "MPD_PORT" = "6600";
433 };
434
377 systemd.services."kill-user@" = { 435 systemd.services."kill-user@" = {
378 serviceConfig = { 436 serviceConfig = {
379 Type = "oneshot"; 437 Type = "oneshot";
diff --git a/hel/recv-media.nix b/hel/recv-media.nix
index 52d5bae6..a074e76b 100644
--- a/hel/recv-media.nix
+++ b/hel/recv-media.nix
@@ -6,6 +6,7 @@
6, showTitle ? true 6, showTitle ? true
7, ffmpeg ? null 7, ffmpeg ? null
8, gnused ? null 8, gnused ? null
9, wrapperDir ? "/run/wrappers/bin"
9}: 10}:
10 11
11assert showTitle -> ffmpeg != null && gnused != null && notifyUser != null; 12assert showTitle -> ffmpeg != null && gnused != null && notifyUser != null;
@@ -15,7 +16,7 @@ writeScriptBin "recv-media" ''
15 16
16 pid=$? 17 pid=$?
17 18
18 PATH=${eject}/bin:${coreutils}/bin:${if showTitle then ''${ffmpeg}/bin:${gnused}/bin:'' else ""}/var/setuid-wrappers 19 PATH=${eject}/bin:${coreutils}/bin:${if showTitle then ''${ffmpeg}/bin:${gnused}/bin:'' else ""}${wrapperDir}
19 20
20 exec 1> >(logger --id=$pid -t recv-media -p user.notice) 21 exec 1> >(logger --id=$pid -t recv-media -p user.notice)
21 exec 2> >(logger --id=$pid -t recv-media -p user.error) 22 exec 2> >(logger --id=$pid -t recv-media -p user.error)
diff --git a/musnix b/musnix
Subproject a933288d481af2432861015ffff9800d22f4bd7 Subproject f50fd6646706815285c6b51eb3a11d2561b84bc
diff --git a/users.nix b/users.nix
index 9772535a..cdfbd51b 100644
--- a/users.nix
+++ b/users.nix
@@ -7,6 +7,7 @@ let
7 extraUsers = { 7 extraUsers = {
8 ymir = { 8 ymir = {
9 "mherold" = import ./users/mherold.nix; 9 "mherold" = import ./users/mherold.nix;
10 "some" = import ./users/some.nix;
10 "llovisa" = import ./users/llovisa.nix; 11 "llovisa" = import ./users/llovisa.nix;
11 "vkleen" = import ./users/vkleen.nix; 12 "vkleen" = import ./users/vkleen.nix;
12 "tkleen" = import ./users/tkleen.nix; 13 "tkleen" = import ./users/tkleen.nix;
diff --git a/users/gkleen@ymir.nix b/users/gkleen@ymir.nix
index 79a121fc..72d4c30c 100644
--- a/users/gkleen@ymir.nix
+++ b/users/gkleen@ymir.nix
@@ -1,4 +1,5 @@
1{ 1{
2 packageOverrides = pkgs: rec { 2 packageOverrides = pkgs: rec {
3 infinoted = pkgs.libinfinity.override { daemon = true; };
3 } // (import ../utils/nix/default.nix) {}; 4 } // (import ../utils/nix/default.nix) {};
4} 5}
diff --git a/users/mherold.nix b/users/mherold.nix
index 209dbadc..4a35d2b9 100644
--- a/users/mherold.nix
+++ b/users/mherold.nix
@@ -3,6 +3,6 @@
3 description = "Magdalena Herold"; 3 description = "Magdalena Herold";
4 extraGroups = ["xmpp" "mail"]; 4 extraGroups = ["xmpp" "mail"];
5 group = "users"; 5 group = "users";
6 hashedPassword = "$6$rounds=500000$MUhLTEEvBI$NJ1l17WtRpDJGCWzVPfbjxCcx4G/yKSIbYXDMX3D.q3Go6nyWjl6.kF.D5O8.72eTDlbhkJIWF4fkMrs0MQt10"; 6 hashedPassword = "$6$rounds=500000$y5qNae9r/U/7$HbSrmPcrPl9OQvRFMeo8PDYar32Y1i/C1R5di82rN4PPQZYxg/W.anHSI5Xws6fOQmDtvGsT0lCe4NFNxuTF41";
7 isNormalUser = true; 7 isNormalUser = true;
8} 8}
diff --git a/users/some.nix b/users/some.nix
new file mode 100644
index 00000000..505b3abd
--- /dev/null
+++ b/users/some.nix
@@ -0,0 +1,8 @@
1{
2 name = "some";
3 description = "SomeNights";
4 extraGroups = ["xmpp" "mail"];
5 group = "users";
6 hashedPassword = "$6$rounds=500000$ZOKcPFUxFCCxbS$PSjgCpHs5GfmmusjTVEBY89NFS.hvY21.iuscfiXW8R.B2UW6ScyrIWWWPJkL4ZfI.6pKwXuf01gxazmDjy251";
7 isNormalUser = true;
8}
diff --git a/utils b/utils
Subproject 6b443335b97cc2d6479595313e5a19d2f49c6b7 Subproject 8b11946e67c5aee3e3dff1fc1b8754249b4677c
diff --git a/ymir.nix b/ymir.nix
index 424ca265..74eb1a39 100644
--- a/ymir.nix
+++ b/ymir.nix
@@ -15,10 +15,11 @@ let
15 }; 15 };
16 myDomains = ["dirty-haskell.org" "www.dirty-haskell.org" "lists.dirty-haskell.org" "l.dirty-haskell.org" 16 myDomains = ["dirty-haskell.org" "www.dirty-haskell.org" "lists.dirty-haskell.org" "l.dirty-haskell.org"
17 "files.141.li" "f.141.li" "ymir.141.li" "141.li" "www.141.li" "lists.141.li" "l.141.li" 17 "files.141.li" "f.141.li" "ymir.141.li" "141.li" "www.141.li" "lists.141.li" "l.141.li"
18 "files.lmu.li" "f.lmu.li" "ymir.lmu.li" "lmu.li" "www.lmu.li" "lists.lmu.li" "l.lmu.li"
19 "ymir.xmpp.li" "xmpp.li" "www.xmpp.li" "lists.xmpp.li" "l.xmpp.li" 18 "ymir.xmpp.li" "xmpp.li" "www.xmpp.li" "lists.xmpp.li" "l.xmpp.li"
20 "files.yggdrasil.li" "f.yggdrasil.li" "ymir.yggdrasil.li" "git.yggdrasil.li" "www.yggdrasil.li" "yggdrasil.li" "lists.yggdrasil.li" "l.yggdrasil.li" 19 "files.yggdrasil.li" "f.yggdrasil.li" "ymir.yggdrasil.li" "git.yggdrasil.li" "www.yggdrasil.li" "yggdrasil.li" "lists.yggdrasil.li" "l.yggdrasil.li"
21 "files.praseodym.org" "f.praseodym.org" "ymir.praseodym.org" "praseodym.org" "www.praseodym.org" "lists.praseodym.org" "l.praseodym.org" 20 "files.praseodym.org" "f.praseodym.org" "ymir.praseodym.org" "praseodym.org" "www.praseodym.org" "lists.praseodym.org" "l.praseodym.org"
21 "ymir.kleen.li" "kleen.li" "www.kleen.li"
22 "ymir.nights.email" "nights.email" "www.nights.email"
22 ]; 23 ];
23in rec { 24in rec {
24 imports = 25 imports =
@@ -47,12 +48,14 @@ in rec {
47 nixpkgs.config.packageOverrides = pkgs: 48 nixpkgs.config.packageOverrides = pkgs:
48 rec { 49 rec {
49 prosody = pkgs.callPackage ./customized/prosody.nix ({ 50 prosody = pkgs.callPackage ./customized/prosody.nix ({
50 inherit (pkgs.lua51Packages) luasocket luasec luaexpat luafilesystem luabitop luaevent luazlib; 51 inherit (pkgs.lua51Packages) luasocket luaexpat luafilesystem luabitop luaevent luazlib;
52 luasec = lua5_sec;
51 lua5 = pkgs.lua5_1; 53 lua5 = pkgs.lua5_1;
52 communityModules = ["mod_carbons" "mod_reload_modules"]; 54 communityModules = ["mod_carbons" "mod_reload_modules" "mod_csi" "mod_cloud_notify" "mod_csi_pump" "mod_smacks" "mod_track_muc_joins"];
53 extraModules = [prosodyAuth]; 55 extraModules = [prosodyAuth];
54 extraLibs = [luaPam luaPosix luaSha2]; 56 extraLibs = [luaPam luaPosix luaSha2];
55 }); 57 });
58 lua5_sec = pkgs.lua5_sec.override { lua5 = pkgs.lua5_1; };
56 uwsgi = pkgs.callPackage ./customized/uwsgi.nix { 59 uwsgi = pkgs.callPackage ./customized/uwsgi.nix {
57 extraPlugins = { 60 extraPlugins = {
58 cgi = { 61 cgi = {
@@ -144,6 +147,7 @@ in rec {
144 9418 # git 147 9418 # git
145 64738 # murmur 148 64738 # murmur
146 53 # DNS 149 53 # DNS
150 6523 # Obby
147 ]; 151 ];
148 allowedUDPPorts = [ 64738 # murmur 152 allowedUDPPorts = [ 64738 # murmur
149 53 # DNS 153 53 # DNS
@@ -199,6 +203,7 @@ in rec {
199 "nginx" 203 "nginx"
200 "postfix" 204 "postfix"
201 "murmur" 205 "murmur"
206 "infinoted"
202 ]; 207 ];
203 }; 208 };
204 209
@@ -219,6 +224,10 @@ in rec {
219 "auth_custom" 224 "auth_custom"
220 "carbons" 225 "carbons"
221 "reload_modules" 226 "reload_modules"
227 "smacks"
228 "csi"
229 "csi_pump"
230 "cloud_notify"
222 ]; 231 ];
223 extraConfig = '' 232 extraConfig = ''
224 reload_modules = { "group", "tls" } 233 reload_modules = { "group", "tls" }
@@ -236,7 +245,7 @@ in rec {
236 ''; 245 '';
237 246
238 virtualHosts = builtins.listToAttrs (map (name: { inherit name; value = prosodyVirtHost name; }) 247 virtualHosts = builtins.listToAttrs (map (name: { inherit name; value = prosodyVirtHost name; })
239 ["xmpp.li" "yggdrasil.li" "praseodym.org" "141.li"]); 248 ["xmpp.li" "yggdrasil.li" "praseodym.org" "141.li" "nights.email"]);
240 }; 249 };
241 security.pam.services."xmpp".text = '' 250 security.pam.services."xmpp".text = ''
242 auth requisite pam_succeed_if.so user ingroup xmpp 251 auth requisite pam_succeed_if.so user ingroup xmpp
@@ -348,6 +357,7 @@ in rec {
348 postmasterAlias = ""; rootAlias = ""; extraAliases = ""; 357 postmasterAlias = ""; rootAlias = ""; extraAliases = "";
349 virtual = '' 358 virtual = ''
350 blog@dirty-haskell.org dirty-haskell@lists.yggdrasil.li 359 blog@dirty-haskell.org dirty-haskell@lists.yggdrasil.li
360 @nights.email some@nights.email
351 ''; 361 '';
352 #destination = ["yggdrasil.li" "ymir.yggdrasil.li" "praseodym.org" "ymir.praseodym.org" "141.li" "ymir.141.li" "xmpp.li" "ymir.xmpp.li" "dirty-haskell.org" "explainuxul.de" "www.explainuxul.de" "lmu.li" "www.lmu.li" "localhost.yggdrasil.li" "localhost"]; 362 #destination = ["yggdrasil.li" "ymir.yggdrasil.li" "praseodym.org" "ymir.praseodym.org" "141.li" "ymir.141.li" "xmpp.li" "ymir.xmpp.li" "dirty-haskell.org" "explainuxul.de" "www.explainuxul.de" "lmu.li" "www.lmu.li" "localhost.yggdrasil.li" "localhost"];
353 destination = [''regexp:${pkgs.writeText "destination" '' 363 destination = [''regexp:${pkgs.writeText "destination" ''
@@ -355,8 +365,9 @@ in rec {
355 /\.?praseodym\.org$/ ACCEPT 365 /\.?praseodym\.org$/ ACCEPT
356 /\.?141\.li$/ ACCEPT 366 /\.?141\.li$/ ACCEPT
357 /\.?xmpp\.li$/ ACCEPT 367 /\.?xmpp\.li$/ ACCEPT
368 /\.?kleen\.li$/ ACCEPT
358 /\.?dirty-haskell\.org$/ ACCEPT 369 /\.?dirty-haskell\.org$/ ACCEPT
359 /\.?lmu\.li$/ ACCEPT 370 /\.?nights\.email$/ ACCEPT
360 /\.?yggdrasil$/ ACCEPT 371 /\.?yggdrasil$/ ACCEPT
361 /\.?localdomain$/ ACCEPT 372 /\.?localdomain$/ ACCEPT
362 /^localhost$/ ACCEPT 373 /^localhost$/ ACCEPT
@@ -396,6 +407,8 @@ in rec {
396 /@subs?\.(lists?|l)\./ mlmmj-subs: 407 /@subs?\.(lists?|l)\./ mlmmj-subs:
397 ''} regexp:/srv/mail/transport pipemap:{texthash:/srv/mail/discard,static:{discard:}} 408 ''} regexp:/srv/mail/transport pipemap:{texthash:/srv/mail/discard,static:{discard:}}
398 409
410 local_recipient_maps =
411
399 luser_relay = gkleen+''${local} 412 luser_relay = gkleen+''${local}
400 413
401 # 10 GiB 414 # 10 GiB
@@ -426,7 +439,6 @@ in rec {
426 permit_sasl_authenticated, 439 permit_sasl_authenticated,
427 reject_non_fqdn_helo_hostname, 440 reject_non_fqdn_helo_hostname,
428 reject_invalid_helo_hostname, 441 reject_invalid_helo_hostname,
429 reject_unknown_reverse_client_hostname,
430 reject_unauth_destination, 442 reject_unauth_destination,
431 check_client_access regexp:${pkgs.writeText "spfpolicy" '' 443 check_client_access regexp:${pkgs.writeText "spfpolicy" ''
432 /(^|\.)tu-muenchen\.de$/ DUNNO 444 /(^|\.)tu-muenchen\.de$/ DUNNO
@@ -463,6 +475,16 @@ in rec {
463 475
464 alias_maps = texthash:${pkgs.writeText "aliases" '' 476 alias_maps = texthash:${pkgs.writeText "aliases" ''
465 postmaster gkleen 477 postmaster gkleen
478 webmaster gkleen
479 abuse gkleen
480 noc gkleen
481 security gkleen
482 hostmaster gkleen
483 usenet gkleen
484 news gkleen
485 www gkleen
486 uucp gkleen
487 ftp gkleen
466 root gkleen 488 root gkleen
467 ''} texthash:/srv/mail/spm 489 ''} texthash:/srv/mail/spm
468 490
@@ -478,10 +500,23 @@ in rec {
478 recipient_canonical_classes= envelope_recipient,header_recipient 500 recipient_canonical_classes= envelope_recipient,header_recipient
479 ''; 501 '';
480 extraMasterConf = '' 502 extraMasterConf = ''
481 uucp unix - n n - - pipe flags=Fqhu user=uucp argv=/var/setuid-wrappers/uux -z -a $sender - $nexthop!rmail ($recipient) 503 uucp unix - n n - - pipe flags=Fqhu user=uucp argv=${config.security.wrapperDir}/uux -z -a $sender - $nexthop!rmail ($recipient)
482 mlmmj unix - n n - - pipe flags=ORhu user=mlmmj argv=${pkgs.mlmmj}/bin/mlmmj-receive -F -L /var/spool/lists/''${user} 504 mlmmj unix - n n - - pipe flags=ORhu user=mlmmj argv=${pkgs.mlmmj}/bin/mlmmj-receive -F -L /var/spool/lists/''${user}
483 mlmmj-subs unix - n n - - pipe flags=ORhu user=mlmmj argv=${pkgs.mlmmj-exposed}/bin/mlmmj-exposed /var/spool/lists/''${user} ''${extension} 505 mlmmj-subs unix - n n - - pipe flags=ORhu user=mlmmj argv=${pkgs.mlmmj-exposed}/bin/mlmmj-exposed /var/spool/lists/''${user} ''${extension}
484 policy-spf unix - n n - - spawn user=nobody argv=${pkgs.pythonPackages.pypolicyd-spf}/bin/policyd-spf ${./ymir/spf.conf} 506 policy-spf unix - n n - - spawn user=nobody argv=${pkgs.pythonPackages.pypolicyd-spf}/bin/policyd-spf ${./ymir/spf.conf}
507 logEmail unix - n n - 10 pipe flags=Rq user=nobody null_sender= argv=${pkgs.writeScript "logEmail" ''
508 #!${pkgs.stdenv.shell}
509
510 export PATH=${config.security.wrapperDir}:/run/current-system/sw/bin
511
512 mailFile=/tmp/logEmail/$(date +"%F-%H%M%S").$$
513
514 mkdir -p -m 700 /tmp/logEmail
515
516 cat >$mailFile
517
518 sendmail -G -i "$@" <$mailFile
519 ''} -f ''${sender} -- ''${recipient}
485 ''; 520 '';
486 networks = ["127.0.0.0/8" "[::ffff:127.0.0.0]/104" "[::1]/128" "10.141.0.0/16"]; 521 networks = ["127.0.0.0/8" "[::ffff:127.0.0.0]/104" "[::1]/128" "10.141.0.0/16"];
487 }; 522 };
@@ -494,6 +529,8 @@ in rec {
494 ".praseodym.org" "praseodym.org" 529 ".praseodym.org" "praseodym.org"
495 ".141.li" "141.li" 530 ".141.li" "141.li"
496 ".xmpp.li" "xmpp.li" 531 ".xmpp.li" "xmpp.li"
532 ".kleen.li" "kleen.li"
533 ".nights.email" "nights.email"
497 ".lmu.li" "lmu.li" 534 ".lmu.li" "lmu.li"
498 ".dirty-haskell.org" "dirty-haskell.org" 535 ".dirty-haskell.org" "dirty-haskell.org"
499 ]; 536 ];
@@ -527,11 +564,23 @@ in rec {
527 selector = "ymir"; 564 selector = "ymir";
528 configFile = builtins.toFile "opendkim.conf" '' 565 configFile = builtins.toFile "opendkim.conf" ''
529 Syslog true 566 Syslog true
530 MTACommand /var/setuid-wrappers/sendmail 567 MTACommand ${config.security.wrapperDir}/sendmail
531 LogResults true 568 LogResults true
532 ''; 569 '';
533 }; 570 };
534 571
572 services.postgrey = {
573 enable = true;
574 socket = {
575 path = "/var/lib/postfix/queue/private/policy-greylist";
576 mode = "0777";
577 };
578 delay = 60;
579 autoWhitelist = 1;
580 maxAge = 7;
581 retryWindow = 1;
582 };
583
535 services.dovecot2 = { 584 services.dovecot2 = {
536 enable = true; 585 enable = true;
537 enableImap = true; 586 enableImap = true;
@@ -606,6 +655,35 @@ in rec {
606 655
607 users.extraGroups."mlmmj" = {}; 656 users.extraGroups."mlmmj" = {};
608 657
658 users.extraGroups."mladmin" = {
659 members = [ "gkleen" ];
660 };
661
662 users.extraGroups."infinoted" = {
663 members = [ "infinoted" "gitolite" ];
664 };
665
666 security.sudo.extraConfig = ''
667 %mladmin ALL=(mlmmj) NOPASSWD: ALL
668 %infinoted ALL=(infinoted) NOPASSWD: ALL
669 '';
670
671 security.polkit = {
672 enable = true;
673 extraConfig = ''
674 polkit.addRule(function(action, subject) {
675 if ( action.id == "org.freedesktop.systemd1.manage-units"
676 && action.lookup("unit") == "infinoted.service"
677 && subject.isInGroup("infinoted")
678 ) {
679 return polkit.Result.YES;
680 }
681 });
682 '';
683 };
684
685 security.wrappers = { "newgrp".source = "${pkgs.shadow}/bin/newgrp"; };
686
609 security.acme = { 687 security.acme = {
610 certs = { 688 certs = {
611 "yggdrasil.li" = { 689 "yggdrasil.li" = {
@@ -616,7 +694,7 @@ in rec {
616 extraDomains = builtins.listToAttrs (builtins.map (name: { inherit name; value = "/srv/www/acme/${name}"; }) myDomains); 694 extraDomains = builtins.listToAttrs (builtins.map (name: { inherit name; value = "/srv/www/acme/${name}"; }) myDomains);
617 postRun = '' 695 postRun = ''
618 systemctl reload nginx.service 696 systemctl reload nginx.service
619 prosodyctl reload 697 ${pkgs.prosody}/bin/prosodyctl reload
620 ''; 698 '';
621 }; 699 };
622 }; 700 };
@@ -627,8 +705,8 @@ in rec {
627 nodeName = "ymir"; 705 nodeName = "ymir";
628 remoteNodes = ["isaac" "hel"]; # legacy name for odin 706 remoteNodes = ["isaac" "hel"]; # legacy name for odin
629 sshUser = { 707 sshUser = {
630 openssh.authorizedKeys.keys = [ ''no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="/var/setuid-wrappers/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEgtDHA7oDIaRwggGGznNaKZF68rFTziqefSCn1t9ZKe uucp@odin'' 708 openssh.authorizedKeys.keys = [ ''no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEgtDHA7oDIaRwggGGznNaKZF68rFTziqefSCn1t9ZKe uucp@odin''
631 ''no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="/var/setuid-wrappers/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWBybBQKbPucqBgULQ1phv7IKFWl1Xc4drkCx3D5mIz uucp@hel'' 709 ''no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWBybBQKbPucqBgULQ1phv7IKFWl1Xc4drkCx3D5mIz uucp@hel''
632 ]; 710 ];
633 }; 711 };
634 sshConfig = '' 712 sshConfig = ''
@@ -694,4 +772,34 @@ in rec {
694 forward-addr: 10.141.1.1 772 forward-addr: 10.141.1.1
695 ''; 773 '';
696 }; 774 };
775
776 services.infinoted = {
777 enable = true;
778 keyFile = "/var/lib/acme/yggdrasil.li/key.pem";
779 certificateFile = "/var/lib/acme/yggdrasil.li/fullchain.pem";
780 plugins = [ "note-text" "note-chat" "logging" "autosave" "certificate-auth" "directory-sync" ];
781 extraConfig = ''
782 [certificate-auth]
783 ca-list=/var/lib/infinoted/ca.cert.pem
784 ca-key=/var/lib/infinoted/ca.key.pem
785 accept-unauthenticated-clients=true
786
787 [autosave]
788 interval=5
789
790 [directory-sync]
791 directory=/var/lib/infinoted/dirsync
792 interval=5
793 hook=/var/lib/infinoted/git-sync.sh
794 '';
795 };
796
797 users.extraUsers."infinoted" = {
798 home = "/var/lib/infinoted";
799 createHome = true;
800 };
801
802 services.haveged = {
803 enable = true;
804 };
697} 805}
diff --git a/ymir/mlmmj-expose.hs b/ymir/mlmmj-expose.hs
new file mode 100644
index 00000000..f074659b
--- /dev/null
+++ b/ymir/mlmmj-expose.hs
@@ -0,0 +1,182 @@
1{-# LANGUAGE ViewPatterns, RecordWildCards, OverloadedStrings #-}
2
3import System.IO
4import System.IO.Error
5import System.FilePath
6import System.Environment
7import System.Exit
8import System.Directory
9import System.Process
10import Text.Printf
11
12import Data.Char
13
14import Control.Monad
15
16import Crypto.Hash
17
18import qualified Data.ByteString.Lazy as LBS
19import qualified Data.ByteString.Char8 as CBS
20
21import qualified Data.UUID as UUID (toString)
22import qualified Data.UUID.V4 as UUID (nextRandom)
23
24import Data.Aeson
25import Data.Aeson.Encode.Pretty
26
27import Data.Set (Set)
28import qualified Data.Set as Set
29
30newtype FoxReplace = FoxReplace (Set FoxReplaceGroup)
31 deriving (Ord, Eq, Show)
32
33data FoxReplaceGroup = FoxReplaceGroup
34 { groupName :: String
35 , groupUrls :: Set String
36 , groupSubs :: Set FoxReplaceSub
37 , groupHtmlMode :: FoxReplaceHTML
38 }
39 deriving (Ord, Eq, Show)
40
41data FoxReplaceHTML = NoHTML | OutputOnlyHTML | BothHTML
42 deriving (Ord, Eq, Enum, Show)
43
44data FoxReplaceSub = FoxReplaceSub
45 { rInput, rOutput :: String
46 , rInputType :: SubInput
47 , rCaseSensitive :: Bool
48 }
49 deriving (Ord, Eq, Show)
50
51data SubInput = TextInput | WordInput | RegexpInput
52 deriving (Ord, Eq, Enum, Show)
53
54
55instance ToJSON FoxReplace where
56 toJSON (FoxReplace groupSet) = object
57 [ "version" .= ("0.15" :: String)
58 , "groups" .= groupSet
59 ]
60
61instance ToJSON FoxReplaceGroup where
62 toJSON FoxReplaceGroup{..} = object
63 [ "name" .= groupName
64 , "html" .= groupHtmlMode
65 , "enabled" .= True
66 , "urls" .= groupUrls
67 , "substitutions" .= groupSubs
68 ]
69
70instance ToJSON FoxReplaceHTML where
71 toJSON NoHTML = String "none"
72 toJSON OutputOnlyHTML = String "output"
73 toJSON BothHTML = String "inputoutput"
74
75instance ToJSON FoxReplaceSub where
76 toJSON FoxReplaceSub{..} = object
77 [ "input" .= rInput
78 , "output" .= rOutput
79 , "inputType" .= rInputType
80 , "caseSensitive" .= rCaseSensitive
81 ]
82
83instance ToJSON SubInput where
84 toJSON TextInput = String "text"
85 toJSON WordInput = String "wholewords"
86 toJSON RegexpInput = String "regexp"
87
88
89main :: IO ()
90main = do
91 progName <- takeFileName <$> getProgName
92 case progName of
93 "mlmmj-exposed" -> do
94 args <- getArgs
95 case args of
96 [listDir, (map toLower -> extension)] -> do
97 setCurrentDirectory listDir
98 identities <- getIdentities
99 subscribers <- getSubscribers
100 let hashes = filter ((==) extension . snd) [((ident, sub), hash' (ident, sub)) | ident <- identities, sub <- subscribers]
101 case hashes of
102 [((_, recipient), _)] -> do
103 uuid <- UUID.nextRandom
104 let fName = "queue" </> "exposed" <.> uuidTrans uuid
105 uuidTrans = uuidTrans' . UUID.toString
106 where
107 uuidTrans' [] = []
108 uuidTrans' ('-':xs) = uuidTrans' xs
109 uuidTrans' (x:xs) = x : uuidTrans' xs
110 getContents >>= writeFile fName
111 hPrintf stdout "Forwarding mail to <%s>, subscribed to %s\n" recipient (takeBaseName listDir)
112 callProcess "@mlmmj@/bin/mlmmj-send" ["-L", listDir, "-l", "6", "-m", fName, "-T", recipient]
113 removeFile fName
114 [] -> die "Unknown extension"
115 _ -> die "Ambiguous extension"
116 _ -> hPutStrLn stderr ("Called without expected arguments (<listDirectory> <recipientExtension>)") >> exitWith (ExitFailure 2)
117 "mlmmj-expose" -> do
118 args <- getArgs
119 case args of
120 [listDir, (map toLower -> ident)] -> do
121 setCurrentDirectory listDir
122 identities <- getIdentities
123 case ident `elem` identities of
124 True -> putStrLn "Identity is already known"
125 False -> writeFile "exposed.ids" . unlines $ ident : identities
126 _ -> hPutStrLn stderr ("Called without expected arguments (<listDirectory> <senderIdentity>)") >> exitWith (ExitFailure 2)
127 "mlmmj-get-exposed" -> do
128 args <- getArgs
129 case args of
130 [(dropTrailingPathSeparator -> listDir), (map toLower -> ident)] -> do
131 setCurrentDirectory listDir
132 identities <- getIdentities
133 unless (ident `elem` identities) . die $ "Unknown sender: ‘" ++ ident ++ "’"
134 mapM_ (\sub -> putStrLn $ sub ++ " " ++ takeFileName listDir ++ "+" ++ hash' (ident, sub) ++ "@subs.lists.yggdrasil.li") =<< getSubscribers
135 (dropTrailingPathSeparator -> listDir) : (map toLower -> ident) : (map (map toLower) -> recipients) -> do
136 setCurrentDirectory listDir
137 identities <- getIdentities
138 unless (ident `elem` identities) . die $ "Unknown sender: ‘" ++ ident ++ "’"
139 subscribers <- getSubscribers
140 forM_ recipients $ \recipient -> do
141 unless (recipient `elem` subscribers) . die $ "Unknown recipient: ‘" ++ recipient ++ "’";
142 putStrLn $ takeFileName listDir ++ "+" ++ hash' (ident, recipient) ++ "@subs.lists.yggdrasil.li";
143 _ -> hPutStrLn stderr ("Called without expected arguments (<listDirectory> <senderIdentity> [<recipient> [...]])") >> exitWith (ExitFailure 2)
144 "mlmmj-serve-exposed" -> do
145 args <- getArgs
146 case args of
147 [(dropTrailingPathSeparator -> listDir)] -> do
148 setCurrentDirectory listDir
149 subscribers <- getSubscribers
150 identities <- getIdentities
151
152 let
153 listName = takeBaseName listDir
154 replaceGroup ident = FoxReplaceGroup { groupName = ident ++ "." ++ listName
155 , groupHtmlMode = NoHTML
156 , groupUrls = Set.empty
157 , groupSubs = Set.fromList $ map (replaceSub ident) subscribers
158 }
159 replaceSub ident sub = FoxReplaceSub { rInput = listName ++ "\\+" ++ hash' (ident, sub) ++ "(@subs\\.lists\\.yggdrasil\\.li)?"
160 , rOutput = sub
161 , rInputType = RegexpInput
162 , rCaseSensitive = True
163 }
164
165 LBS.putStr . encodePretty . FoxReplace . Set.fromList $ map replaceGroup identities
166 putChar '\n'
167 _ -> hPutStrLn stderr "Called without expected arguments (<listDirectory>)" >> exitWith (ExitFailure 2)
168 _ -> hPutStrLn stderr ("Called under unsupported name ‘" ++ progName ++ "’") >> exitWith (ExitFailure 2)
169
170getIdentities :: IO [String]
171getIdentities = (filter (not . null) . lines <$> readFile "exposed.ids") `catchIOError` (\e -> if isDoesNotExistError e then return [] else ioError e)
172
173getSubscribers :: IO [String]
174getSubscribers = map (map toLower) . concat <$> mapM (flip catchIOError (\e -> if isDoesNotExistError e then return [] else ioError e) . readDir) ["subscribers.d", "digesters.d"]
175 where
176 readDir dir = concat <$> (mapM (fmap lines . readFile) . map (dir </>) . filter (not . (`elem` [".", ".."]))=<< (getDirectoryContents dir))
177
178hash' :: Show a => a -> String
179hash' = take len . map toLower . show . (hash :: CBS.ByteString -> Digest SHA256) . CBS.pack . map toLower . show
180
181len :: Int
182len = 32
diff --git a/ymir/mlmmj-expose.nix b/ymir/mlmmj-expose.nix
index 0873b0f7..b3f7499c 100644
--- a/ymir/mlmmj-expose.nix
+++ b/ymir/mlmmj-expose.nix
@@ -1,105 +1,27 @@
1{ config, pkgs, ... }: 1{ config, pkgs, ... }:
2 2
3let 3let
4 haskellEnv = pkgs.haskellPackages.ghcWithPackages (pkgs: with pkgs; [ filepath directory cryptonite bytestring uuid ]); 4 haskellEnv = pkgs.haskellPackages.ghcWithPackages dependencies;
5 dependencies = pkgs: with pkgs; [ filepath
6 directory
7 cryptonite
8 bytestring
9 uuid
10 aeson
11 aeson-pretty
12 ];
5 mlmmj-exposed = pkgs.stdenv.mkDerivation { 13 mlmmj-exposed = pkgs.stdenv.mkDerivation {
6 name = "mlmmj-exposed"; 14 name = "mlmmj-expose";
7 src = pkgs.writeText "mlmmj-exposed.hs" '' 15 src = pkgs.substituteAll {
8 {-# LANGUAGE ViewPatterns #-} 16 src = ./mlmmj-expose.hs;
9 17 inherit (pkgs) mlmmj;
10 import System.IO 18 };
11 import System.IO.Error
12 import System.FilePath
13 import System.Environment
14 import System.Exit
15 import System.Directory
16 import System.Process
17 import Text.Printf
18
19 import Data.Char
20
21 import Control.Monad
22
23 import Crypto.Hash
24
25 import qualified Data.ByteString.Lazy as LBS
26 import qualified Data.ByteString.Char8 as CBS
27
28 import qualified Data.UUID as UUID (toString)
29 import qualified Data.UUID.V4 as UUID (nextRandom)
30
31 main :: IO ()
32 main = do
33 progName <- takeFileName <$> getProgName
34 case progName of
35 "mlmmj-exposed" -> do
36 args <- getArgs
37 case args of
38 [listDir, (map toLower -> extension)] -> do
39 setCurrentDirectory listDir
40 identities <- getIdentities
41 subscribers <- getSubscribers
42 let hashes = filter ((==) extension . snd) [((ident, sub), hash' (ident, sub)) | ident <- identities, sub <- subscribers]
43 case hashes of
44 [((_, recipient), _)] -> do
45 uuid <- UUID.nextRandom
46 let fName = "queue" </> "exposed" <.> uuidTrans uuid
47 uuidTrans = uuidTrans' . UUID.toString
48 where
49 uuidTrans' [] = []
50 uuidTrans' ('-':xs) = uuidTrans' xs
51 uuidTrans' (x:xs) = x : uuidTrans' xs
52 getContents >>= writeFile fName
53 hPrintf stdout "Forwarding mail to <%s>, subscribed to %s\n" recipient (takeBaseName listDir)
54 callProcess "${pkgs.mlmmj}/bin/mlmmj-send" ["-L", listDir, "-l", "6", "-m", fName, "-T", recipient]
55 removeFile fName
56 [] -> die "Unknown extension"
57 _ -> die "Ambiguous extension"
58 _ -> hPutStrLn stderr ("Called without expected arguments (<listDirectory> <recipientExtension>)") >> exitWith (ExitFailure 2)
59 "mlmmj-expose" -> do
60 args <- getArgs
61 case args of
62 [listDir, (map toLower -> ident)] -> do
63 setCurrentDirectory listDir
64 identities <- getIdentities
65 case ident `elem` identities of
66 True -> putStrLn "Identity is already known"
67 False -> writeFile "exposed.ids" . unlines $ ident : identities
68 _ -> hPutStrLn stderr ("Called without expected arguments (<listDirectory> <senderIdentity>)") >> exitWith (ExitFailure 2)
69 "mlmmj-get-exposed" -> do
70 args <- getArgs
71 case args of
72 (dropTrailingPathSeparator -> listDir) : (map toLower -> ident) : (map (map toLower) -> recipients) -> do
73 setCurrentDirectory listDir
74 identities <- getIdentities
75 unless (ident `elem` identities) . die $ "Unknown sender: ‘" ++ ident ++ "’"
76 subscribers <- getSubscribers
77 forM_ recipients (\recipient -> do {
78 unless (recipient `elem` subscribers) . die $ "Unknown recipient: ‘" ++ recipient ++ "’";
79 putStrLn $ takeFileName listDir ++ "+" ++ hash' (ident, recipient) ++ "@subs.lists.yggdrasil.li";
80 })
81 _ -> hPutStrLn stderr ("Called without expected arguments (<listDirectory> <senderIdentity> [<recipient> [...]])") >> exitWith (ExitFailure 2)
82 _ -> hPutStrLn stderr ("Called under unsupported name ‘" ++ progName ++ "’") >> exitWith (ExitFailure 2)
83 getIdentities :: IO [String]
84 getIdentities = (filter (not . null) . lines <$> readFile "exposed.ids") `catchIOError` (\e -> if isDoesNotExistError e then return [] else ioError e)
85
86 getSubscribers :: IO [String]
87 getSubscribers = map (map toLower) . concat <$> mapM (flip catchIOError (\e -> if isDoesNotExistError e then return [] else ioError e) . readDir) ["subscribers.d", "digesters.d"]
88 where
89 readDir dir = concat <$> (mapM (fmap lines . readFile) . map (dir </>) . filter (not . (`elem` [".", ".."]))=<< (getDirectoryContents dir))
90
91 hash' :: Show a => a -> String
92 hash' = take len . map toLower . show . (hash :: CBS.ByteString -> Digest SHA256) . CBS.pack . map toLower . show
93
94 len :: Int
95 len = 32
96 '';
97 buildCommand = '' 19 buildCommand = ''
98 mkdir -p $out/bin 20 mkdir -p $out/bin
99 #cp $src $out/bin/.mlmmj-exposed 21 #cp $src $out/bin/.mlmmj-exposed
100 ${haskellEnv}/bin/ghc -o $out/bin/.mlmmj-exposed -odir . -hidir . $src 22 ${haskellEnv}/bin/ghc -o $out/bin/.mlmmj-expose -odir . -hidir . $src
101 for f in mlmmj-exposed mlmmj-expose mlmmj-get-exposed; do 23 for f in mlmmj-exposed mlmmj-expose mlmmj-get-exposed mlmmj-serve-exposed; do
102 ln -s .mlmmj-exposed $out/bin/$f 24 ln -s .mlmmj-expose $out/bin/$f
103 done 25 done
104 ''; 26 '';
105 }; 27 };
diff --git a/ymir/zones/email.nights.soa b/ymir/zones/email.nights.soa
new file mode 100644
index 00000000..ac31f254
--- /dev/null
+++ b/ymir/zones/email.nights.soa
@@ -0,0 +1,34 @@
1$ORIGIN nights.email.
2$TTL 3600
3@ IN SOA ns.yggdrasil.li. root.yggdrasil.li. (
4 2017012701 ; serial
5 10800 ; refresh
6 3600 ; retry
7 604800 ; expire
8 3600 ; min TTL
9)
10 IN NS ns.yggdrasil.li.
11 IN NS ns.inwx.de.
12 IN NS ns2.inwx.de.
13 IN NS ns3.inwx.eu.
14 IN NS ns4.inwx.com.
15 IN NS ns5.inwx.net.
16
17@ IN A 188.68.51.254
18@ IN AAAA 2a03:4000:6:d004::
19@ IN MX 0 ymir.yggdrasil.li.
20@ IN TXT "v=spf1 redirect=yggdrasil.li"
21
22* IN A 188.68.51.254
23* IN AAAA 2a03:4000:6:d004::
24* IN MX 0 ymir.yggdrasil.li.
25* IN TXT "v=spf1 redirect=yggdrasil.li"
26
27ymir._domainkey IN TXT (
28 "v=DKIM1;k=rsa;p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq3cCKlk+VPhyAanLZTM0BCzUT/+fmxHioZcFk0uJk1akBYj7BRofR7eVNcLKpm3rwYMQgE+9vJH9p8SV6tws9EcWc8SMCqqGZlREYM7PmLDiTSK/vjCzkygfgFCb0EBNsY2A/fpP4rTeoxrbcBSvMkq97iY5rwyw4wXZVZXLiDaCj23s8POoxTk1ClqUJZJQ5x2"
29 "qzrC0RfN5kLZ9A7Gq2jB09vNxpXHYqABA0bJv88JiZM7hfkp9IafJZ+yCVMaBcJs4DAxnTjNAuFD9gm+qSFVY8+yeXqL6Qjo5PbruhyZRBW8RgRYT8t5n07XRglMGKKGMwOGLanrltcyXqB+GsDZBD36RAAwjFadnxdpDyRv4SgRP7ff2tKRrORYpmpN+mKdqw5j3J/nP6bXV1oAkyh9XQkPEIDi81WT87EZziTElDzVp6A2qFOxqucAovoRk24"
30 "7vlsns1FApFRsp9mja0UZNObyKD1M6tP9Ep7lS76tFGMk+WDvXRJH5LEsyCpu7sSyl1r/O0M4K+KldRCqLlZd7rf8F5P8T0dn1azk05g7F4p0N/y9GNdzXbPZ9u0eZdI7SEdh8ZoOZp7NVZiBFfbWLSS5ZtyA2kbBa4i7GJ/cuAbEKOmqAkeQPiu96TGIcyjkXjS6mTPI+9UmKZYZC+OM8XdJ02y5KRoonCc19ZS8CAwEAAQ=="
31)
32
33_xmpp-client._tcp IN SRV 5 0 5222 ymir.yggdrasil.li.
34_xmpp-server._tcp IN SRV 5 0 5269 ymir.yggdrasil.li.
diff --git a/ymir/zones/index.nix b/ymir/zones/index.nix
index 8424a0e0..05da73f1 100644
--- a/ymir/zones/index.nix
+++ b/ymir/zones/index.nix
@@ -5,8 +5,9 @@ with lib;
5rec { 5rec {
6 "141.li" = { data = readFile ./li.141.soa; }; 6 "141.li" = { data = readFile ./li.141.soa; };
7 "dirty-haskell.org" = { data = readFile ./org.dirty-haskell.soa; }; 7 "dirty-haskell.org" = { data = readFile ./org.dirty-haskell.soa; };
8 "lmu.li" = { data = readFile ./li.lmu.soa; };
9 "praseodym.org" = { data = readFile ./org.praseodym.soa; }; 8 "praseodym.org" = { data = readFile ./org.praseodym.soa; };
10 "xmpp.li" = { data = readFile ./li.xmpp.soa; }; 9 "xmpp.li" = { data = readFile ./li.xmpp.soa; };
11 "yggdrasil.li" = { data = readFile ./li.yggdrasil.soa; }; 10 "yggdrasil.li" = { data = readFile ./li.yggdrasil.soa; };
11 "kleen.li" = { data = readFile ./li.kleen.soa; };
12 "nights.email" = { data = readFile ./email.nights.soa; };
12} 13}
diff --git a/ymir/zones/li.lmu.soa b/ymir/zones/li.kleen.soa
index d1e05738..8c5af16e 100644
--- a/ymir/zones/li.lmu.soa
+++ b/ymir/zones/li.kleen.soa
@@ -1,7 +1,7 @@
1$ORIGIN lmu.li. 1$ORIGIN kleen.li.
2$TTL 3600 2$TTL 3600
3@ IN SOA ns.yggdrasil.li. root.yggdrasil.li. ( 3@ IN SOA ns.yggdrasil.li. root.yggdrasil.li. (
4 2016111011 ; serial 4 2017012601 ; serial
5 10800 ; refresh 5 10800 ; refresh
6 3600 ; retry 6 3600 ; retry
7 604800 ; expire 7 604800 ; expire
@@ -16,16 +16,19 @@ $TTL 3600
16 16
17@ IN A 188.68.51.254 17@ IN A 188.68.51.254
18@ IN AAAA 2a03:4000:6:d004:: 18@ IN AAAA 2a03:4000:6:d004::
19@ IN MX 10 ymir.yggdrasil.li. 19@ IN MX 0 ymir.yggdrasil.li.
20@ IN TXT "v=spf1 redirect=yggdrasil.li" 20@ IN TXT "v=spf1 redirect=yggdrasil.li"
21 21
22* IN A 188.68.51.254 22* IN A 188.68.51.254
23* IN AAAA 2a03:4000:6:d004:: 23* IN AAAA 2a03:4000:6:d004::
24* IN MX 0 ymir.yggdrasil.li. 24* IN MX 0 ymir.yggdrasil.li.
25* IN TXT "v=spf1 redirect=yggdrasil.li" 25* IN TXT "v=spf1 redirect=yggdrasil.li"
26 26
27ymir._domainkey IN TXT ( 27ymir._domainkey IN TXT (
28 "v=DKIM1;k=rsa;p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq3cCKlk+VPhyAanLZTM0BCzUT/+fmxHioZcFk0uJk1akBYj7BRofR7eVNcLKpm3rwYMQgE+9vJH9p8SV6tws9EcWc8SMCqqGZlREYM7PmLDiTSK/vjCzkygfgFCb0EBNsY2A/fpP4rTeoxrbcBSvMkq97iY5rwyw4wXZVZXLiDaCj23s8POoxTk1ClqUJZJQ5x2" 28 "v=DKIM1;k=rsa;p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq3cCKlk+VPhyAanLZTM0BCzUT/+fmxHioZcFk0uJk1akBYj7BRofR7eVNcLKpm3rwYMQgE+9vJH9p8SV6tws9EcWc8SMCqqGZlREYM7PmLDiTSK/vjCzkygfgFCb0EBNsY2A/fpP4rTeoxrbcBSvMkq97iY5rwyw4wXZVZXLiDaCj23s8POoxTk1ClqUJZJQ5x2"
29 "qzrC0RfN5kLZ9A7Gq2jB09vNxpXHYqABA0bJv88JiZM7hfkp9IafJZ+yCVMaBcJs4DAxnTjNAuFD9gm+qSFVY8+yeXqL6Qjo5PbruhyZRBW8RgRYT8t5n07XRglMGKKGMwOGLanrltcyXqB+GsDZBD36RAAwjFadnxdpDyRv4SgRP7ff2tKRrORYpmpN+mKdqw5j3J/nP6bXV1oAkyh9XQkPEIDi81WT87EZziTElDzVp6A2qFOxqucAovoRk24" 29 "qzrC0RfN5kLZ9A7Gq2jB09vNxpXHYqABA0bJv88JiZM7hfkp9IafJZ+yCVMaBcJs4DAxnTjNAuFD9gm+qSFVY8+yeXqL6Qjo5PbruhyZRBW8RgRYT8t5n07XRglMGKKGMwOGLanrltcyXqB+GsDZBD36RAAwjFadnxdpDyRv4SgRP7ff2tKRrORYpmpN+mKdqw5j3J/nP6bXV1oAkyh9XQkPEIDi81WT87EZziTElDzVp6A2qFOxqucAovoRk24"
30 "7vlsns1FApFRsp9mja0UZNObyKD1M6tP9Ep7lS76tFGMk+WDvXRJH5LEsyCpu7sSyl1r/O0M4K+KldRCqLlZd7rf8F5P8T0dn1azk05g7F4p0N/y9GNdzXbPZ9u0eZdI7SEdh8ZoOZp7NVZiBFfbWLSS5ZtyA2kbBa4i7GJ/cuAbEKOmqAkeQPiu96TGIcyjkXjS6mTPI+9UmKZYZC+OM8XdJ02y5KRoonCc19ZS8CAwEAAQ==" 30 "7vlsns1FApFRsp9mja0UZNObyKD1M6tP9Ep7lS76tFGMk+WDvXRJH5LEsyCpu7sSyl1r/O0M4K+KldRCqLlZd7rf8F5P8T0dn1azk05g7F4p0N/y9GNdzXbPZ9u0eZdI7SEdh8ZoOZp7NVZiBFfbWLSS5ZtyA2kbBa4i7GJ/cuAbEKOmqAkeQPiu96TGIcyjkXjS6mTPI+9UmKZYZC+OM8XdJ02y5KRoonCc19ZS8CAwEAAQ=="
31) 31)
32
33_xmpp-client._tcp IN SRV 5 0 5222 ymir.yggdrasil.li.
34_xmpp-server._tcp IN SRV 5 0 5269 ymir.yggdrasil.li.