diff options
| -rw-r--r-- | .gitignore | 4 | ||||
| -rw-r--r-- | bragi.nix | 157 | ||||
| -rw-r--r-- | bragi/bar/default.nix | 33 | ||||
| -rw-r--r-- | bragi/bar/generated.nix | 34 | ||||
| -rw-r--r-- | bragi/bar/generated.nix.gup | 5 | ||||
| -rw-r--r-- | bragi/thermoprint-server/thermoprint-server.hs | 45 | ||||
| m--------- | custom/thermoprint | 0 | ||||
| -rw-r--r-- | custom/tinc/def.nix | 145 | ||||
| m--------- | custom/trivmix | 0 | ||||
| -rw-r--r-- | custom/trivmix-service.nix | 41 | ||||
| l--------- | custom/trivmix.nix | 1 | ||||
| -rw-r--r-- | custom/uucp.nix | 18 | ||||
| -rw-r--r-- | customized/prosody.nix | 8 | ||||
| -rw-r--r-- | hel.nix | 104 | ||||
| -rw-r--r-- | hel/recv-media.nix | 3 | ||||
| m--------- | musnix | 0 | ||||
| -rw-r--r-- | users.nix | 1 | ||||
| -rw-r--r-- | users/gkleen@ymir.nix | 1 | ||||
| -rw-r--r-- | users/mherold.nix | 2 | ||||
| -rw-r--r-- | users/some.nix | 8 | ||||
| m--------- | utils | 0 | ||||
| -rw-r--r-- | ymir.nix | 130 | ||||
| -rw-r--r-- | ymir/mlmmj-expose.hs | 182 | ||||
| -rw-r--r-- | ymir/mlmmj-expose.nix | 112 | ||||
| -rw-r--r-- | ymir/zones/email.nights.soa | 34 | ||||
| -rw-r--r-- | ymir/zones/index.nix | 3 | ||||
| -rw-r--r-- | ymir/zones/li.kleen.soa (renamed from ymir/zones/li.lmu.soa) | 17 |
27 files changed, 773 insertions, 315 deletions
| @@ -1,3 +1,5 @@ | |||
| 1 | configuration.nix | 1 | configuration.nix |
| 2 | config.nix | 2 | config.nix |
| 3 | **/\#*\# \ No newline at end of file | 3 | **/\#*\# |
| 4 | **/.gup/ | ||
| 5 | **/result | ||
| @@ -3,6 +3,7 @@ | |||
| 3 | let | 3 | let |
| 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; | ||
| 6 | in rec { | 7 | in 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 | |||
| 7 | let | ||
| 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 | }; | ||
| 24 | in 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 | }: | ||
| 11 | mkDerivation { | ||
| 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 | |||
| 3 | gup -u ${2:r}.cabal | ||
| 4 | cd ${2:h} | ||
| 5 | cabal2nix --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 | |||
| 4 | module Main (main) where | ||
| 5 | |||
| 6 | import Thermoprint.Server | ||
| 7 | |||
| 8 | import Thermoprint.Server.Printer.Generic | ||
| 9 | |||
| 10 | import Control.Monad.Trans.Resource | ||
| 11 | import Control.Monad.Logger | ||
| 12 | import Control.Monad.Reader | ||
| 13 | |||
| 14 | import Data.Function ((&)) | ||
| 15 | |||
| 16 | import Database.Persist.Postgresql | ||
| 17 | |||
| 18 | import qualified Network.Wai.Handler.Warp as Warp | ||
| 19 | |||
| 20 | type ServerM = ReaderT ConnectionPool (LoggingT IO) | ||
| 21 | |||
| 22 | main :: IO () | ||
| 23 | main = 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 | }; | ||
| 9 | in | 80 | in |
| 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 | ||
| 13 | let | 15 | let |
| 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 | 26 | in { |
| 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 | }; | ||
| 35 | in 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 @@ | |||
| 1 | trivmix/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); |
| 26 | in | 26 | in |
| 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 ] |
| @@ -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 | ||
| 11 | assert showTitle -> ffmpeg != null && gnused != null && notifyUser != null; | 12 | assert 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 | ||
| @@ -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 | ||
| @@ -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 | ]; |
| 23 | in rec { | 24 | in 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 | |||
| 3 | import System.IO | ||
| 4 | import System.IO.Error | ||
| 5 | import System.FilePath | ||
| 6 | import System.Environment | ||
| 7 | import System.Exit | ||
| 8 | import System.Directory | ||
| 9 | import System.Process | ||
| 10 | import Text.Printf | ||
| 11 | |||
| 12 | import Data.Char | ||
| 13 | |||
| 14 | import Control.Monad | ||
| 15 | |||
| 16 | import Crypto.Hash | ||
| 17 | |||
| 18 | import qualified Data.ByteString.Lazy as LBS | ||
| 19 | import qualified Data.ByteString.Char8 as CBS | ||
| 20 | |||
| 21 | import qualified Data.UUID as UUID (toString) | ||
| 22 | import qualified Data.UUID.V4 as UUID (nextRandom) | ||
| 23 | |||
| 24 | import Data.Aeson | ||
| 25 | import Data.Aeson.Encode.Pretty | ||
| 26 | |||
| 27 | import Data.Set (Set) | ||
| 28 | import qualified Data.Set as Set | ||
| 29 | |||
| 30 | newtype FoxReplace = FoxReplace (Set FoxReplaceGroup) | ||
| 31 | deriving (Ord, Eq, Show) | ||
| 32 | |||
| 33 | data FoxReplaceGroup = FoxReplaceGroup | ||
| 34 | { groupName :: String | ||
| 35 | , groupUrls :: Set String | ||
| 36 | , groupSubs :: Set FoxReplaceSub | ||
| 37 | , groupHtmlMode :: FoxReplaceHTML | ||
| 38 | } | ||
| 39 | deriving (Ord, Eq, Show) | ||
| 40 | |||
| 41 | data FoxReplaceHTML = NoHTML | OutputOnlyHTML | BothHTML | ||
| 42 | deriving (Ord, Eq, Enum, Show) | ||
| 43 | |||
| 44 | data FoxReplaceSub = FoxReplaceSub | ||
| 45 | { rInput, rOutput :: String | ||
| 46 | , rInputType :: SubInput | ||
| 47 | , rCaseSensitive :: Bool | ||
| 48 | } | ||
| 49 | deriving (Ord, Eq, Show) | ||
| 50 | |||
| 51 | data SubInput = TextInput | WordInput | RegexpInput | ||
| 52 | deriving (Ord, Eq, Enum, Show) | ||
| 53 | |||
| 54 | |||
| 55 | instance ToJSON FoxReplace where | ||
| 56 | toJSON (FoxReplace groupSet) = object | ||
| 57 | [ "version" .= ("0.15" :: String) | ||
| 58 | , "groups" .= groupSet | ||
| 59 | ] | ||
| 60 | |||
| 61 | instance ToJSON FoxReplaceGroup where | ||
| 62 | toJSON FoxReplaceGroup{..} = object | ||
| 63 | [ "name" .= groupName | ||
| 64 | , "html" .= groupHtmlMode | ||
| 65 | , "enabled" .= True | ||
| 66 | , "urls" .= groupUrls | ||
| 67 | , "substitutions" .= groupSubs | ||
| 68 | ] | ||
| 69 | |||
| 70 | instance ToJSON FoxReplaceHTML where | ||
| 71 | toJSON NoHTML = String "none" | ||
| 72 | toJSON OutputOnlyHTML = String "output" | ||
| 73 | toJSON BothHTML = String "inputoutput" | ||
| 74 | |||
| 75 | instance ToJSON FoxReplaceSub where | ||
| 76 | toJSON FoxReplaceSub{..} = object | ||
| 77 | [ "input" .= rInput | ||
| 78 | , "output" .= rOutput | ||
| 79 | , "inputType" .= rInputType | ||
| 80 | , "caseSensitive" .= rCaseSensitive | ||
| 81 | ] | ||
| 82 | |||
| 83 | instance ToJSON SubInput where | ||
| 84 | toJSON TextInput = String "text" | ||
| 85 | toJSON WordInput = String "wholewords" | ||
| 86 | toJSON RegexpInput = String "regexp" | ||
| 87 | |||
| 88 | |||
| 89 | main :: IO () | ||
| 90 | main = 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 | |||
| 170 | getIdentities :: IO [String] | ||
| 171 | getIdentities = (filter (not . null) . lines <$> readFile "exposed.ids") `catchIOError` (\e -> if isDoesNotExistError e then return [] else ioError e) | ||
| 172 | |||
| 173 | getSubscribers :: IO [String] | ||
| 174 | getSubscribers = 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 | |||
| 178 | hash' :: Show a => a -> String | ||
| 179 | hash' = take len . map toLower . show . (hash :: CBS.ByteString -> Digest SHA256) . CBS.pack . map toLower . show | ||
| 180 | |||
| 181 | len :: Int | ||
| 182 | len = 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 | ||
| 3 | let | 3 | let |
| 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 | |||
| 27 | ymir._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; | |||
| 5 | rec { | 5 | rec { |
| 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 | ||
| 27 | ymir._domainkey IN TXT ( | 27 | ymir._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. | ||
