1
0
Fork 0
This commit is contained in:
Malte 2023-05-22 03:06:42 +02:00
parent 157f7077d0
commit b4db084e37
144 changed files with 2916 additions and 3931 deletions

View file

@ -1,27 +1,35 @@
{pkgs}: {
{ pkgs }: {
syncthing = {
declarativeWith = hosts: path: let
mkFolder = name: {
path = "${path}/${name}";
devices = hosts;
declarativeWith = hosts: path:
let
mkFolder = name: {
path = "${path}/${name}";
devices = hosts;
};
devices = pkgs.lib.mapAttrs (name: conf:
conf // {
addresses = [ "tcp6://${name}.vpn.m-0.eu" ];
}) {
apollo.id =
"BOTTTGS-QQUHWAK-IFBT3T2-HGHHUZ7-QHRZXC7-JC42VT7-67ZOJBE-WHDWEQX";
zeus.id =
"5BUZIS5-ESTYAJO-IQQD7EA-O3VGONJ-E74OHUJ-ZSLF4JK-6HS3UHG-4CQ5OAO";
pegasus.id =
"BISYPNZ-54VKBKS-LBND4AS-JNWVOW7-BTW2UMV-QHYM5TZ-GE3AK3E-PGSXPQE";
hera.id =
"TJHVUM6-RTB6V3D-JF4GIB2-TVDF2ST-5MTN6N2-ZDIWGF7-XZUCCFG-EQG5WA6";
};
in {
devices = pkgs.lib.getAttrs hosts devices;
folders = {
science = mkFolder "science";
documents = mkFolder "documents";
audio = mkFolder "audio";
video = mkFolder "video";
images = mkFolder "images";
books = mkFolder "books";
tmp = mkFolder "tmp";
};
};
devices = pkgs.lib.mapAttrs (name: conf: conf // {addresses = ["tcp6://${name}.vpn.m-0.eu"];}) {
apollo.id = "BOTTTGS-QQUHWAK-IFBT3T2-HGHHUZ7-QHRZXC7-JC42VT7-67ZOJBE-WHDWEQX";
zeus.id = "5BUZIS5-ESTYAJO-IQQD7EA-O3VGONJ-E74OHUJ-ZSLF4JK-6HS3UHG-4CQ5OAO";
pegasus.id = "BISYPNZ-54VKBKS-LBND4AS-JNWVOW7-BTW2UMV-QHYM5TZ-GE3AK3E-PGSXPQE";
hera.id = "TJHVUM6-RTB6V3D-JF4GIB2-TVDF2ST-5MTN6N2-ZDIWGF7-XZUCCFG-EQG5WA6";
};
in {
devices = pkgs.lib.getAttrs hosts devices;
folders = {
science = mkFolder "science";
documents = mkFolder "documents";
audio = mkFolder "audio";
video = mkFolder "video";
images = mkFolder "images";
books = mkFolder "books";
tmp = mkFolder "tmp";
};
};
};
}

View file

@ -1,9 +1,4 @@
{
config,
pkgs,
lib,
...
}:
{ config, pkgs, lib, ... }:
with lib; {
config = {
m-0.monitoring = [
@ -55,8 +50,8 @@ with lib; {
monitoring = mkOption {
type = types.listOf (types.submodule {
options = {
name = mkOption {type = types.str;};
host = mkOption {type = types.str;};
name = mkOption { type = types.str; };
host = mkOption { type = types.str; };
container = mkOption {
type = types.bool;
default = false;
@ -67,18 +62,13 @@ with lib; {
};
};
});
default = [];
default = [ ];
};
headscaleIPs = mkOption {
type = types.listOf types.string;
default = [
"100.64.7.0/24"
"fd7a:115c:a1e0:77::/64"
];
};
virtualHosts = mkOption {
type = types.attrs;
default = [ "100.64.7.0/24" "fd7a:115c:a1e0:77::/64" ];
};
virtualHosts = mkOption { type = types.attrs; };
hosts = mkOption {
type = types.attrs;
default = let
@ -99,14 +89,7 @@ with lib; {
# (echo '{' && tailscale status -json | jq -r '.Self,.Peer[] | .DNSName[:-17] + " = { A = \"" + .TailscaleIPs[0] + "\"; AAAA = \"" + .TailscaleIPs[1] + "\";};"' && echo '}') > common/tailscale.nix
tailscale = import ./tailscale.nix;
publicAliases = {
hera = [
"blog"
"cloud"
"git"
"lists"
"matrix"
"rpg"
];
hera = [ "blog" "cloud" "git" "lists" "matrix" "rpg" ];
};
aliases = {
hera = [
@ -131,9 +114,9 @@ with lib; {
"tasks"
"taskserver"
];
fluffy = ["home" "syncthing-fluffy" "5e"];
zeus = ["syncthing-zeus"];
apollo = ["syncthing-apollo"];
fluffy = [ "home" "syncthing-fluffy" "5e" ];
zeus = [ "syncthing-zeus" ];
apollo = [ "syncthing-apollo" ];
};
};
};

View file

@ -1,8 +1,4 @@
{
inputs,
config,
...
}: {
{ inputs, config, ... }: {
imports = [
inputs.pre-commit-hooks.flakeModule
./nixos/flake-module.nix
@ -10,22 +6,17 @@
./packages/flake-module.nix
./overlays/flake-module.nix
];
systems = ["x86_64-linux"];
perSystem = {
inputs',
lib,
config,
pkgs,
...
}: {
systems = [ "x86_64-linux" ];
perSystem = { inputs', lib, config, pkgs, ... }: {
devShells = {
default = pkgs.mkShell {
shellHook = config.pre-commit.installationScript;
};
default =
pkgs.mkShell { shellHook = config.pre-commit.installationScript; };
};
checks = {
system-checks = pkgs.recursiveLinkFarm "all-configs" {
nixos-configurations = lib.mapAttrs (_: config: config.config.system.build.toplevel) inputs.self.nixosConfigurations;
nixos-configurations =
lib.mapAttrs (_: config: config.config.system.build.toplevel)
inputs.self.nixosConfigurations;
home-manager-configurations = inputs.self.homeModes;
};
};
@ -42,8 +33,10 @@
];
hooks = {
hlint.enable = true;
alejandra.enable = true;
nix-linter.enable = false; # Too many false positives for now
nixfmt.enable = true;
#nil.enable = true;
#editorconfig-checker.enable = true;
#deadnix.enable = true;
statix.enable = true;
fourmolu.enable = true;
shellcheck.enable = true;

View file

@ -32,13 +32,12 @@
nixpkgs-22_11.follows = "";
blobs.follows = "";
};
url = "git+https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git";
url =
"git+https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git";
};
home-manager = {
url = "home-manager/master";
inputs = {
nixpkgs.follows = "";
};
inputs = { nixpkgs.follows = ""; };
};
hexa-nur-packages = {
url = "github:mweinelt/nur-packages";
@ -60,6 +59,7 @@
};
};
outputs = inputs @ {nixos-hardware, ...}:
inputs.flake-parts.lib.mkFlake {inherit inputs;} (import ./flake-module.nix);
outputs = inputs@{ nixos-hardware, ... }:
inputs.flake-parts.lib.mkFlake { inherit inputs; }
(import ./flake-module.nix);
}

View file

@ -1,50 +1,36 @@
{
withSystem,
lib,
inputs,
...
}: {
flake = withSystem "x86_64-linux" ({
self',
pkgs,
...
}: let
flattenAttrs = attrs:
lib.listToAttrs (lib.flatten (lib.mapAttrsToList
(
outer_key:
lib.mapAttrsToList
(inner_key: value: {
name = "${outer_key}-${inner_key}";
inherit value;
})
)
attrs));
machines = import ./machines.nix;
buildHomeManager = config: (inputs.home-manager.lib.homeManagerConfiguration {
inherit pkgs;
modules = [
config
inputs.emanote.homeManagerModule
inputs.nix-index-database.hmModules.nix-index
];
{ withSystem, lib, inputs, ... }: {
flake = withSystem "x86_64-linux" ({ self', pkgs, ... }:
let
flattenAttrs = attrs:
lib.listToAttrs (lib.flatten (lib.mapAttrsToList (outer_key:
lib.mapAttrsToList (inner_key: value: {
name = "${outer_key}-${inner_key}";
inherit value;
})) attrs));
machines = import ./machines.nix;
buildHomeManager = config:
(inputs.home-manager.lib.homeManagerConfiguration {
inherit pkgs;
modules = [
config
inputs.emanote.homeManagerModule
inputs.nix-index-database.hmModules.nix-index
];
});
buildModesForHost = host: modes:
(pkgs.recursiveLinkFarm "${host}-modes"
(lib.mapAttrs (_: config: (buildHomeManager config).activationPackage)
modes)).overrideAttrs (old: {
buildCommand = if inputs.self.sourceInfo ? rev then ''
${old.buildCommand}
echo ${inputs.self.sourceInfo.rev} > $out/config-commit;
'' else
old.buildCommand;
});
in {
homeConfigurations =
lib.mapAttrs (_: buildHomeManager) (flattenAttrs machines);
homeModes =
lib.mapAttrs buildModesForHost { inherit (machines) zeus apollo; };
});
buildModesForHost = host: modes:
(pkgs.recursiveLinkFarm "${host}-modes"
(lib.mapAttrs
(_: config: (buildHomeManager config).activationPackage)
modes))
.overrideAttrs (old: {
buildCommand =
if inputs.self.sourceInfo ? rev
then ''
${old.buildCommand}
echo ${inputs.self.sourceInfo.rev} > $out/config-commit;
''
else old.buildCommand;
});
in {
homeConfigurations = lib.mapAttrs (_: buildHomeManager) (flattenAttrs machines);
homeModes = lib.mapAttrs buildModesForHost {inherit (machines) zeus apollo;};
});
}

View file

@ -1,20 +1,18 @@
let
restrictedPages =
[
"reddit.com"
"github.com"
"*.ccc.de"
"haskell.org"
"*.haskell.org"
"*.nixos.org"
"nixos.org"
"matrix.org"
"element.io"
"youtube.*"
"*.element.io"
"twitter.com"
]
++ newsPages;
restrictedPages = [
"reddit.com"
"github.com"
"*.ccc.de"
"haskell.org"
"*.haskell.org"
"*.nixos.org"
"nixos.org"
"matrix.org"
"element.io"
"youtube.*"
"*.element.io"
"twitter.com"
] ++ newsPages;
newsPages = [
"chaos.social"
"zeit.de"
@ -33,26 +31,19 @@ let
];
makeConfig = hostName: imports: _: {
imports = imports ++ [./roles/default.nix];
imports = imports ++ [ ./roles/default.nix ];
m-0.hostName = hostName;
};
makeAutostart = name: {config, ...}: {
config.xdg.configFile."autostart/${name}.desktop".source = "${config.home.path}/share/applications/${name}.desktop";
};
orga-basics = [
./roles/mail.nix
./roles/taskwarrior.nix
];
default = [
./roles/on-my-machine.nix
./roles/systemd-exporter.nix
];
daily-driver = name: extra: let
all =
extra
++ orga-basics
++ default
++ [
makeAutostart = name:
{ config, ... }: {
config.xdg.configFile."autostart/${name}.desktop".source =
"${config.home.path}/share/applications/${name}.desktop";
};
orga-basics = [ ./roles/mail.nix ./roles/taskwarrior.nix ];
default = [ ./roles/on-my-machine.nix ./roles/systemd-exporter.nix ];
daily-driver = name: extra:
let
all = extra ++ orga-basics ++ default ++ [
(makeAutostart "kassandra2")
(makeAutostart "unlock-ssh")
./roles/beets.nix
@ -83,46 +74,30 @@ let
./roles/wallpaper.nix
./roles/zettelkasten.nix
];
blockServer = import ./roles/block-server.nix;
in {
klausur = makeConfig name (
all
++ [
(blockServer restrictedPages)
]
);
code = makeConfig name (
all
++ [
blockServer = import ./roles/block-server.nix;
in {
klausur = makeConfig name (all ++ [ (blockServer restrictedPages) ]);
code = makeConfig name (all ++ [
./roles/mail-client.nix
./roles/chat.nix
(blockServer newsPages)
]
);
leisure = makeConfig name (
all
++ [
]);
leisure = makeConfig name (all ++ [
./roles/mail-client.nix
./roles/games.nix
./roles/chat.nix
(blockServer newsPages)
]
);
unrestricted = makeConfig name (
all
++ [
]);
unrestricted = makeConfig name (all ++ [
./roles/mail-client.nix
./roles/games.nix
./roles/chat.nix
(blockServer [])
]
);
};
(blockServer [ ])
]);
};
in {
apollo = daily-driver "apollo" [
./roles/battery.nix
./roles/untrusted-env.nix
];
apollo =
daily-driver "apollo" [ ./roles/battery.nix ./roles/untrusted-env.nix ];
zeus = daily-driver "zeus" [
(import ./roles/state.nix "klausur")
./roles/create-plans.nix
@ -130,23 +105,14 @@ in {
./roles/trusted-env.nix
./roles/wine.nix
];
fluffy.default = makeConfig "fluffy" (
default
++ [
./roles/headless.nix
(import ./roles/state.nix "default")
]
);
hera.default = makeConfig "hera" (
default
++ orga-basics
++ [
./roles/fetch-banking-timer.nix
./roles/weechat
./roles/mail-sort.nix
./roles/mail2rss.nix
./roles/headless-mpd.nix
./roles/headless.nix
]
);
fluffy.default = makeConfig "fluffy"
(default ++ [ ./roles/headless.nix (import ./roles/state.nix "default") ]);
hera.default = makeConfig "hera" (default ++ orga-basics ++ [
./roles/fetch-banking-timer.nix
./roles/weechat
./roles/mail-sort.nix
./roles/mail2rss.nix
./roles/headless-mpd.nix
./roles/headless.nix
]);
}

View file

@ -1,69 +1,63 @@
{
lib,
pkgs,
config,
...
}: let
battery-watch =
pkgs.writeHaskellScript
{
name = "battery-watch";
bins = [pkgs.acpi];
imports = [
"DBus.Notify"
"Control.Concurrent"
"Text.Megaparsec"
"Text.Megaparsec.Char"
"Text.Megaparsec.Char.Lexer"
"Replace.Megaparsec"
"Data.Maybe"
];
} ''
moderateLevel = 50 -- percent
lowLevel = 20 -- percent
criticalLevel = 8 -- percent
minute = 60 * 1000 * 1000 -- threadDelay takes microseconds
{ lib, pkgs, config, ... }:
let
battery-watch = pkgs.writeHaskellScript {
name = "battery-watch";
bins = [ pkgs.acpi ];
imports = [
"DBus.Notify"
"Control.Concurrent"
"Text.Megaparsec"
"Text.Megaparsec.Char"
"Text.Megaparsec.Char.Lexer"
"Replace.Megaparsec"
"Data.Maybe"
];
} ''
moderateLevel = 50 -- percent
lowLevel = 20 -- percent
criticalLevel = 8 -- percent
minute = 60 * 1000 * 1000 -- threadDelay takes microseconds
main = do
client <- connectSession
let loop = \lastState handleMay -> do
newState <- getState
let noteMay = chooseAction lastState newState
handle <- if | Just note <- noteMay -> Just <$> maybe (notify client note) (flip (replace client) note) handleMay
| otherwise -> pure handleMay
threadDelay $ minute `div` 4
loop newState handle
loop (BatState True 100) Nothing
main = do
client <- connectSession
let loop = \lastState handleMay -> do
newState <- getState
let noteMay = chooseAction lastState newState
handle <- if | Just note <- noteMay -> Just <$> maybe (notify client note) (flip (replace client) note) handleMay
| otherwise -> pure handleMay
threadDelay $ minute `div` 4
loop newState handle
loop (BatState True 100) Nothing
data BatState = BatState { charging :: Bool, level :: Int }
data BatState = BatState { charging :: Bool, level :: Int }
getState = do
batteryStateText <- decodeUtf8 <$> (acpi "-a" |> captureTrim)
batteryLevelText <- decodeUtf8 <$> (acpi "-b" |> captureTrim)
chargerOnline <- maybe (fail "Couldnt get charging state") pure $ parseMaybe onlineParser batteryStateText
batteryLevel <- maybe (fail "Couldnt get battery level") pure $ parseMaybe levelParser batteryLevelText
pure $ BatState chargerOnline batteryLevel
getState = do
batteryStateText <- decodeUtf8 <$> (acpi "-a" |> captureTrim)
batteryLevelText <- decodeUtf8 <$> (acpi "-b" |> captureTrim)
chargerOnline <- maybe (fail "Couldnt get charging state") pure $ parseMaybe onlineParser batteryStateText
batteryLevel <- maybe (fail "Couldnt get battery level") pure $ parseMaybe levelParser batteryLevelText
pure $ BatState chargerOnline batteryLevel
type Parser = Parsec Text LText
type Parser = Parsec Text LText
onlineParser :: Parser Bool
onlineParser = not . null . rights <$> sepCap (string "on-line")
onlineParser :: Parser Bool
onlineParser = not . null . rights <$> sepCap (string "on-line")
levelParser :: Parser Int
levelParser = (maybe (fail "No Number found") pure . listToMaybe . rights) =<< sepCap (decimal <* "%")
levelParser :: Parser Int
levelParser = (maybe (fail "No Number found") pure . listToMaybe . rights) =<< sepCap (decimal <* "%")
chooseAction :: BatState -> BatState -> Maybe Note
chooseAction (BatState wasCharging lastLevel) (BatState isCharging currentLevel)
| wasCharging && isCharging = Nothing
| wasCharging && not isCharging = Just $ myNote{summary = "Charger disconnected." }
| not wasCharging && isCharging = Just $ myNote{summary = "Charger connected.", expiry = Milliseconds 5000 }
| currentLevel <= criticalLevel = Just $ myNote{summary = "Battery is very low!" }
| currentLevel <= lowLevel && currentLevel < lastLevel = Just $ myNote{summary = "Battery is low!"}
| ((currentLevel `mod` 5 == 0 && currentLevel <= moderateLevel) || (currentLevel `mod` 10 == 0)) && currentLevel < lastLevel = Just $ myNote{summary = "Battery is discharging."}
| otherwise = Nothing
where
myNote = blankNote { body = Just $ Text [i|#{currentLevel}% remaining.|]}
'';
chooseAction :: BatState -> BatState -> Maybe Note
chooseAction (BatState wasCharging lastLevel) (BatState isCharging currentLevel)
| wasCharging && isCharging = Nothing
| wasCharging && not isCharging = Just $ myNote{summary = "Charger disconnected." }
| not wasCharging && isCharging = Just $ myNote{summary = "Charger connected.", expiry = Milliseconds 5000 }
| currentLevel <= criticalLevel = Just $ myNote{summary = "Battery is very low!" }
| currentLevel <= lowLevel && currentLevel < lastLevel = Just $ myNote{summary = "Battery is low!"}
| ((currentLevel `mod` 5 == 0 && currentLevel <= moderateLevel) || (currentLevel `mod` 10 == 0)) && currentLevel < lastLevel = Just $ myNote{summary = "Battery is discharging."}
| otherwise = Nothing
where
myNote = blankNote { body = Just $ Text [i|#{currentLevel}% remaining.|]}
'';
in {
systemd.user = {
services.battery = {
@ -73,7 +67,7 @@ in {
Restart = "always";
RestartSec = 60;
};
Install.WantedBy = ["default.target"];
Install.WantedBy = [ "default.target" ];
};
};
}

View file

@ -1,22 +1,22 @@
{
pkgs,
config,
...
}: {
{ pkgs, config, ... }: {
xdg.configFile."beets/config.yaml".text = builtins.toJSON {
directory = config.services.mpd.musicDirectory;
import.move = true;
paths = {
default = "$genre/%the{$albumartist}/$album/%if{$multidisc,Disc $disc/}$track. $title";
default =
"$genre/%the{$albumartist}/$album/%if{$multidisc,Disc $disc/}$track. $title";
singleton = "$genre/%the{$artist}/singles/$title";
comp = "$genre/%the{$artist}/$album%/%if{$multidisc,Disc $disc/}$track. $title";
"genre:soundtrack" = "Soundtrack/$album/%if{$multidisc,Disc $disc/}$track. $title";
comp =
"$genre/%the{$artist}/$album%/%if{$multidisc,Disc $disc/}$track. $title";
"genre:soundtrack" =
"Soundtrack/$album/%if{$multidisc,Disc $disc/}$track. $title";
};
plugins = "convert web fromfilename the duplicates missing inline";
item_fields.multidisc = "1 if disctotal > 1 else 0";
convert = {
auto = true;
command = "${pkgs.ffmpeg}/bin/ffmpeg -i $source -y -vn -acodec libopus -ab 192k $dest";
command =
"${pkgs.ffmpeg}/bin/ffmpeg -i $source -y -vn -acodec libopus -ab 192k $dest";
extension = "opus";
never_convert_lossy_files = true;
};

View file

@ -1,19 +1,16 @@
{
pkgs,
lib,
...
}: let
{ pkgs, lib, ... }:
let
package = pkgs.rbw.override {
withFzf = true;
withPass = true;
};
rbw-totp-fzf = pkgs.runCommand "rbw-totp-fzf" {} ''
rbw-totp-fzf = pkgs.runCommand "rbw-totp-fzf" { } ''
mkdir -p $out/bin
cp ${package}/bin/rbw-fzf $out/bin/rbw-totp-fzf
${lib.getExe pkgs.sd} "rbw get" "rbw code" $out/bin/rbw-totp-fzf
'';
in {
home.packages = [rbw-totp-fzf];
home.packages = [ rbw-totp-fzf ];
programs.rbw = {
enable = true;
inherit package;

View file

@ -1,22 +1,22 @@
list: {
pkgs,
lib,
...
}: {
list:
{ pkgs, lib, ... }: {
systemd.user.services.blockserver = {
Unit.Description = "Serve a blocklist";
Service = let
blocklist = pkgs.writeTextDir "blocklist" (lib.concatStringsSep "\r\n" list);
startpage = pkgs.writeTextDir "index.html" (builtins.readFile ./startpage.html);
blocklist =
pkgs.writeTextDir "blocklist" (lib.concatStringsSep "\r\n" list);
startpage =
pkgs.writeTextDir "index.html" (builtins.readFile ./startpage.html);
in {
ExecStart = "${pkgs.python3}/bin/python -m http.server --bind :: 8842 -d ${
pkgs.symlinkJoin {
name = "blockserver-dir";
paths = [blocklist startpage];
}
}";
ExecStart =
"${pkgs.python3}/bin/python -m http.server --bind :: 8842 -d ${
pkgs.symlinkJoin {
name = "blockserver-dir";
paths = [ blocklist startpage ];
}
}";
Restart = "always";
};
Install.WantedBy = ["default.target"];
Install.WantedBy = [ "default.target" ];
};
}

View file

@ -1,11 +1,9 @@
{pkgs, ...}: {
home.packages =
builtins.attrValues
{
inherit (pkgs) discord signal-desktop tdesktop element-desktop;
weechat = pkgs.writeShellScriptBin "weechat" "ssh -t hera 'TMUX_TMPDIR=/run/user/1000 tmux -L weechat attach'";
};
xdg.configFile."Element/config.json".text = builtins.toJSON {
showLabsSettings = true;
{ pkgs, ... }: {
home.packages = builtins.attrValues {
inherit (pkgs) discord signal-desktop tdesktop element-desktop;
weechat = pkgs.writeShellScriptBin "weechat"
"ssh -t hera 'TMUX_TMPDIR=/run/user/1000 tmux -L weechat attach'";
};
xdg.configFile."Element/config.json".text =
builtins.toJSON { showLabsSettings = true; };
}

View file

@ -1,74 +1,65 @@
{
pkgs,
lib,
...
}: let
{ pkgs, lib, ... }:
let
dimensions = "20,130";
service = name: {
extra,
text,
wait,
}: let
config-file = builtins.toFile "conky-${name}.conf" ''
conky.config = {
background = false,
border_width = 0,
cpu_avg_samples = 2,
double_buffer = true,
draw_borders = false,
draw_graph_borders = false,
draw_outline = false,
draw_shades = false,
extra_newline = false,
font = 'CozetteVector:pixelsize=12',
gap_y = 1,
minimum_height = 5,
minimum_width = 2,
max_text_width = 25,
net_avg_samples = 2,
no_buffers = true,
out_to_console = false,
out_to_ncurses = false,
out_to_stderr = false,
out_to_x = true,
own_window = true,
own_window_class = 'Conky',
own_window_type = 'panel',
own_window_argb_visual = true,
own_window_argb_value = 0,
show_graph_range = false,
show_graph_scale = false,
stippled_borders = 0,
color0 = 'd9e0ee',
color1 = '9999ff',
uppercase = false,
use_spacer = 'none',
use_xft = true,
${extra}
}
conky.text = [[
${text}
]]
'';
in {
name = "conky-${name}";
value = {
Unit = {
Description = "Run conky ${name}";
};
Service = {
ExecStart =
(pkgs.writeShellScript "conky-${name}" ''
service = name:
{ extra, text, wait, }:
let
config-file = builtins.toFile "conky-${name}.conf" ''
conky.config = {
background = false,
border_width = 0,
cpu_avg_samples = 2,
double_buffer = true,
draw_borders = false,
draw_graph_borders = false,
draw_outline = false,
draw_shades = false,
extra_newline = false,
font = 'CozetteVector:pixelsize=12',
gap_y = 1,
minimum_height = 5,
minimum_width = 2,
max_text_width = 25,
net_avg_samples = 2,
no_buffers = true,
out_to_console = false,
out_to_ncurses = false,
out_to_stderr = false,
out_to_x = true,
own_window = true,
own_window_class = 'Conky',
own_window_type = 'panel',
own_window_argb_visual = true,
own_window_argb_value = 0,
show_graph_range = false,
show_graph_scale = false,
stippled_borders = 0,
color0 = 'd9e0ee',
color1 = '9999ff',
uppercase = false,
use_spacer = 'none',
use_xft = true,
${extra}
}
conky.text = [[
${text}
]]
'';
in {
name = "conky-${name}";
value = {
Unit = { Description = "Run conky ${name}"; };
Service = {
ExecStart = (pkgs.writeShellScript "conky-${name}" ''
${lib.getExe pkgs.conky} -i ${toString wait} -c ${config-file}
${lib.getExe pkgs.conky} -c ${config-file}
'')
.outPath;
Restart = "always";
RestartSec = "10s";
'').outPath;
Restart = "always";
RestartSec = "10s";
};
Install.WantedBy = [ "default.target" ];
};
Install.WantedBy = ["default.target"];
};
};
in {
systemd.user.services = lib.mapAttrs' service {
status = {

View file

@ -1,35 +1,25 @@
{
pkgs,
lib,
...
}: let
plans =
pkgs.privateValue
{
"workDay" = "pass";
"weekend" = "pass";
}
"plans";
createPlans =
pkgs.writeHaskellScript
{
name = "create-plans";
bins = [pkgs.khal pkgs.vdirsyncer];
imports = [
"Data.Time"
];
} ''
main = do
today <- localDay . zonedTimeToLocalTime <$> getZonedTime
[0..7] & fmap (`addDays` today) & mapM_ \day -> do
planned <- khal ["list", "-a", "Planung", show day, "06:00", "24h", "--notstarted"] |> captureTrim
when (LBS.null planned) $ do
say $ "Creating events for " <> show day
if (dayOfWeek day `elem` [Saturday, Sunday]) then do
${plans.weekend}
else do
${plans.workDay}
'';
{ pkgs, lib, ... }:
let
plans = pkgs.privateValue {
"workDay" = "pass";
"weekend" = "pass";
} "plans";
createPlans = pkgs.writeHaskellScript {
name = "create-plans";
bins = [ pkgs.khal pkgs.vdirsyncer ];
imports = [ "Data.Time" ];
} ''
main = do
today <- localDay . zonedTimeToLocalTime <$> getZonedTime
[0..7] & fmap (`addDays` today) & mapM_ \day -> do
planned <- khal ["list", "-a", "Planung", show day, "06:00", "24h", "--notstarted"] |> captureTrim
when (LBS.null planned) $ do
say $ "Creating events for " <> show day
if (dayOfWeek day `elem` [Saturday, Sunday]) then do
${plans.weekend}
else do
${plans.workDay}
'';
sync = "${lib.getExe pkgs.vdirsyncer} sync nextcloud_calendar/planung";
in {
systemd.user = {
@ -37,15 +27,12 @@ in {
Unit.Description = "Create planning appointments in calendar";
Service = {
Type = "oneshot";
ExecStart =
(
pkgs.writeShellScript "update-plans" (lib.concatStringsSep "\n" [
"set -e"
sync
(lib.getExe createPlans)
])
)
.outPath;
ExecStart = (pkgs.writeShellScript "update-plans"
(lib.concatStringsSep "\n" [
"set -e"
sync
(lib.getExe createPlans)
])).outPath;
Restart = "on-failure";
RestartSec = 60;
};
@ -53,7 +40,7 @@ in {
timers.create-plans = {
Unit.Description = "Create planning appointments in calendar";
Timer.OnCalendar = "00:01:00";
Install.WantedBy = ["timers.target"];
Install.WantedBy = [ "timers.target" ];
};
};
}

View file

@ -1,9 +1,4 @@
{
pkgs,
config,
lib,
...
}: {
{ pkgs, config, lib, ... }: {
imports = [
./zsh
./home-options.nix
@ -69,7 +64,8 @@
git = {
aliases = {
sync = "!git pull -r && git push";
cpr = "!f() { git fetch origin refs/pull/$1/head && git checkout FETCH_HEAD; }; f";
cpr =
"!f() { git fetch origin refs/pull/$1/head && git checkout FETCH_HEAD; }; f";
};
extraConfig = {
@ -131,60 +127,33 @@
};
home = {
packages =
builtins.attrValues {
inherit
(pkgs)
go
gdb
mpc_cli
ncmpcpp
shfmt
astyle
nodejs
tasksh
magic-wormhole
alejandra
nix-top
nix-diff
matrix-commander
upterm
lazygit
gh
ledger
aqbanking
;
inherit (pkgs.haskellPackages) hledger hledger-ui hledger-web;
mytmux = pkgs.writeShellScriptBin "mytmux" ''
session=$(${pkgs.tmux}/bin/tmux ls | grep -v attached | head -1 | cut -f1 -d:)
if [[ -n $session ]]; then
exec ${pkgs.tmux}/bin/tmux attach -t $session;
else
exec ${pkgs.tmux}/bin/tmux;
fi
'';
}
++ [
(
pkgs.writeShellScriptBin "unlock-ssh" ''
SSH_ASKPASS="print-ssh-pw" DISPLAY="a" ssh-add < /dev/null
''
)
(
pkgs.writeShellScriptBin "print-ssh-pw"
"rbw get ${config.m-0.hostName}.m-0.eu ssh-key"
)
(
pkgs.writeShellScriptBin "dingdingding" (builtins.readFile ./signal.sh)
)
];
packages = builtins.attrValues {
inherit (pkgs)
go gdb mpc_cli ncmpcpp shfmt astyle nodejs tasksh magic-wormhole
alejandra nix-top nix-diff matrix-commander upterm lazygit gh ledger
aqbanking;
inherit (pkgs.haskellPackages) hledger hledger-ui hledger-web;
mytmux = pkgs.writeShellScriptBin "mytmux" ''
session=$(${pkgs.tmux}/bin/tmux ls | grep -v attached | head -1 | cut -f1 -d:)
if [[ -n $session ]]; then
exec ${pkgs.tmux}/bin/tmux attach -t $session;
else
exec ${pkgs.tmux}/bin/tmux;
fi
'';
} ++ [
(pkgs.writeShellScriptBin "unlock-ssh" ''
SSH_ASKPASS="print-ssh-pw" DISPLAY="a" ssh-add < /dev/null
'')
(pkgs.writeShellScriptBin "print-ssh-pw"
"rbw get ${config.m-0.hostName}.m-0.eu ssh-key")
(pkgs.writeShellScriptBin "dingdingding" (builtins.readFile ./signal.sh))
];
sessionVariables = {
PATH = "$HOME/.nix-profile/bin:$PATH";
BROWSER = "firefox";
SUDO_ASKPASS = toString (
pkgs.writeShellScript "print-sudo-pw"
"rbw get ${config.m-0.hostName}.m-0.eu ${config.home.username}"
);
SUDO_ASKPASS = toString (pkgs.writeShellScript "print-sudo-pw"
"rbw get ${config.m-0.hostName}.m-0.eu ${config.home.username}");
};
};
@ -208,17 +177,17 @@
mimeApps = {
enable = true;
defaultApplications = {
"application/pdf" = ["org.gnome.Evince.desktop"];
"x-scheme-handler/http" = ["firefox.desktop"];
"x-scheme-handler/https" = ["firefox.desktop"];
"x-scheme-handler/chrome" = ["firefox.desktop"];
"text/html" = ["firefox.desktop"];
"application/x-extension-htm" = ["firefox.desktop"];
"application/x-extension-html" = ["firefox.desktop"];
"application/x-extension-shtml" = ["firefox.desktop"];
"application/xhtml+xml" = ["firefox.desktop"];
"application/x-extension-xhtml" = ["firefox.desktop"];
"application/x-extension-xht" = ["firefox.desktop"];
"application/pdf" = [ "org.gnome.Evince.desktop" ];
"x-scheme-handler/http" = [ "firefox.desktop" ];
"x-scheme-handler/https" = [ "firefox.desktop" ];
"x-scheme-handler/chrome" = [ "firefox.desktop" ];
"text/html" = [ "firefox.desktop" ];
"application/x-extension-htm" = [ "firefox.desktop" ];
"application/x-extension-html" = [ "firefox.desktop" ];
"application/x-extension-shtml" = [ "firefox.desktop" ];
"application/xhtml+xml" = [ "firefox.desktop" ];
"application/x-extension-xhtml" = [ "firefox.desktop" ];
"application/x-extension-xht" = [ "firefox.desktop" ];
};
};
userDirs = {

View file

@ -1,8 +1,5 @@
{
pkgs,
config,
...
}: let
{ pkgs, config, ... }:
let
simpleDesktopItem = name: command:
pkgs.makeDesktopItem {
inherit name;
@ -19,5 +16,6 @@
superSimpleDesktopItem = name: simpleDesktopItem name name;
terminalDesktopItem = name: namedTerminalDesktopItem name name;
in {
home.packages = map superSimpleDesktopItem ["kassandra2"] ++ map terminalDesktopItem ["unlock-ssh"];
home.packages = map superSimpleDesktopItem [ "kassandra2" ]
++ map terminalDesktopItem [ "unlock-ssh" ];
}

View file

@ -1,18 +1,12 @@
{
pkgs,
config,
...
}: {
{ pkgs, config, ... }: {
home = {
# This fixes border drawing but makes neo wonky. sessionVariables.NIXOS_OZONE_WL = "1";
packages = builtins.attrValues {
zoom = pkgs.zoom-us.overrideAttrs (old: {
postFixup =
old.postFixup
+ ''
wrapProgram $out/bin/zoom-us --unset XDG_SESSION_TYPE
wrapProgram $out/bin/zoom --unset XDG_SESSION_TYPE
'';
postFixup = old.postFixup + ''
wrapProgram $out/bin/zoom-us --unset XDG_SESSION_TYPE
wrapProgram $out/bin/zoom --unset XDG_SESSION_TYPE
'';
});
mic-check = pkgs.writeShellScriptBin "mic-check" ''
echo "Activating loopback!"
@ -26,72 +20,37 @@
inherit (pkgs.gnome) nautilus;
inherit (pkgs.xorg) xbacklight;
inherit
(pkgs)
# web
chromium
mumble
upower
speedtest-cli
acpi
inherit (pkgs)
# web
chromium mumble upower speedtest-cli acpi
# tools & office
feh
gimp
imagemagick
libreoffice-fresh
xournal
musescore
handbrake
evince
abcde
beets
zbar
feh gimp imagemagick libreoffice-fresh xournal musescore handbrake
evince abcde beets zbar
# media
ncpamixer
pavucontrol
playerctl
deluge
gmpc
vlc
yt-dlp
spotdl
ffmpeg
syncplay
esphome
ncpamixer pavucontrol playerctl deluge gmpc vlc yt-dlp spotdl ffmpeg
syncplay esphome
# To flash devices
esptool
# provides esptool.py
lm_sensors
xwayland
xdg_utils
libnotify
shotcut
audacity
paprefs
wl-clipboard
dconf2nix
chrysalis
;
inherit
(pkgs.gnome)
dconf-editor
gnome-tweaks
adwaita-icon-theme
gnome-session
;
lm_sensors xwayland xdg_utils libnotify shotcut audacity paprefs
wl-clipboard dconf2nix chrysalis;
inherit (pkgs.gnome)
dconf-editor gnome-tweaks adwaita-icon-theme gnome-session;
};
file.".zprofile".text = ". $HOME/.nix-profile/etc/profile.d/hm-session-vars.sh";
file.".zprofile".text =
". $HOME/.nix-profile/etc/profile.d/hm-session-vars.sh";
};
programs.password-store = {
package = pkgs.pass-wayland.withExtensions (exts: [exts.pass-otp]);
package = pkgs.pass-wayland.withExtensions (exts: [ exts.pass-otp ]);
enable = true;
settings.PASSWORD_STORE_DIR = "${config.home.homeDirectory}/git/password-store";
settings.PASSWORD_STORE_DIR =
"${config.home.homeDirectory}/git/password-store";
};
gtk = {
enable = true;
@ -108,11 +67,9 @@
package = pkgs.catppuccin-gtk.override {
variant = "mocha";
size = "compact";
tweaks = ["rimless"];
tweaks = [ "rimless" ];
};
};
gtk3.bookmarks = [
"ftp://fluffy.lo.m-0.eu"
];
gtk3.bookmarks = [ "ftp://fluffy.lo.m-0.eu" ];
};
}

View file

@ -1,26 +1,22 @@
{
pkgs,
lib,
...
}: {
{ pkgs, lib, ... }: {
systemd.user = {
services.fetch-banking = {
Unit.Description = "Fetch banking";
Service = {
Type = "oneshot";
Environment = "PATH=${lib.makeBinPath [pkgs.coreutils pkgs.git pkgs.pass pkgs.gnupg]}";
ExecStart = toString (
pkgs.writeShellScript "fetch-banking" ''
cd ~/git/buchhaltung
exec ${pkgs.nix}/bin/nix develop -c ${pkgs.nix}/bin/nix run ".#autoupdate"
''
);
Environment = "PATH=${
lib.makeBinPath [ pkgs.coreutils pkgs.git pkgs.pass pkgs.gnupg ]
}";
ExecStart = toString (pkgs.writeShellScript "fetch-banking" ''
cd ~/git/buchhaltung
exec ${pkgs.nix}/bin/nix develop -c ${pkgs.nix}/bin/nix run ".#autoupdate"
'');
};
};
timers.fetch-banking = {
Unit.Description = "Fetch banking";
Timer.OnCalendar = "22:00";
Install.WantedBy = ["timers.target"];
Install.WantedBy = [ "timers.target" ];
};
};
}

View file

@ -1,5 +1,5 @@
{pkgs, ...}: {
home.packages = [pkgs.firefox];
{ pkgs, ... }: {
home.packages = [ pkgs.firefox ];
home.sessionVariables = {
# So that electron can open firefox links. See
# Issue: https://github.com/electron/electron/issues/28436

View file

@ -1,8 +1,5 @@
{
pkgs,
config,
...
}: let
{ pkgs, config, ... }:
let
gw2dir = "${config.home.homeDirectory}/.volatile/GW2";
wine = pkgs.wineWowPackages.staging;
gw2env = ''
@ -23,7 +20,8 @@
export WINEESYNC=1
'';
dxvk = fetchTarball {
url = "https://github.com/doitsujin/dxvk/releases/download/v1.7.2/dxvk-1.7.2.tar.gz";
url =
"https://github.com/doitsujin/dxvk/releases/download/v1.7.2/dxvk-1.7.2.tar.gz";
sha256 = "07q9fsrvjq2ndnhd93000jw89bkaw6hdi2yhl4d6j8n4ak71r8pv";
};
gw2installdxvk = pkgs.writeShellScriptBin "gw2-install-dxvk" ''
@ -54,10 +52,8 @@ in {
username = "maralorn";
token = pkgs.privateValue "" "factorio";
};
inherit
(pkgs) #steam minetest
minecraft
;
inherit (pkgs) # steam minetest
minecraft;
inherit gw2run gw2setup wine gw2installdxvk;
};
}

View file

@ -1,3 +1 @@
_: {
programs.git.signing.key = "6C3D12CD88CDF46C5EAF4D12226A2D41EF5378C9";
}
_: { programs.git.signing.key = "6C3D12CD88CDF46C5EAF4D12226A2D41EF5378C9"; }

View file

@ -1,65 +1,51 @@
{
pkgs,
lib,
config,
...
} @ args: let
{ pkgs, lib, config, ... }@args:
let
hotkeys = pkgs.writeShellScriptBin "hotkeys" ''
${pkgs.wizards-dialog}/bin/hotkeys ${pkgs.writeText "hotkeys.yaml" (builtins.toJSON (import ./hotkeys.nix args))}
${pkgs.wizards-dialog}/bin/hotkeys ${
pkgs.writeText "hotkeys.yaml"
(builtins.toJSON (import ./hotkeys.nix args))
}
'';
extensions = builtins.attrValues {
inherit
(pkgs.gnomeExtensions)
appindicator
window-is-ready-remover
nothing-to-say
windownavigator
user-themes
dash-to-panel
removable-drive-menu
pop-shell
notifications-to-file
caffeine
;
inherit (pkgs.gnomeExtensions)
appindicator window-is-ready-remover nothing-to-say windownavigator
user-themes dash-to-panel removable-drive-menu pop-shell
notifications-to-file caffeine;
};
inherit (lib.hm.gvariant) mkTuple mkUint32;
font = "Monospace 9";
in {
home.packages = extensions ++ [hotkeys];
home.packages = extensions ++ [ hotkeys ];
services.gpg-agent.pinentryFlavor = "gnome3";
dconf.settings = {
"org/gnome/desktop/notifications" = {
show-banners = false;
show-in-lock-screen = false;
};
"org/gnome/shell/keybindings" = {
"toggle-overview" = [];
};
"org/gnome/shell/keybindings" = { "toggle-overview" = [ ]; };
"org/gnome/desktop/wm/keybindings" = {
switch-input-source = [];
switch-input-source-backward = [];
switch-applications = [];
switch-applications-backward = [];
minimize = [];
maximize = [];
unmaximize = [];
cycle-windows = ["<Super>Tab"];
cycle-windows-backward = ["<Shift><Super>Tab"];
close = ["<Super>q"];
move-to-monitor-down = [];
move-to-monitor-left = [];
move-to-monitor-right = [];
move-to-monitor-up = [];
toggle-fullscreen = ["<Super>f"];
switch-input-source = [ ];
switch-input-source-backward = [ ];
switch-applications = [ ];
switch-applications-backward = [ ];
minimize = [ ];
maximize = [ ];
unmaximize = [ ];
cycle-windows = [ "<Super>Tab" ];
cycle-windows-backward = [ "<Shift><Super>Tab" ];
close = [ "<Super>q" ];
move-to-monitor-down = [ ];
move-to-monitor-left = [ ];
move-to-monitor-right = [ ];
move-to-monitor-up = [ ];
toggle-fullscreen = [ "<Super>f" ];
};
"org/gnome/mutter" = {
dynamic-workspaces = true;
};
"org/gnome/mutter" = { dynamic-workspaces = true; };
"org/gnome/mutter/keybindings" = {
toggle-tiled-left = [];
toggle-tiled-right = [];
toggle-tiled-left = [ ];
toggle-tiled-right = [ ];
};
"org/gnome/settings-daemon/plugins/color" = {
@ -73,9 +59,7 @@ in {
sleep-inactive-ac-type = "suspend";
};
"org/gnome/desktop/peripherals/mouse" = {
speed = 1;
};
"org/gnome/desktop/peripherals/mouse" = { speed = 1; };
"org/gnome/desktop/interface" = {
document-font-name = font;
@ -88,9 +72,7 @@ in {
locate-pointer = true;
};
"org/gnome/desktop/calendar" = {
show-weekdate = true;
};
"org/gnome/desktop/calendar" = { show-weekdate = true; };
"org/gnome/desktop/wm/preferences" = {
auto-raise = true;
@ -108,9 +90,7 @@ in {
name = "Catppuccin-Mocha-Compact-Blue-Dark";
};
"system/locale" = {
region = "en_DK.UTF-8";
};
"system/locale" = { region = "en_DK.UTF-8"; };
"org/gnome/desktop/screensaver" = {
lock-delay = "0"; # lock screen immediately on screen blank
@ -129,25 +109,26 @@ in {
tile-by-default = true;
active-hint = true;
hint-color-rgba = "rgba(48, 0, 208,0.5)";
tile-enter = ["<Super>t"];
tile-move-left-global = ["<Super><Shift>Left"];
tile-move-right-global = ["<Super><Shift>Right"];
tile-move-up-global = ["<Super><Shift>Up"];
tile-move-down-global = ["<Super><Shift>Down"];
tile-resize-left = ["n"];
tile-resize-right = ["t"];
tile-resize-up = ["g"];
tile-resize-down = ["r"];
pop-workspace-up = [];
pop-workspace-down = [];
pop-monitor-left = [];
pop-monitor-right = [];
pop-monitor-up = [];
pop-monitor-down = [];
tile-enter = [ "<Super>t" ];
tile-move-left-global = [ "<Super><Shift>Left" ];
tile-move-right-global = [ "<Super><Shift>Right" ];
tile-move-up-global = [ "<Super><Shift>Up" ];
tile-move-down-global = [ "<Super><Shift>Down" ];
tile-resize-left = [ "n" ];
tile-resize-right = [ "t" ];
tile-resize-up = [ "g" ];
tile-resize-down = [ "r" ];
pop-workspace-up = [ ];
pop-workspace-down = [ ];
pop-monitor-left = [ ];
pop-monitor-right = [ ];
pop-monitor-up = [ ];
pop-monitor-down = [ ];
};
"org/gnome/shell/extensions/dash-to-panel" = {
panel-element-positions = ''{"0":[{"element":"showAppsButton","visible":false,"position":"stackedTL"},{"element":"dateMenu","visible":false,"position":"stackedTL"},{"element":"activitiesButton","visible":false,"position":"stackedTL"},{"element":"taskbar","visible":false,"position":"stackedTL"},{"element":"leftBox","visible":false,"position":"stackedTL"},{"element":"centerBox","visible":false,"position":"stackedBR"},{"element":"rightBox","visible":true,"position":"stackedBR"},{"element":"systemMenu","visible":true,"position":"stackedBR"},{"element":"desktopButton","visible":false,"position":"stackedBR"}]}'';
panel-element-positions = ''
{"0":[{"element":"showAppsButton","visible":false,"position":"stackedTL"},{"element":"dateMenu","visible":false,"position":"stackedTL"},{"element":"activitiesButton","visible":false,"position":"stackedTL"},{"element":"taskbar","visible":false,"position":"stackedTL"},{"element":"leftBox","visible":false,"position":"stackedTL"},{"element":"centerBox","visible":false,"position":"stackedBR"},{"element":"rightBox","visible":true,"position":"stackedBR"},{"element":"systemMenu","visible":true,"position":"stackedBR"},{"element":"desktopButton","visible":false,"position":"stackedBR"}]}'';
panel-positions = ''{"0":"LEFT"}'';
panel-anchors = ''{"0":"END"}'';
panel-sizes = ''{"0":24}'';
@ -160,30 +141,34 @@ in {
};
"org/gnome/desktop/input-sources" = {
sources = [(mkTuple ["xkb" "de+neo"])]; # use neo
sources = [ (mkTuple [ "xkb" "de+neo" ]) ]; # use neo
xkb-options = [
"altwin:swap_lalt_lwin" # swap alt and win
"lv3:menu_switch" # So that gnome-settings does not set it to ralt
];
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/terminal" = {
binding = "<Super>Return";
command = "${config.home.sessionVariables.TERMINAL}";
name = "Terminal";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/terminal" =
{
binding = "<Super>Return";
command = "${config.home.sessionVariables.TERMINAL}";
name = "Terminal";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/hotkeys" = {
binding = "<Super>space";
command = "${config.home.sessionVariables.TERMINAL} ${lib.getExe hotkeys}";
name = "Hotkeys";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/hotkeys" =
{
binding = "<Super>space";
command =
"${config.home.sessionVariables.TERMINAL} ${lib.getExe hotkeys}";
name = "Hotkeys";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/standby" = {
binding = "<Super>F5";
command = "systemctl suspend";
name = "Standby";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/standby" =
{
binding = "<Super>F5";
command = "systemctl suspend";
name = "Standby";
};
"org/gnome/shell/extensions/nothing-to-say" = {
icon-visibility = "always";
@ -195,8 +180,8 @@ in {
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/hotkeys/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/standby/"
];
area-screenshot-clip = ["Print"];
screenshot = [];
area-screenshot-clip = [ "Print" ];
screenshot = [ ];
};
};
}

View file

@ -1,11 +1,11 @@
{pkgs, ...}: {
{ pkgs, ... }: {
systemd.user.services.hoogle = {
Unit.Description = "Hoogle server";
Install.WantedBy = ["graphical-session.target"];
Install.WantedBy = [ "graphical-session.target" ];
Service = {
ExecStart = "${pkgs.ghcWithPackages}/bin/hoogle server --local --links";
Restart = "always";
};
};
home.packages = [pkgs.ghcWithPackages];
home.packages = [ pkgs.ghcWithPackages ];
}

View file

@ -1,3 +1 @@
{pkgs, ...}: {
services.gpg-agent.pinentryFlavor = "curses";
}
{ pkgs, ... }: { services.gpg-agent.pinentryFlavor = "curses"; }

View file

@ -1,33 +1,21 @@
{
pkgs,
config,
...
}: let
{ pkgs, config, ... }:
let
language-servers = {
inherit
(pkgs.nodePackages)
typescript-language-server
vscode-json-languageserver-bin
vscode-html-languageserver-bin
vscode-css-languageserver-bin
;
inherit (pkgs.nodePackages)
typescript-language-server vscode-json-languageserver-bin
vscode-html-languageserver-bin vscode-css-languageserver-bin;
inherit (pkgs.python3Packages) python-lsp-server;
inherit
(pkgs)
rust-analyzer
taplo
inherit (pkgs)
rust-analyzer taplo
# toml
nil
# nix
texlab
# latex
lean
yaml-language-server
ltex-ls
;
lean yaml-language-server ltex-ls;
# languagetool support for markdown
};
in {
@ -68,29 +56,31 @@ in {
"C-f" = ":format";
};
in {
normal =
common_keys
// {
"C-r" = ["extend_to_line_bounds" ":reflow"];
};
select = {
"C-r" = ["extend_to_line_bounds" "join_selections" "keep_primary_selection" "extend_to_line_bounds" ":reflow"];
normal = common_keys // {
"C-r" = [ "extend_to_line_bounds" ":reflow" ];
};
select = {
"C-r" = [
"extend_to_line_bounds"
"join_selections"
"keep_primary_selection"
"extend_to_line_bounds"
":reflow"
];
};
insert = common_keys // {
up = [ "normal_mode" "move_line_up" ];
down = [ "normal_mode" "move_line_down" ];
left = [ "normal_mode" "move_char_left" ];
right = [ "normal_mode" "move_char_right" ];
};
insert =
common_keys
// {
up = ["normal_mode" "move_line_up"];
down = ["normal_mode" "move_line_down"];
left = ["normal_mode" "move_char_left"];
right = ["normal_mode" "move_char_right"];
};
};
editor = {
whitespace.render = {
space = "all";
tab = "all";
};
rulers = [80 100 120];
rulers = [ 80 100 120 ];
lsp.display-messages = true;
indent-guides.render = true;
cursorline = true;
@ -122,7 +112,7 @@ in {
{
name = "markdown";
language-server.command = "ltex-ls";
file-types = ["md" "markdown" "txt"];
file-types = [ "md" "markdown" "txt" ];
config.ltex.additionalRules = {
enablePickyRules = true;
motherTongue = "de-DE";
@ -133,7 +123,7 @@ in {
name = "nix";
formatter = {
command = "alejandra";
args = ["-q"];
args = [ "-q" ];
};
}
];

View file

@ -1,9 +1,9 @@
{lib, ...}: {
{ lib, ... }: {
options = {
m-0 = {
hostName = lib.mkOption {type = lib.types.str;};
hostName = lib.mkOption { type = lib.types.str; };
colors = lib.mkOption {
default = {};
default = { };
type = lib.types.attrs;
};
};

View file

@ -1,22 +1,19 @@
{
pkgs,
config,
lib,
...
}: let
{ pkgs, config, lib, ... }:
let
fork = cmd: "fork ${cmd}";
edit_dir = dir: "sh -c 'cd ${dir}; hx ${dir}'";
with-mic-check = cmd: fork "sh -c '${config.home.sessionVariables.TERMINAL} mic-check; ${cmd}'";
with-mic-check = cmd:
fork "sh -c '${config.home.sessionVariables.TERMINAL} mic-check; ${cmd}'";
in [
{
Orga = [
{Kassandra = fork "kassandra2";}
{Kalendar = "ikhal";}
{Habitica = fork "firefox https://habitica.com";}
{Tasks = "tasksh";}
{Meditate = "meditate";}
{Pythia = "pythia";}
{Notes = edit_dir "~/git/notes";}
{ Kassandra = fork "kassandra2"; }
{ Kalendar = "ikhal"; }
{ Habitica = fork "firefox https://habitica.com"; }
{ Tasks = "tasksh"; }
{ Meditate = "meditate"; }
{ Pythia = "pythia"; }
{ Notes = edit_dir "~/git/notes"; }
];
}
{
@ -24,7 +21,8 @@ in [
Zotero = fork "zotero";
Open = fork "evince ~/git/promotion/out/print.pdf";
Build = "sh -c 'cd ~/git/promotion; nix run'";
Directory = fork "${config.home.sessionVariables.TERMINAL} -D ~/git/promotion";
Directory =
fork "${config.home.sessionVariables.TERMINAL} -D ~/git/promotion";
Edit = edit_dir "~/git/promotion";
};
}
@ -36,47 +34,48 @@ in [
};
}
{
SSH = let
ssh = host: "ssh ${host}";
SSH = let ssh = host: "ssh ${host}";
in [
{"hera via vpn" = ssh "hera.vpn.m-0.eu";}
{"fluffy via vpn" = ssh "fluffy.vpn.m-0.eu";}
{remote-builder = ssh "phoibe.cased.de";}
{ag = ssh "ag-forward";}
{mathe-gateway = ssh "gw";}
{backup-server = ssh "borg.cysec.de";}
{shells = ssh "shells";}
{"bach (ved)" = ssh "bach.vocalensemble-darmstadt.de";}
{"nixbuild.net" = "${pkgs.rlwrap}/bin/rlwrap ssh eu.nixbuild.net shell";}
{"fluffy via local network" = ssh "fluffy.lo.m-0.eu";}
{"hera via public v4" = ssh "hera-v4";}
{"TU Tunnel" = "sshuttle --python python3.9 -r gw 130.83.0.0/16";}
{ "hera via vpn" = ssh "hera.vpn.m-0.eu"; }
{ "fluffy via vpn" = ssh "fluffy.vpn.m-0.eu"; }
{ remote-builder = ssh "phoibe.cased.de"; }
{ ag = ssh "ag-forward"; }
{ mathe-gateway = ssh "gw"; }
{ backup-server = ssh "borg.cysec.de"; }
{ shells = ssh "shells"; }
{ "bach (ved)" = ssh "bach.vocalensemble-darmstadt.de"; }
{
"nixbuild.net" = "${pkgs.rlwrap}/bin/rlwrap ssh eu.nixbuild.net shell";
}
{ "fluffy via local network" = ssh "fluffy.lo.m-0.eu"; }
{ "hera via public v4" = ssh "hera-v4"; }
{ "TU Tunnel" = "sshuttle --python python3.9 -r gw 130.83.0.0/16"; }
];
}
{
Sound = let
mpdclient = host: "sh -c 'switch-mpd ${host}; ncmpcpp -h ${host}'";
in [
{"Play/Pause" = "${pkgs.playerctl}/bin/playerctl play-pause";}
{"MPD lokal" = mpdclient "::";}
{"Lautstärke" = "ncpamixer";}
{Pavucontrol = fork "pavucontrol";}
{
Headset = {
Earplugs = {
connect = "bluetoothctl connect 00:00:AB:BD:7D:68";
disconnect = "bluetoothctl disconnect 00:00:AB:BD:7D:68";
Sound =
let mpdclient = host: "sh -c 'switch-mpd ${host}; ncmpcpp -h ${host}'";
in [
{ "Play/Pause" = "${pkgs.playerctl}/bin/playerctl play-pause"; }
{ "MPD lokal" = mpdclient "::"; }
{ "Lautstärke" = "ncpamixer"; }
{ Pavucontrol = fork "pavucontrol"; }
{
Headset = {
Earplugs = {
connect = "bluetoothctl connect 00:00:AB:BD:7D:68";
disconnect = "bluetoothctl disconnect 00:00:AB:BD:7D:68";
};
Overears = {
connect = "bluetoothctl connect E8:EE:CC:25:66:C3";
disconnect = "bluetoothctl disconnect E8:EE:CC:25:66:C3";
};
};
Overears = {
connect = "bluetoothctl connect E8:EE:CC:25:66:C3";
disconnect = "bluetoothctl disconnect E8:EE:CC:25:66:C3";
};
};
}
{"MPD Lounge" = mpdclient "lounge.w17.io";}
{"MPD Kitchen" = mpdclient "kitchen.w17.io";}
{"MPD Space" = mpdclient "burbon.w17.io";}
];
}
{ "MPD Lounge" = mpdclient "lounge.w17.io"; }
{ "MPD Kitchen" = mpdclient "kitchen.w17.io"; }
{ "MPD Space" = mpdclient "burbon.w17.io"; }
];
}
{
Apps = {
@ -84,7 +83,8 @@ in [
Files = fork "nautilus";
Accounting = {
Update = "nix run ./git/buchhaltung#update";
Display = "hledger -f ~/git/buchhaltung/buchhaltung.journal ui -- --watch --theme=terminal -X -t -E";
Display =
"hledger -f ~/git/buchhaltung/buchhaltung.journal ui -- --watch --theme=terminal -X -t -E";
};
Games = {
GW2 = fork "gw2";
@ -105,14 +105,19 @@ in [
}
{
Passmenu = {
Password = "sh -c '(rbw-fzf | wl-copy) && ${lib.getExe pkgs.termdown} -T \"Clearing password in\" -f term 20 && wl-copy -c'";
Password = "sh -c '(rbw-fzf | wl-copy) && ${
lib.getExe pkgs.termdown
} -T \"Clearing password in\" -f term 20 && wl-copy -c'";
"OTP" = "sh -c 'rbw-totp-fzf | wl-copy'";
};
}
{"Select Mode" = lib.mapAttrs (name: _: "select-mode ${name}") (import ../machines.nix).${config.m-0.hostName};}
{
"Select Mode" = lib.mapAttrs (name: _: "select-mode ${name}")
(import ../machines.nix).${config.m-0.hostName};
}
{
Communication = [
{Matrix = fork "element-desktop";}
{ Matrix = fork "element-desktop"; }
{
Mail = {
Open = "neomutt";
@ -126,15 +131,15 @@ in [
Nixos = with-mic-check "mumble mumble://maralorn@lassul.us/nixos";
};
}
{Weechat = "weechat";}
{Signal = fork "signal-desktop";}
{Zoom = with-mic-check "zoom";}
{Telegram = fork "telegram-desktop";}
{Discord = with-mic-check "Discord";}
{Tmate = "tmate";}
{ Weechat = "weechat"; }
{ Signal = fork "signal-desktop"; }
{ Zoom = with-mic-check "zoom"; }
{ Telegram = fork "telegram-desktop"; }
{ Discord = with-mic-check "Discord"; }
{ Tmate = "tmate"; }
];
}
{"Monitor (btop)" = "btop";}
{ "Monitor (btop)" = "btop"; }
{
"W17" = {
Strichliste = "firefox https://strichliste.w17.io/#!/user/56";
@ -144,5 +149,5 @@ in [
Close = "ssh door@burbon.w17.io close";
};
}
{"Clear Notifications" = "sh -c 'rm -r ~/.notifications/*'";}
{ "Clear Notifications" = "sh -c 'rm -r ~/.notifications/*'"; }
]

View file

@ -1,5 +1,6 @@
{pkgs, ...}: let
dhallFiles = pkgs.runCommand "kassandra-config-src" {} ''
{ pkgs, ... }:
let
dhallFiles = pkgs.runCommand "kassandra-config-src" { } ''
mkdir $out
${pkgs.kassandra-standalone}/bin/kassandra2 print-types > $out/types.dhall
ln -s ${./kassandra}/{config,backend}.dhall $out
@ -7,15 +8,17 @@
'';
backend = pkgs.dhallPackages.buildDhallPackage {
name = "kassandra-backend-config";
code = "${dhallFiles}/backend.dhall : (${dhallFiles}/types.dhall).BackendConfig";
code =
"${dhallFiles}/backend.dhall : (${dhallFiles}/types.dhall).BackendConfig";
source = true;
dependencies = [pkgs.dhallPackages.Prelude];
dependencies = [ pkgs.dhallPackages.Prelude ];
};
standalone = pkgs.dhallPackages.buildDhallPackage {
name = "kassandra-standalone-config";
code = "${dhallFiles}/config.dhall : (${dhallFiles}/types.dhall).StandaloneConfig";
code =
"${dhallFiles}/config.dhall : (${dhallFiles}/types.dhall).StandaloneConfig";
source = true;
dependencies = [pkgs.dhallPackages.Prelude];
dependencies = [ pkgs.dhallPackages.Prelude ];
};
dhallResult = pkgs.recursiveLinkFarm "kassandra-config" {
"backend.dhall" = "${backend}/source.dhall";
@ -23,5 +26,5 @@
};
in {
xdg.configFile.kassandra.source = dhallResult.out;
home.packages = [pkgs.kassandra-standalone];
home.packages = [ pkgs.kassandra-standalone ];
}

View file

@ -1,7 +1,7 @@
{pkgs, ...}: let
calendars = pkgs.privateValue [] "calendars";
{ pkgs, ... }:
let calendars = pkgs.privateValue [ ] "calendars";
in {
home.packages = [pkgs.khal];
home.packages = [ pkgs.khal ];
xdg.configFile."khal/config".text = ''
[locale]
dateformat = "%Y-%m-%d"
@ -10,23 +10,10 @@ in {
[default]
default_calendar = Standard
[calendars]
${
pkgs.lib.concatMapStringsSep "\n" (
{
name,
readOnly ? false,
...
}: ''
[[${name}]]
type = discover
path = ~/.calendars/${name}/*
readonly = ${
if readOnly
then "True"
else "False"
}''
)
calendars
}
${pkgs.lib.concatMapStringsSep "\n" ({ name, readOnly ? false, ... }: ''
[[${name}]]
type = discover
path = ~/.calendars/${name}/*
readonly = ${if readOnly then "True" else "False"}'') calendars}
'';
}

View file

@ -1,5 +1,5 @@
{pkgs, ...}: {
home.packages = [pkgs.khard];
{ pkgs, ... }: {
home.packages = [ pkgs.khard ];
xdg.configFile."khard/khard.conf".text = ''
[addressbooks]
[[Kontakte]]

View file

@ -1,3 +1 @@
{pkgs, ...}: {
home.packages = [pkgs.neomutt];
}
{ pkgs, ... }: { home.packages = [ pkgs.neomutt ]; }

View file

@ -1,9 +1,5 @@
{
pkgs,
lib,
config,
...
}: let
{ pkgs, lib, config, ... }:
let
mail2task = pkgs.writeShellScript "mail2task" ''
set -euo pipefail
${pkgs.isync}/bin/mbsync hera:Move/todo
@ -13,9 +9,9 @@
${pkgs.notmuch}/bin/notmuch new
'';
lists = pkgs.privateValue {
sortLists = [];
stupidLists = [];
notifications = [];
sortLists = [ ];
stupidLists = [ ];
notifications = [ ];
} "mail/filters";
maildir = config.accounts.email.maildirBasePath;
# mhdr -h List-ID -d Maildir/hera/Archiv/unsortiert | sort | sed 's/^.*<\(.*\)>$/\1/' | uniq | xargs -I '{}' sh -c "notmuch count List:{} | sed 's/$/: {}/'" | sort
@ -29,89 +25,83 @@
toFolder (lib.concatStringsSep "." (lib.splitString "@" name));
toFolder = name:
lib.concatStringsSep "/" (lib.reverseList (lib.splitString "." name));
simple = filter: target: {inherit filter target;};
simple = filter: target: { inherit filter target; };
notifications = notify:
simple "from:${notify}" "notifications/${mailToFolder notify}";
stupidList = list: simple "to:${list}" "list/${mailToFolder list}";
simpleSortList = listName:
simple "List:${listName}" "list/${toFolder listName}";
};
myFilters =
builtins.map filter.simpleSortList lists.sortLists
myFilters = builtins.map filter.simpleSortList lists.sortLists
++ builtins.map filter.stupidList lists.stupidLists
++ builtins.map filter.notifications lists.notifications;
sortMail =
pkgs.writeHaskellScript
{
name = "sort-mail-archive";
bins = [pkgs.notmuch pkgs.coreutils pkgs.mblaze pkgs.findutils];
imports = [
"Text.Megaparsec"
"Text.Megaparsec.Char"
"Text.Megaparsec.Char.Lexer"
"qualified Data.List.NonEmpty as NE"
"qualified Data.Text as T"
"System.Environment (setEnv)"
];
} ''
reScan = notmuch "new" "--quiet"
sortMail = pkgs.writeHaskellScript {
name = "sort-mail-archive";
bins = [ pkgs.notmuch pkgs.coreutils pkgs.mblaze pkgs.findutils ];
imports = [
"Text.Megaparsec"
"Text.Megaparsec.Char"
"Text.Megaparsec.Char.Lexer"
"qualified Data.List.NonEmpty as NE"
"qualified Data.Text as T"
"System.Environment (setEnv)"
];
} ''
reScan = notmuch "new" "--quiet"
findFilterMail :: (Text,Text) -> IO (Maybe (LByteString, Text, Text))
findFilterMail (filter_, target) = do
files <- notmuch "search" "--output" "files" (toString filter_) "folder:${unsortedSuffix}" |> capture
pure $ if (LBS.length files > 0) then Just (files, filter_, target) else Nothing
findFilterMail :: (Text,Text) -> IO (Maybe (LByteString, Text, Text))
findFilterMail (filter_, target) = do
files <- notmuch "search" "--output" "files" (toString filter_) "folder:${unsortedSuffix}" |> capture
pure $ if (LBS.length files > 0) then Just (files, filter_, target) else Nothing
executeFilterMail :: (LByteString, Text, Text) -> IO ()
executeFilterMail (files, filter_, target) = do
say [i|Sorting "#{filter_}" into #{target}|]
writeOutput files |> mscan
mmkdir ([i|${archive}/#{target}|] :: String)
writeOutput files |> mrefile ([i|${archive}/#{target}|] :: String)
executeFilterMail :: (LByteString, Text, Text) -> IO ()
executeFilterMail (files, filter_, target) = do
say [i|Sorting "#{filter_}" into #{target}|]
writeOutput files |> mscan
mmkdir ([i|${archive}/#{target}|] :: String)
writeOutput files |> mrefile ([i|${archive}/#{target}|] :: String)
myFilters :: [(Text,Text)]
myFilters = [${
lib.concatStringsSep ","
(
builtins.map ({
filter,
target,
}: ''("${filter}","${target}")'')
myFilters
)
}]
myFilters :: [(Text,Text)]
myFilters = [${
lib.concatStringsSep ","
(builtins.map ({ filter, target, }: ''("${filter}","${target}")'')
myFilters)
}]
filtersFromTo :: Text -> Maybe (Text,Text)
filtersFromTo = filtersFromField "to" [toToName]
toToName :: Text -> Maybe Text
toToName (T.splitOn "@" -> [name, "maralorn.de"])
| not (T.isInfixOf "randy" name) = Just . ("to/" <>) . T.intercalate "_" . T.splitOn "." $ name
toToName _ = Nothing
filtersFromField :: Text -> [Text-> Maybe Text] -> Text -> Maybe (Text,Text)
filtersFromField field filters text = fmap ([i|#{field}:#{text}|],) . viaNonEmpty Relude.head . mapMaybe ($ text) $ filters
filtersFromListIDs :: Text -> Maybe (Text,Text)
filtersFromListIDs = filtersFromField "List" [githubNameFolderFromId, gitlabNameFolderFromId]
githubNameFolderFromId :: Text -> Maybe Text
githubNameFolderFromId (reverse . T.splitOn "." -> ("com":"github":org:name)) = Just [i|github/#{org}/#{T.intercalate "_" $ reverse name}|]
githubNameFolderFromId _ = Nothing
gitlabNameFolderFromId :: Text -> Maybe Text
gitlabNameFolderFromId (reverse . T.splitOn "." -> ("de":"ccc":"darmstadt":"git":org:name1:name)) = Just [i|cda-gitlab/#{org}/#{T.intercalate "_" . toList . Relude.tail $ NE.reverse (name1:|name)}|]
gitlabNameFolderFromId _ = Nothing
filtersFromTo :: Text -> Maybe (Text,Text)
filtersFromTo = filtersFromField "to" [toToName]
toToName :: Text -> Maybe Text
toToName (T.splitOn "@" -> [name, "maralorn.de"])
| not (T.isInfixOf "randy" name) = Just . ("to/" <>) . T.intercalate "_" . T.splitOn "." $ name
toToName _ = Nothing
filtersFromField :: Text -> [Text-> Maybe Text] -> Text -> Maybe (Text,Text)
filtersFromField field filters text = fmap ([i|#{field}:#{text}|],) . viaNonEmpty Relude.head . mapMaybe ($ text) $ filters
filtersFromListIDs :: Text -> Maybe (Text,Text)
filtersFromListIDs = filtersFromField "List" [githubNameFolderFromId, gitlabNameFolderFromId]
githubNameFolderFromId :: Text -> Maybe Text
githubNameFolderFromId (reverse . T.splitOn "." -> ("com":"github":org:name)) = Just [i|github/#{org}/#{T.intercalate "_" $ reverse name}|]
githubNameFolderFromId _ = Nothing
gitlabNameFolderFromId :: Text -> Maybe Text
gitlabNameFolderFromId (reverse . T.splitOn "." -> ("de":"ccc":"darmstadt":"git":org:name1:name)) = Just [i|cda-gitlab/#{org}/#{T.intercalate "_" . toList . Relude.tail $ NE.reverse (name1:|name)}|]
gitlabNameFolderFromId _ = Nothing
type Parser = Parsec Text Text
listId :: Parser Text
listId = manyTill anySingle (char '<') *> (toText <$> manyTill anySingle (char '>'))
type Parser = Parsec Text Text
listId :: Parser Text
listId = manyTill anySingle (char '<') *> (toText <$> manyTill anySingle (char '>'))
main = do
setEnv "MBLAZE_PAGER" "cat"
setEnv "NOTMUCH_CONFIG" "${config.home.sessionVariables.NOTMUCH_CONFIG or ""}"
reScan
(listIDs,tos) <- concurrently (mhdr "-h" "List-ID" "-d" "${unsorted}" |> capture) (mhdr "-h" "To" "-d" "${unsorted}" "-A" |> capture)
let listFilters = mapMaybe filtersFromListIDs . sortNub . mapMaybe (parseMaybe listId) . lines . decodeUtf8 $ listIDs
toFilters = mapMaybe filtersFromTo . sortNub . fmap (\x -> maybe x Relude.id $ parseMaybe listId x) . lines . decodeUtf8 $ tos
applicableFilters <- catMaybes <$> forConcurrently (listFilters <> myFilters <> toFilters) findFilterMail
for_ applicableFilters executeFilterMail
reScan
'';
main = do
setEnv "MBLAZE_PAGER" "cat"
setEnv "NOTMUCH_CONFIG" "${
config.home.sessionVariables.NOTMUCH_CONFIG or ""
}"
reScan
(listIDs,tos) <- concurrently (mhdr "-h" "List-ID" "-d" "${unsorted}" |> capture) (mhdr "-h" "To" "-d" "${unsorted}" "-A" |> capture)
let listFilters = mapMaybe filtersFromListIDs . sortNub . mapMaybe (parseMaybe listId) . lines . decodeUtf8 $ listIDs
toFilters = mapMaybe filtersFromTo . sortNub . fmap (\x -> maybe x Relude.id $ parseMaybe listId x) . lines . decodeUtf8 $ tos
applicableFilters <- catMaybes <$> forConcurrently (listFilters <> myFilters <> toFilters) findFilterMail
for_ applicableFilters executeFilterMail
reScan
'';
in {
services.mbsync = {
postExec = "${sortMail}/bin/sort-mail-archive";
@ -120,7 +110,7 @@ in {
accounts.email.accounts = {
hera.imapnotify = {
onNotifyPost = toString mail2task;
boxes = ["Move/todo"];
boxes = [ "Move/todo" ];
};
};
}

View file

@ -1,21 +1,12 @@
{
lib,
config,
pkgs,
...
}: let
inherit
(pkgs.privateValue {
gpg = "";
name = "";
mail = "";
alternates = [];
} "mail/me")
gpg
name
mail
alternates
;
{ lib, config, pkgs, ... }:
let
inherit (pkgs.privateValue {
gpg = "";
name = "";
mail = "";
alternates = [ ];
} "mail/me")
gpg name mail alternates;
quick-mail-sync = pkgs.writeShellScriptBin "quick-mail-sync" ''
${pkgs.isync}/bin/mbsync hera:INBOX,Code
${pkgs.notmuch}/bin/notmuch new
@ -32,12 +23,13 @@ in {
};
systemd.user.timers.mbsync.Timer.RandomizedDelaySec = "10m";
accounts.email.accounts = lib.recursiveUpdate (pkgs.privateValue {} "mail/accounts") {
hera = {
passwordCommand = "${pkgs.coreutils}/bin/cat /run/agenix/mail-password";
imapnotify.onNotify = lib.getExe quick-mail-sync;
accounts.email.accounts =
lib.recursiveUpdate (pkgs.privateValue { } "mail/accounts") {
hera = {
passwordCommand = "${pkgs.coreutils}/bin/cat /run/agenix/mail-password";
imapnotify.onNotify = lib.getExe quick-mail-sync;
};
};
};
systemd.user.services = let
hasImapHost = name: account: account.imap != null;
@ -53,18 +45,17 @@ in {
done
'');
};
Install.WantedBy = ["default.target"];
Install.WantedBy = [ "default.target" ];
};
};
in
lib.mapAttrs' mkWatchService (lib.filterAttrs hasImapHost config.accounts.email.accounts)
// {
mbsync.Service = {
Environment = "PATH=${lib.makeBinPath [pkgs.rbw pkgs.coreutils]}";
Restart = "on-failure";
RestartSec = "30s";
};
in lib.mapAttrs' mkWatchService
(lib.filterAttrs hasImapHost config.accounts.email.accounts) // {
mbsync.Service = {
Environment = "PATH=${lib.makeBinPath [ pkgs.rbw pkgs.coreutils ]}";
Restart = "on-failure";
RestartSec = "30s";
};
};
programs = {
msmtp.enable = true;
@ -78,17 +69,18 @@ in {
${pkgs.notmuch}/bin/notmuch tag -spam -- "(not folder:/Junk|Spam|SPAM/) tag:spam"
'';
new = {
tags = [];
ignore = [".isyncuidmap.db"];
tags = [ ];
ignore = [ ".isyncuidmap.db" ];
};
maildir.synchronizeFlags = true;
};
};
home = {
packages = [quick-mail-sync];
packages = [ quick-mail-sync ];
file = let
mutt_alternates = "@maralorn.de " + (builtins.concatStringsSep " " alternates);
mutt_alternates = "@maralorn.de "
+ (builtins.concatStringsSep " " alternates);
show-sidebar = pkgs.writeText "show-sidebar" ''
set sidebar_visible=yes
bind index <up> sidebar-prev
@ -117,7 +109,9 @@ in {
audio/*; ${pkgs.xdg_utils}/bin/xdg-open %s > /dev/null
'';
# See: https://unix.stackexchange.com/questions/44358/mutt-mark-as-read-and-delete
move-message-macro = key: dir: name: ''macro index,pager ${key} ":set confirmappend=no resolve=no\n<clear-flag>N<save-message>=hera/${dir}\n:set confirmappend=yes resolve=yes\n<next-undeleted>" "move message to ${name}"'';
move-message-macro = key: dir: name:
''
macro index,pager ${key} ":set confirmappend=no resolve=no\n<clear-flag>N<save-message>=hera/${dir}\n:set confirmappend=yes resolve=yes\n<next-undeleted>" "move message to ${name}"'';
in {
".neomuttrc".text = ''
set editor = "hx"
@ -133,7 +127,11 @@ in {
${move-message-macro "l" "Move/readlater" "readlater list"}
macro attach 'V' "<pipe-entry>iconv -c --to-code=UTF8 > ~/.cache/mutt/mail.html<enter><shell-escape>firefox ~/.cache/mutt/mail.html<enter>"
macro index,pager <F6> "<shell-escape>${pkgs.zsh}/bin/zsh -c '${pkgs.sieve-connect}/bin/sieve-connect -s ${config.accounts.email.accounts.hera.imap.host or ""} -u ${config.accounts.email.accounts.hera.userName or ""} --passwordfd 3 --edit --remotesieve filter 3<<(cat /run/agenix/mail-password)'\n"
macro index,pager <F6> "<shell-escape>${pkgs.zsh}/bin/zsh -c '${pkgs.sieve-connect}/bin/sieve-connect -s ${
config.accounts.email.accounts.hera.imap.host or ""
} -u ${
config.accounts.email.accounts.hera.userName or ""
} --passwordfd 3 --edit --remotesieve filter 3<<(cat /run/agenix/mail-password)'\n"
macro index,pager A "<pipe-message>${pkgs.khard}/bin/khard add-email<return>" "add sender to to khard"
set query_format="%4c %t %-70.70a %-70.70n %?e?(%e)?"

View file

@ -1,39 +1,33 @@
{
lib,
pkgs,
config,
...
}: let
mail2rss =
pkgs.writeHaskellScript
{
name = "mail2rss";
bins = [pkgs.notmuch pkgs.mblaze pkgs.isync pkgs.rssfeeds];
imports = ["System.Environment (setEnv)"];
} ''
main = do
setEnv "NOTMUCH_CONFIG" "${
config.home.sessionVariables.NOTMUCH_CONFIG or ""
}"
mbsync "-a"
notmuch "new" "--quiet"
mail2rss "${config.accounts.email.maildirBasePath}" "hera/Move/readlater" &> Truncate "/var/www/rss/mails.xml"
files <- notmuch "search" "--output" "files" "folder:hera/Move/readlater" |> capture
writeOutput files |> mrefile "${config.accounts.email.maildirBasePath}/hera/Archiv/unsortiert"
mbsync "-a"
notmuch "new" "--quiet"
'';
{ lib, pkgs, config, ... }:
let
mail2rss = pkgs.writeHaskellScript {
name = "mail2rss";
bins = [ pkgs.notmuch pkgs.mblaze pkgs.isync pkgs.rssfeeds ];
imports = [ "System.Environment (setEnv)" ];
} ''
main = do
setEnv "NOTMUCH_CONFIG" "${
config.home.sessionVariables.NOTMUCH_CONFIG or ""
}"
mbsync "-a"
notmuch "new" "--quiet"
mail2rss "${config.accounts.email.maildirBasePath}" "hera/Move/readlater" &> Truncate "/var/www/rss/mails.xml"
files <- notmuch "search" "--output" "files" "folder:hera/Move/readlater" |> capture
writeOutput files |> mrefile "${config.accounts.email.maildirBasePath}/hera/Archiv/unsortiert"
mbsync "-a"
notmuch "new" "--quiet"
'';
in {
systemd.user = {
timers.mail2rss = {
Timer.OnCalendar = "23:58";
Install.WantedBy = ["timers.target"];
Install.WantedBy = [ "timers.target" ];
};
services = {
mail2rss = {
Unit.Description = "Mail to rss exporter";
Service = {
Environment = "PATH=${lib.makeBinPath [pkgs.coreutils]}";
Environment = "PATH=${lib.makeBinPath [ pkgs.coreutils ]}";
ExecStart = "${mail2rss}/bin/mail2rss";
Type = "oneshot";
};

View file

@ -1,3 +1 @@
{pkgs, ...}: {
home.packages = builtins.attrValues pkgs.mode-scripts;
}
{ pkgs, ... }: { home.packages = builtins.attrValues pkgs.mode-scripts; }

View file

@ -1,3 +1,4 @@
{config, ...}: {
xdg.configFile."monitors.xml".source = ./. + "/${config.m-0.hostName}-monitors.xml";
{ config, ... }: {
xdg.configFile."monitors.xml".source = ./.
+ "/${config.m-0.hostName}-monitors.xml";
}

View file

@ -1,5 +1,5 @@
{pkgs, ...}: {
home.packages = [pkgs.ncmpcpp];
{ pkgs, ... }: {
home.packages = [ pkgs.ncmpcpp ];
home.file.".ncmpcpp/config".text = ''
ask_before_clearing_playlists=no
mouse_support = yes

View file

@ -1,24 +1,26 @@
{
pkgs,
config,
lib,
...
}: let
{ pkgs, config, lib, ... }:
let
audio_dir = "${config.home.homeDirectory}/media/audio";
playlist_dir = "${audio_dir}/playlists";
mprisCfg = config.xdg.configFile."mpDris2/mpDris2.conf";
replace_string = "@HOST@";
in {
home.file."media/audio/playlists" = {
source = pkgs.recursiveLinkFarm "mpd-playlists" (lib.mapAttrs' (name: content: lib.nameValuePair "${name}.m3u" (builtins.toFile "${name}.m3u" content)) {
"radio-swiss-classic" = "https://stream.srg-ssr.ch/m/rsc_de/aacp_96";
"radio-swiss-jazz" = "https://stream.srg-ssr.ch/m/rsj/aacp_96";
"br-klassik" = "http://dispatcher.rndfnk.com/br/brklassik/live/mp3/high";
"klassik-radio-games" = "https://klassikr.streamabc.net/klr-games-mp3-128-1540253";
"klassik-radio-movie" = "https://klassikr.streamabc.net/klr-movie-mp3-128-5213277";
"radio-caprice-power-metal" = "http://79.120.77.11:8000/powermetal";
"metal-hammer" = "https://metal-hammer.stream.laut.fm/metal-hammer";
});
source = pkgs.recursiveLinkFarm "mpd-playlists" (lib.mapAttrs'
(name: content:
lib.nameValuePair "${name}.m3u"
(builtins.toFile "${name}.m3u" content)) {
"radio-swiss-classic" = "https://stream.srg-ssr.ch/m/rsc_de/aacp_96";
"radio-swiss-jazz" = "https://stream.srg-ssr.ch/m/rsj/aacp_96";
"br-klassik" =
"http://dispatcher.rndfnk.com/br/brklassik/live/mp3/high";
"klassik-radio-games" =
"https://klassikr.streamabc.net/klr-games-mp3-128-1540253";
"klassik-radio-movie" =
"https://klassikr.streamabc.net/klr-movie-mp3-128-5213277";
"radio-caprice-power-metal" = "http://79.120.77.11:8000/powermetal";
"metal-hammer" = "https://metal-hammer.stream.laut.fm/metal-hammer";
});
recursive = true;
};
xdg.configFile."mpDris2/mpDris2.conf".enable = false;
@ -46,7 +48,9 @@ in {
home.packages = [
(pkgs.writeShellScriptBin "switch-mpd" ''
mkdir -p ${config.xdg.configHome}/mpDris2
${lib.getExe pkgs.sd} -p ${replace_string} "$1" ${mprisCfg.source} > $HOME/${mprisCfg.target}
${
lib.getExe pkgs.sd
} -p ${replace_string} "$1" ${mprisCfg.source} > $HOME/${mprisCfg.target}
${pkgs.systemd}/bin/systemctl --user restart mpdris2.service
'')
];

View file

@ -1,17 +1,14 @@
{pkgs, ...}: let
script =
(pkgs.recursiveLinkFarm "autosave.lua"
{"share/mpv/scripts/autosave.lua" = ./autosave.lua;})
// {scriptName = "autosave.lua";};
{ pkgs, ... }:
let
script = (pkgs.recursiveLinkFarm "autosave.lua" {
"share/mpv/scripts/autosave.lua" = ./autosave.lua;
}) // {
scriptName = "autosave.lua";
};
in {
programs.mpv = {
enable = true;
config = {
save-position-on-quit = true;
};
scripts = [
pkgs.mpvScripts.mpris
script
];
config = { save-position-on-quit = true; };
scripts = [ pkgs.mpvScripts.mpris script ];
};
}

View file

@ -1,37 +1,36 @@
{pkgs, ...}: let
night-shutdown =
pkgs.writeHaskellScript
{
name = "night-shutdown";
imports = [
"Data.Time.LocalTime"
"Data.Time.Format"
"Data.Time.Clock"
"Control.Concurrent"
"Data.Functor"
];
bins = [pkgs.libnotify pkgs.systemd];
} ''
interval = 5
{ pkgs, ... }:
let
night-shutdown = pkgs.writeHaskellScript {
name = "night-shutdown";
imports = [
"Data.Time.LocalTime"
"Data.Time.Format"
"Data.Time.Clock"
"Control.Concurrent"
"Data.Functor"
];
bins = [ pkgs.libnotify pkgs.systemd ];
} ''
interval = 5
main = forever $ do
time <- getZonedTime
let tod = localTimeOfDay . zonedTimeToLocalTime$ time
hour = todHour tod
minute = todMin tod
evening = hour == 0
night = (hour < 6 && hour >= 1)
action
| evening = notify_send "Shutdown alert!" ([i|Rechner fährt in #{59-minute} Minuten runter.|]::String)
| night = systemctl "poweroff"
| otherwise = pass
action
threadDelay $ (interval - (minute `mod` interval)) * 60 * 1000000
'';
main = forever $ do
time <- getZonedTime
let tod = localTimeOfDay . zonedTimeToLocalTime$ time
hour = todHour tod
minute = todMin tod
evening = hour == 0
night = (hour < 6 && hour >= 1)
action
| evening = notify_send "Shutdown alert!" ([i|Rechner fährt in #{59-minute} Minuten runter.|]::String)
| night = systemctl "poweroff"
| otherwise = pass
action
threadDelay $ (interval - (minute `mod` interval)) * 60 * 1000000
'';
in {
systemd.user.services.night-shutdown = {
Unit.Description = "Night Shutdown";
Service.ExecStart = "${night-shutdown}/bin/night-shutdown";
Install.WantedBy = ["graphical-session.target"];
Install.WantedBy = [ "graphical-session.target" ];
};
}

View file

@ -1,11 +1,6 @@
{
config,
pkgs,
lib,
...
}:
with lib; let
inherit (config.lib) dag;
{ config, pkgs, lib, ... }:
with lib;
let inherit (config.lib) dag;
in {
home.activation.report-changes = dag.entryAnywhere ''
if [[ -n "$oldGenPath" && "$oldGenPath" != "$newGenPath" ]]; then

View file

@ -1,9 +1,4 @@
{
pkgs,
config,
lib,
...
}: {
{ pkgs, config, lib, ... }: {
home = {
username = "maralorn";
homeDirectory = "/home/maralorn";

View file

@ -1,8 +1,5 @@
{
pkgs,
config,
...
}: let
{ pkgs, config, ... }:
let
pythia-path = "${config.home.homeDirectory}/documents/pythia";
pythia = pkgs.writeShellScriptBin "pythia" ''
today=$(date +%Y-%m-%d)
@ -104,4 +101,4 @@
${hold}
exit
'';
in {home.packages = [pythia meditate];}
in { home.packages = [ pythia meditate ]; }

View file

@ -1,8 +1,5 @@
{
pkgs,
config,
...
}: let
{ pkgs, config, ... }:
let
configPath = "${config.home.homeDirectory}/git/config";
configGit = "${pkgs.git}/bin/git -C ${configPath}";
in {
@ -17,7 +14,7 @@ in {
timers.refresh-config = {
Unit.Description = "Fetch config updates";
Timer.OnCalendar = "*:0/5:0";
Install.WantedBy = ["timers.target"];
Install.WantedBy = [ "timers.target" ];
};
};
}

View file

@ -1,7 +1,7 @@
{pkgs, ...}: {
home.packages = [pkgs.zotero];
{ pkgs, ... }: {
home.packages = [ pkgs.zotero ];
programs.texlive = {
enable = true;
extraPackages = p: {inherit (p) scheme-full;};
extraPackages = p: { inherit (p) scheme-full; };
};
}

View file

@ -1,9 +1,5 @@
{
pkgs,
lib,
config,
...
}: let
{ pkgs, lib, config, ... }:
let
rbw = config.programs.rbw.package;
video_dir = "${config.home.homeDirectory}/.volatile/video-downloads";
download-and-watch = pkgs.writeShellScriptBin "download-and-watch" ''
@ -12,7 +8,9 @@
link="''${1:-`${lib.getBin pkgs.wl-clipboard}/bin/wl-paste`}"
filename="`${lib.getExe pkgs.yt-dlp} -j $link | ${lib.getExe pkgs.jq} -r .filename`"
filename="`${lib.getExe pkgs.yt-dlp} -j $link | ${
lib.getExe pkgs.jq
} -r .filename`"
if [[ ! -f "$filename" ]]; then
echo "Prefetching file "
# --user to use the user daemon
@ -21,17 +19,19 @@
${lib.getBin pkgs.systemd}/bin/systemd-run --user --no-block -G \
${lib.getExe pkgs.foot} -D "${video_dir}" \
sh -c \
"${lib.getExe pkgs.yt-dlp} --embed-subs --embed-metadata --embed-chapters \"$1\" && ${lib.getExe pkgs.libnotify} \"Download complete\" \"$filename\""
"${
lib.getExe pkgs.yt-dlp
} --embed-subs --embed-metadata --embed-chapters \"$1\" && ${
lib.getExe pkgs.libnotify
} \"Download complete\" \"$filename\""
else
echo "File already fetched. Playing "
${lib.getExe config.programs.mpv.finalPackage} "$filename"
fi
'';
commands =
builtins.mapAttrs (name: {
config ? "",
user,
}: let
commands = builtins.mapAttrs (name:
{ config ? "", user, }:
let
configFile = pkgs.writeText "${name}-newsboat-config" ''
show-read-feeds no
show-read-articles no
@ -44,22 +44,21 @@
miniflux-passwordeval "${lib.getExe rbw} get rss.maralorn.de ${user}"
${config}
'';
in
pkgs.writeShellScriptBin name "${lib.getExe pkgs.newsboat} -r -C ${configFile} -c ~/.local/share/newsboat/${name}-cache.db \"$@\"") {
news = {
user = "maralorn";
in pkgs.writeShellScriptBin name ''
${
lib.getExe pkgs.newsboat
} -r -C ${configFile} -c ~/.local/share/newsboat/${name}-cache.db "$@"'') {
news = { user = "maralorn"; };
software-updates = { user = "maralorn-softwareupdates"; };
watchfeeds = {
user = "maralorn-watchfeeds";
config = ''
browser "${lib.getExe download-and-watch} %u"
'';
};
} // {
inherit download-and-watch;
};
software-updates = {
user = "maralorn-softwareupdates";
};
watchfeeds = {
user = "maralorn-watchfeeds";
config = ''
browser "${lib.getExe download-and-watch} %u"
'';
};
}
// {inherit download-and-watch;};
in {
systemd.user = {
services.update-software-feeds = {
@ -75,10 +74,8 @@ in {
timers.update-software-feeds = {
Unit.Description = "Update software feeds";
Timer.OnCalendar = "00:05";
Install.WantedBy = ["timers.target"];
Install.WantedBy = [ "timers.target" ];
};
};
home = {
packages = builtins.attrValues commands;
};
home = { packages = builtins.attrValues commands; };
}

View file

@ -1,8 +1,6 @@
defaultMode: {
lib,
config,
...
}: let
defaultMode:
{ lib, config, ... }:
let
# Persistent means that files get snapshoted and kept for a month
# Volatile means that files just lay on the disk
# Backups are organized independently on this system
@ -35,8 +33,8 @@ defaultMode: {
"git"
"media"
];
persistentStateFiles = [".chpwd-recent-dirs"];
volatileStateFiles = [];
persistentStateFiles = [ ".chpwd-recent-dirs" ];
volatileStateFiles = [ ];
volatileStateDirs = [
".steam"
".local/share/Steam"
@ -44,21 +42,21 @@ defaultMode: {
".cache/nix-output-monitor"
];
mkLine = type: to: from: "${type} ${to} - - - - ${from}";
mkEntry = type: persistence: name: let
target = "/disk/${persistence}/maralorn/${name}";
in [(mkLine "L+" "${home}/${name}" target) (mkLine type target "")];
mkEntry = type: persistence: name:
let target = "/disk/${persistence}/maralorn/${name}";
in [ (mkLine "L+" "${home}/${name}" target) (mkLine type target "") ];
in {
systemd.user.tmpfiles.rules =
lib.concatLists
(
map (mkEntry "f" "volatile") volatileStateFiles ++ map (mkEntry "d" "volatile") volatileStateDirs ++ map (mkEntry "f" "persist") persistentStateFiles ++ map (mkEntry "d" "persist") persistentStateDirs
)
++ [
(mkLine "L+" "${home}/.password-store" "git/password-store")
(mkLine "L+" "${home}/.volatile" "/disk/volatile/maralorn")
(mkLine "L+" "${home}/.persist" "/disk/persist/maralorn")
(mkLine "f" "${home}/.mode" defaultMode)
(mkLine "f" "${home}/.config/lazygit/state.yml" "startuppopupversion: 5")
(mkLine "d" "${home}/.cache/mutt" "")
];
systemd.user.tmpfiles.rules = lib.concatLists
(map (mkEntry "f" "volatile") volatileStateFiles
++ map (mkEntry "d" "volatile") volatileStateDirs
++ map (mkEntry "f" "persist") persistentStateFiles
++ map (mkEntry "d" "persist") persistentStateDirs) ++ [
(mkLine "L+" "${home}/.password-store" "git/password-store")
(mkLine "L+" "${home}/.volatile" "/disk/volatile/maralorn")
(mkLine "L+" "${home}/.persist" "/disk/persist/maralorn")
(mkLine "f" "${home}/.mode" defaultMode)
(mkLine "f" "${home}/.config/lazygit/state.yml"
"startuppopupversion: 5")
(mkLine "d" "${home}/.cache/mutt" "")
];
}

View file

@ -1,8 +1,4 @@
{
pkgs,
lib,
...
}: {
{ pkgs, lib, ... }: {
systemd.user.services.status-script = {
Unit.Description = "Status Script";
Service = {
@ -10,6 +6,6 @@
Restart = "always";
RestartSec = "10s";
};
Install.WantedBy = ["graphical-session.target"];
Install.WantedBy = [ "graphical-session.target" ];
};
}

View file

@ -1,11 +1,12 @@
{pkgs, ...}: {
{ pkgs, ... }: {
systemd.user = {
services.prometheus-systemd-exporter = {
Unit.Description = "Prometheus systemd exporter";
Service = {
ExecStart = "${pkgs.prometheus-systemd-exporter}/bin/systemd_exporter --systemd.collector.user";
ExecStart =
"${pkgs.prometheus-systemd-exporter}/bin/systemd_exporter --systemd.collector.user";
};
Install.WantedBy = ["default.target"];
Install.WantedBy = [ "default.target" ];
};
};
}

View file

@ -1,10 +1,5 @@
{
lib,
pkgs,
config,
...
}: {
home.packages = [pkgs.taskwarrior-git];
{ lib, pkgs, config, ... }: {
home.packages = [ pkgs.taskwarrior-git ];
home.file = {
"add-git" = {
target = ".task/hooks/on-add.git";

View file

@ -1,15 +1,11 @@
{
pkgs,
config,
lib,
...
}: let
{ pkgs, config, lib, ... }:
let
fix-tasks = pkgs.writeShellScriptBin "fix-tasks" ''
sed 's/depends.*open.*\([0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}\).*close[^ ]* /depends:"\1" /' -i ~/.task/*.data
sed 's/dep_\[[^ ]* //' -i ~/.task/*.data
'';
in {
home.packages = [fix-tasks];
home.packages = [ fix-tasks ];
services.taskwarrior-sync = {
enable = true;
frequency = "*:0/1";
@ -18,26 +14,25 @@ in {
taskwarrior-sync.Service.ExecStartPre =
(pkgs.writeShellScript "ensure-taskwarrior-login" ''
set -eu
if [[ -z "$(${lib.getExe pkgs.taskwarrior} show taskd.credentials | grep maralorn)" ]]; then
yes | /bin/sh <(${lib.getExe pkgs.openssh} root@hera nixos-taskserver user export maralorn.de maralorn)
if [[ -z "$(${
lib.getExe pkgs.taskwarrior
} show taskd.credentials | grep maralorn)" ]]; then
yes | /bin/sh <(${
lib.getExe pkgs.openssh
} root@hera nixos-taskserver user export maralorn.de maralorn)
fi
'')
.outPath;
'').outPath;
watch-tasks = {
Unit.Description = "Watch tasks for changes and trigger sync";
Service = {
ExecStart =
(
pkgs.writeShellScript "watch-vdir" ''
while ${pkgs.coreutils}/bin/sleep 1s; do
${pkgs.systemd}/bin/systemctl --user start taskwarrior-sync
${pkgs.inotify-tools}/bin/inotifywait -e move,create,delete,modify -r ${config.home.homeDirectory}/.task
done
''
)
.outPath;
ExecStart = (pkgs.writeShellScript "watch-vdir" ''
while ${pkgs.coreutils}/bin/sleep 1s; do
${pkgs.systemd}/bin/systemctl --user start taskwarrior-sync
${pkgs.inotify-tools}/bin/inotifywait -e move,create,delete,modify -r ${config.home.homeDirectory}/.task
done
'').outPath;
};
Install.WantedBy = ["default.target"];
Install.WantedBy = [ "default.target" ];
};
};
home.file = {
@ -61,36 +56,33 @@ in {
target = ".task/hooks/on-modify.habitica-points";
executable = true;
source = "${
pkgs.writeHaskellScript
{
name = "habitica-points";
bins = [pkgs.curl pkgs.jq pkgs.libnotify];
imports = ["Data.Aeson"];
} ''
pkgs.writeHaskellScript {
name = "habitica-points";
bins = [ pkgs.curl pkgs.jq pkgs.libnotify ];
imports = [ "Data.Aeson" ];
} ''
data Task = Task { status :: Text } deriving (Generic, FromJSON)
data Task = Task { status :: Text } deriving (Generic, FromJSON)
main = do
oldTask <- getLine
newTask <- getLine
let oldStatus = maybe "unknown" status (decode (encodeUtf8 oldTask))
newStatus = maybe "unknown" status (decode (encodeUtf8 newTask))
when (oldStatus /= "completed" && newStatus == "completed") $ do
result :: String <- curl "-XPOST" "-H" "x-api-user: dbd97aba-8b6b-4649-9dd4-dad284333925" "-H" "x-api-key: ${pkgs.privateValue "" "habitica-token"}" "https://habitica.com/api/v3/tasks/6e95cccd-06e1-466c-b871-643dff31423c/score/up" |> jq "-c" ".data._tmp" |> captureTrim <&> decodeUtf8
notify_send "Task Completed!" result
putTextLn newTask
''
}/bin/habitica-points";
main = do
oldTask <- getLine
newTask <- getLine
let oldStatus = maybe "unknown" status (decode (encodeUtf8 oldTask))
newStatus = maybe "unknown" status (decode (encodeUtf8 newTask))
when (oldStatus /= "completed" && newStatus == "completed") $ do
result :: String <- curl "-XPOST" "-H" "x-api-user: dbd97aba-8b6b-4649-9dd4-dad284333925" "-H" "x-api-key: ${
pkgs.privateValue "" "habitica-token"
}" "https://habitica.com/api/v3/tasks/6e95cccd-06e1-466c-b871-643dff31423c/score/up" |> jq "-c" ".data._tmp" |> captureTrim <&> decodeUtf8
notify_send "Task Completed!" result
putTextLn newTask
''
}/bin/habitica-points";
};
};
programs.taskwarrior = {
enable = true;
dataLocation = "${config.home.homeDirectory}/.task";
config = {
taskd = {
server = "taskserver.maralorn.de:53589";
};
};
config = { taskd = { server = "taskserver.maralorn.de:53589"; }; };
extraConfig = ''
alias.inbox=+PENDING -TAGGED limit:1
alias.inboxall=+PENDING -TAGGED

View file

@ -1,8 +1,4 @@
{
pkgs,
config,
...
}: {
{ pkgs, config, ... }: {
home.sessionVariables.TERMINAL = "${pkgs.foot}/bin/foot";
home.packages = [
(pkgs.recursiveLinkFarm "fake-gnome-terminal" {
@ -13,12 +9,10 @@
settings = {
main = {
font = "Symbols Nerd Font Mono:pixelsize=12,CozetteVector:pixelsize=12";
include =
(pkgs.runCommandLocal "foot-theme" {} ''
cat ${pkgs.foot.themes}/share/foot/themes/catppuccin > $out
echo -e "background=000000\nalpha=0.9" >> $out
'')
.outPath;
include = (pkgs.runCommandLocal "foot-theme" { } ''
cat ${pkgs.foot.themes}/share/foot/themes/catppuccin > $out
echo -e "background=000000\nalpha=0.9" >> $out
'').outPath;
};
csd = {
preferred = "client";
@ -26,9 +20,7 @@
border-width = "1";
color = "ff${config.m-0.colors.accent}";
};
mouse = {
hide-when-typing = "yes";
};
mouse = { hide-when-typing = "yes"; };
tweak.font-monospace-warn = "no";
};
enable = true;

View file

@ -1,16 +1,8 @@
{pkgs, ...}: {
{ pkgs, ... }: {
home.packages = builtins.attrValues {
inherit (pkgs.xorg) xev;
inherit
(pkgs)
meld
icedtea8_web
octave
filezilla
nix-review
gparted
grafana-devel
;
inherit (pkgs)
meld icedtea8_web octave filezilla nix-review gparted grafana-devel;
};
home.file.".editorconfig".text = ''
# Top-most EditorConfig file

View file

@ -1,7 +1,5 @@
_: {
dconf.settings = {
"org/gnome/desktop/screensaver" = {
lock-enabled = false;
};
"org/gnome/desktop/screensaver" = { lock-enabled = false; };
};
}

View file

@ -1,17 +1,8 @@
{
pkgs,
config,
...
}: let
makeUnlocker = {
name,
hostName,
pubKey,
passwordName,
}: let
knownHosts = pkgs.writeText "KnownBootHosts" "${hostName} ${pubKey}";
in
pkgs.writeShellScriptBin "unlock-${name}" ''
{ pkgs, config, ... }:
let
makeUnlocker = { name, hostName, pubKey, passwordName, }:
let knownHosts = pkgs.writeText "KnownBootHosts" "${hostName} ${pubKey}";
in pkgs.writeShellScriptBin "unlock-${name}" ''
echo "Waiting for host to come up";
while true; do
echo -n .
@ -22,12 +13,11 @@
echo "Ping successful; Entering disk encryption password"
${config.programs.rbw.package}/bin/rbw get ${passwordName} | (ssh -4 root@${hostName} -o UserKnownHostsFile=${knownHosts} cryptsetup-askpass && echo "Unlocking of ${name} successful" || echo "Unlocking of ${name} failed")
'';
unlocker = [
{
name = "hera";
hostName = "hera-v4";
pubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCHkqWlFLtmIlTSKahr2PcL++K75YgfsSU6jwVYW5df3JCkowu/M16SIBxABxYSQrKej5uIz/OFCjqSxHJQ8D5wSYBvn2gYr/BbBcz4rfIJmZ55Od2jckaqlj/M8TtkuPPhsQG7S730vXxK5hbMT8iW5WWv8sIKY/WtaRbZOFMX/53WCLEHtnMu5zFJFWf92+mjIHSLyW8ggl1m525RUiaAfCge2vnuzIFq4kUqJxaWzxIvEWIncKWN10K/HMvdI+yOtbSen41uKedwSFhUFs3xHy1mJddYOrlcJQPt5zuuffZ/nTDVXMZoh5QNwg8ZlkkueVChaS1Y5STjb7cem1Mt";
passwordName = "hera.m-0.eu disk";
}
];
in {config = {home.packages = map makeUnlocker unlocker;};}
unlocker = [{
name = "hera";
hostName = "hera-v4";
pubKey =
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCHkqWlFLtmIlTSKahr2PcL++K75YgfsSU6jwVYW5df3JCkowu/M16SIBxABxYSQrKej5uIz/OFCjqSxHJQ8D5wSYBvn2gYr/BbBcz4rfIJmZ55Od2jckaqlj/M8TtkuPPhsQG7S730vXxK5hbMT8iW5WWv8sIKY/WtaRbZOFMX/53WCLEHtnMu5zFJFWf92+mjIHSLyW8ggl1m525RUiaAfCge2vnuzIFq4kUqJxaWzxIvEWIncKWN10K/HMvdI+yOtbSen41uKedwSFhUFs3xHy1mJddYOrlcJQPt5zuuffZ/nTDVXMZoh5QNwg8ZlkkueVChaS1Y5STjb7cem1Mt";
passwordName = "hera.m-0.eu disk";
}];
in { config = { home.packages = map makeUnlocker unlocker; }; }

View file

@ -1,7 +1,5 @@
_: {
dconf.settings = {
"org/gnome/desktop/screensaver" = {
lock-enabled = true;
};
"org/gnome/desktop/screensaver" = { lock-enabled = true; };
};
}

View file

@ -1,115 +1,87 @@
{
pkgs,
lib,
config,
...
}: let
addressbooks = pkgs.privateValue [] "addressbooks";
calendars = pkgs.privateValue [] "calendars";
{ pkgs, lib, config, ... }:
let
addressbooks = pkgs.privateValue [ ] "addressbooks";
calendars = pkgs.privateValue [ ] "calendars";
mkConfig = config:
(pkgs.formats.ini {}).generate "vdirsyncer-config" (
lib.mapAttrs
(
_: lib.mapAttrs (_: builtins.toJSON)
)
config
);
mkCalendar = {
name,
url,
username,
passwordPath,
collections ? ["from a" "from b"],
readOnly ? false,
type ? "caldav",
}: let
pairName = "${name}_calendar";
remoteName = "${pairName}_remote";
localName = "${pairName}_local";
in {
"pair ${pairName}" = {
a = localName;
b = remoteName;
inherit collections;
conflict_resolution = "b wins";
metadata = ["color"];
};
"storage ${localName}" = {
type = "filesystem";
path = "~/.calendars/${name}/";
fileext = ".ics";
};
"storage ${remoteName}" =
{
(pkgs.formats.ini { }).generate "vdirsyncer-config"
(lib.mapAttrs (_: lib.mapAttrs (_: builtins.toJSON)) config);
mkCalendar = { name, url, username, passwordPath
, collections ? [ "from a" "from b" ], readOnly ? false, type ? "caldav", }:
let
pairName = "${name}_calendar";
remoteName = "${pairName}_remote";
localName = "${pairName}_local";
in {
"pair ${pairName}" = {
a = localName;
b = remoteName;
inherit collections;
conflict_resolution = "b wins";
metadata = [ "color" ];
};
"storage ${localName}" = {
type = "filesystem";
path = "~/.calendars/${name}/";
fileext = ".ics";
};
"storage ${remoteName}" = {
inherit type;
inherit url;
}
// (
if (type == "caldav")
then {
inherit username;
"password.fetch" = ["command" (lib.getExe config.programs.rbw.package) "get"] ++ passwordPath;
read_only = readOnly;
}
else {}
);
};
mkAddressbook = {
name,
url,
username,
passwordPath,
collections ? ["from a" "from b"],
readOnly ? false,
}: let
pairName = "${name}_contacts";
remoteName = "${pairName}_remote";
localName = "${pairName}_local";
in {
"pair ${pairName}" = {
a = localName;
b = remoteName;
inherit collections;
conflict_resolution = "b wins";
} // (if (type == "caldav") then {
inherit username;
"password.fetch" =
[ "command" (lib.getExe config.programs.rbw.package) "get" ]
++ passwordPath;
read_only = readOnly;
} else
{ });
};
"storage ${localName}" = {
type = "filesystem";
path = "~/.contacts/${name}/";
fileext = ".vcf";
mkAddressbook = { name, url, username, passwordPath
, collections ? [ "from a" "from b" ], readOnly ? false, }:
let
pairName = "${name}_contacts";
remoteName = "${pairName}_remote";
localName = "${pairName}_local";
in {
"pair ${pairName}" = {
a = localName;
b = remoteName;
inherit collections;
conflict_resolution = "b wins";
};
"storage ${localName}" = {
type = "filesystem";
path = "~/.contacts/${name}/";
fileext = ".vcf";
};
"storage ${remoteName}" = {
type = "carddav";
inherit url username;
"password.fetch" =
[ "command" (lib.getExe config.programs.rbw.package) "get" ]
++ passwordPath;
read_only = readOnly;
};
};
"storage ${remoteName}" = {
type = "carddav";
inherit url username;
"password.fetch" = ["command" (lib.getExe config.programs.rbw.package) "get"] ++ passwordPath;
read_only = readOnly;
};
};
in {
xdg.configFile."vdirsyncer/config".source =
mkConfig
(
pkgs.lib.fold (a: b: a // b)
{
general.status_path = "~/.vdirsyncer/status";
}
(map mkCalendar calendars ++ map mkAddressbook addressbooks)
);
home.packages = [pkgs.vdirsyncer];
xdg.configFile."vdirsyncer/config".source = mkConfig
(pkgs.lib.fold (a: b: a // b) {
general.status_path = "~/.vdirsyncer/status";
} (map mkCalendar calendars ++ map mkAddressbook addressbooks));
home.packages = [ pkgs.vdirsyncer ];
systemd.user = {
services.watch-vdir = {
Unit.Description = "Watch vdir data for changes";
Service = {
ExecStart = toString (
pkgs.writeShellScript "watch-vdir" ''
while ${pkgs.coreutils}/bin/sleep 1s; do
${pkgs.vdirsyncer}/bin/vdirsyncer sync
${pkgs.inotify-tools}/bin/inotifywait -e move,create,delete,modify -r ${config.home.homeDirectory}/.contacts ${config.home.homeDirectory}/.calendars
done
''
);
ExecStart = toString (pkgs.writeShellScript "watch-vdir" ''
while ${pkgs.coreutils}/bin/sleep 1s; do
${pkgs.vdirsyncer}/bin/vdirsyncer sync
${pkgs.inotify-tools}/bin/inotifywait -e move,create,delete,modify -r ${config.home.homeDirectory}/.contacts ${config.home.homeDirectory}/.calendars
done
'');
};
Install.WantedBy = ["default.target"];
Install.WantedBy = [ "default.target" ];
};
services.vdirsyncer = {
Unit.Description = "vdirsyncer sync";
@ -123,7 +95,7 @@ in {
timers.vdirsyncer = {
Unit.Description = "vdirsync sync timer";
Timer.OnCalendar = "*:0/15";
Install.WantedBy = ["timers.target"];
Install.WantedBy = [ "timers.target" ];
};
};
}

View file

@ -1,32 +1,27 @@
{
pkgs,
config,
...
}: let
{ pkgs, config, ... }:
let
modeFile = "${config.home.homeDirectory}/.mode";
wallPapers = "${config.home.homeDirectory}/media/images/wallpapers";
randomWallpaper =
pkgs.writeHaskellScript
{
name = "random-wallpaper";
imports = ["System.Random"];
bins = [pkgs.coreutils pkgs.glib];
} ''
main = do
mode <- cat "${modeFile}" |> captureTrim
(lines . decodeUtf8 -> files) <- ls ([i|${wallPapers}/#{mode}|] :: String) |> captureTrim
((files Unsafe.!!) -> file) <- getStdRandom $ randomR (0, length files - 1)
(decodeUtf8 -> current) <- gsettings "get" "org.gnome.desktop.background" "picture-uri" |> captureTrim
let new = [i|file:///${wallPapers}/#{mode}/#{file}|] :: String
when (new /= current) $ do
gsettings "set" "org.gnome.desktop.background" "picture-uri" new
gsettings "set" "org.gnome.desktop.screensaver" "picture-uri" new
'';
randomWallpaper = pkgs.writeHaskellScript {
name = "random-wallpaper";
imports = [ "System.Random" ];
bins = [ pkgs.coreutils pkgs.glib ];
} ''
main = do
mode <- cat "${modeFile}" |> captureTrim
(lines . decodeUtf8 -> files) <- ls ([i|${wallPapers}/#{mode}|] :: String) |> captureTrim
((files Unsafe.!!) -> file) <- getStdRandom $ randomR (0, length files - 1)
(decodeUtf8 -> current) <- gsettings "get" "org.gnome.desktop.background" "picture-uri" |> captureTrim
let new = [i|file:///${wallPapers}/#{mode}/#{file}|] :: String
when (new /= current) $ do
gsettings "set" "org.gnome.desktop.background" "picture-uri" new
gsettings "set" "org.gnome.desktop.screensaver" "picture-uri" new
'';
in {
home.packages = [randomWallpaper];
home.packages = [ randomWallpaper ];
systemd.user = {
services.random-wallpaper = {
Unit = {Description = "Random Wallpaper";};
Unit = { Description = "Random Wallpaper"; };
Service = {
ExecStart = "${randomWallpaper}/bin/random-wallpaper";
Type = "oneshot";
@ -37,7 +32,7 @@ in {
OnCalendar = "*:00/30:00";
OnActiveSec = 1;
};
Install = {WantedBy = ["timers.target"];};
Install = { WantedBy = [ "timers.target" ]; };
};
};
}

View file

@ -1,19 +1,13 @@
{
lib,
pkgs,
config,
...
}:
with lib; let
{ lib, pkgs, config, ... }:
with lib;
let
weechat = pkgs.wrapWeechat pkgs.weechat-unwrapped {
configure = {availablePlugins, ...}: {
plugins = builtins.attrValues (availablePlugins
// {
python =
availablePlugins.python.withPackages
(_: [pkgs.weechatScripts.weechat-matrix]);
});
scripts = [pkgs.weechatScripts.weechat-matrix];
configure = { availablePlugins, ... }: {
plugins = builtins.attrValues (availablePlugins // {
python = availablePlugins.python.withPackages
(_: [ pkgs.weechatScripts.weechat-matrix ]);
});
scripts = [ pkgs.weechatScripts.weechat-matrix ];
};
};
in {
@ -82,15 +76,13 @@ in {
[look]
human_buffer_names = on
[server]
${
lib.concatStringsSep "\n" (lib.mapAttrsToList
(server: serverConfig: ''
${server}.address = "${serverConfig.address}"
${server}.autoconnect = on
${server}.username = "${serverConfig.user}"
${server}.password = "${serverConfig.password}"
'') (pkgs.privateValue {} "weechat/matrix"))
}
${lib.concatStringsSep "\n" (lib.mapAttrsToList
(server: serverConfig: ''
${server}.address = "${serverConfig.address}"
${server}.autoconnect = on
${server}.username = "${serverConfig.user}"
${server}.password = "${serverConfig.password}"
'') (pkgs.privateValue { } "weechat/matrix"))}
'';
};
};
@ -98,7 +90,7 @@ in {
systemd.user = {
timers.log2rss = {
Timer.OnCalendar = "23:58";
Install.WantedBy = ["timers.target"];
Install.WantedBy = [ "timers.target" ];
};
services = {
log2rss = {
@ -112,10 +104,11 @@ in {
Unit.Description = "Weechat Tmux Session";
Service = {
Type = "forking";
ExecStart = "${pkgs.tmux}/bin/tmux -L weechat -2 new-session -d -s irc -n weechat '${weechat}/bin/weechat'";
ExecStart =
"${pkgs.tmux}/bin/tmux -L weechat -2 new-session -d -s irc -n weechat '${weechat}/bin/weechat'";
Restart = "always";
};
Install.WantedBy = ["default.target"];
Install.WantedBy = [ "default.target" ];
};
};
};

View file

@ -1,8 +1,5 @@
{
pkgs,
config,
...
}: let
{ pkgs, config, ... }:
let
wine_dir = "${config.home.homeDirectory}/.volatile/wine_disk";
wine = pkgs.wineWowPackages.staging;
in {
@ -14,8 +11,6 @@ in {
STAGING_SHARED_MEMORY = 1;
WINEESYNC = 1;
};
packages = builtins.attrValues {
inherit wine;
};
packages = builtins.attrValues { inherit wine; };
};
}

View file

@ -1,8 +1,4 @@
{
config,
pkgs,
...
}: {
{ config, pkgs, ... }: {
services.emanote = {
enable = true;
# host = "127.0.0.1"; # default listen address is 127.0.0.1

View file

@ -1,4 +1,4 @@
{pkgs, ...}: {
{ pkgs, ... }: {
programs.zsh = {
enable = true;
enableAutosuggestions = true;
@ -23,14 +23,12 @@
'';
oh-my-zsh = {
enable = true;
plugins = ["colored-man-pages"];
plugins = [ "colored-man-pages" ];
};
plugins = [
{
name = "zsh-nix-shell";
file = "nix-shell.plugin.zsh";
src = "${pkgs.zsh-nix-shell}/share/zsh-nix-shell";
}
];
plugins = [{
name = "zsh-nix-shell";
file = "nix-shell.plugin.zsh";
src = "${pkgs.zsh-nix-shell}/share/zsh-nix-shell";
}];
};
}

View file

@ -1,26 +1,17 @@
{
withSystem,
lib,
inputs,
...
}: {
{ withSystem, lib, inputs, ... }: {
flake = {
nixosConfigurations = withSystem "x86_64-linux" ({
system,
self',
pkgs,
...
}: let
machines = builtins.attrNames (builtins.readDir ./machines);
makeSystem = name:
pkgs.nixos {
imports = [
(import (./. + "/machines/${name}/configuration.nix") inputs)
inputs.secrets.nixosModules.default
inputs.impermanence.nixosModules.impermanence
];
};
in
lib.genAttrs machines makeSystem);
nixosConfigurations = withSystem "x86_64-linux"
({ system, self', pkgs, ... }:
let
machines = builtins.attrNames (builtins.readDir ./machines);
makeSystem = name:
pkgs.nixos {
imports = [
(import (./. + "/machines/${name}/configuration.nix") inputs)
inputs.secrets.nixosModules.default
inputs.impermanence.nixosModules.impermanence
];
};
in lib.genAttrs machines makeSystem);
};
}

View file

@ -1,10 +1,6 @@
flake-inputs: {
lib,
config,
pkgs,
...
}: let
inherit (import ../../../common/common.nix {inherit pkgs;}) syncthing;
flake-inputs:
{ lib, config, pkgs, ... }:
let inherit (import ../../../common/common.nix { inherit pkgs; }) syncthing;
in {
imports = [
(flake-inputs.secrets.lib.vpn "apollo")
@ -41,7 +37,7 @@ in {
network.wait-online.enable = false;
services = {
NetworkManager-wait-online.enable = false;
throttled.path = [pkgs.kmod];
throttled.path = [ pkgs.kmod ];
};
};
@ -64,16 +60,15 @@ in {
cleanupInterval = "15m";
snapshotInterval = "*:00/3:00";
};
syncthing =
{
enable = true;
group = "users";
user = "maralorn";
openDefaultPorts = true;
cert = config.age.secrets."syncthing/apollo/cert.pem".path;
key = config.age.secrets."syncthing/apollo/key.pem".path;
}
// syncthing.declarativeWith ["hera" "zeus" "pegasus"] "/home/maralorn/media";
syncthing = {
enable = true;
group = "users";
user = "maralorn";
openDefaultPorts = true;
cert = config.age.secrets."syncthing/apollo/cert.pem".path;
key = config.age.secrets."syncthing/apollo/key.pem".path;
} // syncthing.declarativeWith [ "hera" "zeus" "pegasus" ]
"/home/maralorn/media";
};
system.stateVersion = "19.09";
}

View file

@ -1,11 +1,5 @@
{
lib,
modulesPath,
...
}: {
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
{ lib, modulesPath, ... }: {
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot = {
loader = {
efi = {
@ -22,18 +16,20 @@
};
};
initrd = {
luks.devices."nixos".device = "/dev/disk/by-uuid/78acaebe-952a-43b1-acc8-66c35a60577e";
availableKernelModules = ["xhci_pci" "nvme" "usb_storage" "sd_mod" "rtsx_pci_sdmmc"];
luks.devices."nixos".device =
"/dev/disk/by-uuid/78acaebe-952a-43b1-acc8-66c35a60577e";
availableKernelModules =
[ "xhci_pci" "nvme" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ];
};
kernelModules = ["kvm-intel"];
supportedFilesystems = ["exfat"];
kernelModules = [ "kvm-intel" ];
supportedFilesystems = [ "exfat" ];
};
fileSystems = {
"/" = {
device = "/dev/disk/by-uuid/ce5b0ac6-6eaf-45a6-b6c8-bd4958caf335";
fsType = "btrfs";
options = ["compress=zstd" "autodefrag" "noatime"];
options = [ "compress=zstd" "autodefrag" "noatime" ];
};
"/boot/EFI" = {
device = "/dev/disk/by-uuid/C4A6-3DB5";
@ -41,11 +37,7 @@
};
};
zramSwap.enable = true;
swapDevices = [
{
device = "/dev/mapper/system-swap";
}
];
swapDevices = [{ device = "/dev/mapper/system-swap"; }];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
nix.settings.max-jobs = lib.mkDefault 8;

View file

@ -1,9 +1,6 @@
flake-inputs: {
config,
pkgs,
lib,
...
}: let
flake-inputs:
{ config, pkgs, lib, ... }:
let
wireguard = import ../../../common/wireguard.nix;
inherit (config.m-0) hosts;
localAddress = "fdc0:1::2";
@ -20,12 +17,12 @@ in {
./hardware-configuration.nix
];
age.identityPaths = ["/disk/persist/etc/ssh/ssh_host_ed25519_key"];
age.identityPaths = [ "/disk/persist/etc/ssh/ssh_host_ed25519_key" ];
fileSystems = let
btrfsOptions = {options = ["compress=zstd" "autodefrag" "noatime"];};
btrfsOptions = { options = [ "compress=zstd" "autodefrag" "noatime" ]; };
in {
"/disk" = {neededForBoot = true;} // btrfsOptions;
"/disk" = { neededForBoot = true; } // btrfsOptions;
"/nix" = btrfsOptions;
};
@ -52,11 +49,7 @@ in {
];
environment.persistence."/disk/persist" = {
directories = [
"/etc/ssh"
"/var/lib/nixos"
"/var/lib/tailscale"
];
directories = [ "/etc/ssh" "/var/lib/nixos" "/var/lib/tailscale" ];
};
boot = {
@ -74,7 +67,8 @@ in {
keyFile = "/diskkey.bin";
};
secrets = {
"diskkey.bin" = "/disk/persist/diskkey.bin"; # Key can live on crypted disk, is copied to initrd on install
"diskkey.bin" =
"/disk/persist/diskkey.bin"; # Key can live on crypted disk, is copied to initrd on install
};
};
};
@ -100,12 +94,10 @@ in {
];
};
interfaces.enp1s0 = {
ipv6.addresses = [
{
address = localAddress;
prefixLength = 64;
}
];
ipv6.addresses = [{
address = localAddress;
prefixLength = 64;
}];
useDHCP = true;
};
#wireguard.interfaces = {
@ -124,32 +116,26 @@ in {
# };
#};
};
programs = {
ssh = {
startAgent = true;
};
};
programs = { ssh = { startAgent = true; }; };
hardware.printers = {
ensureDefaultPrinter = "Klio";
ensurePrinters = [
{
name = "Klio";
location = "Wohnzimmer";
description = "Klio (Brother MFC-L3750CDW)";
deviceUri = "ipp://klio.lo.m-0.eu/ipp";
model = "everywhere";
}
];
ensurePrinters = [{
name = "Klio";
location = "Wohnzimmer";
description = "Klio (Brother MFC-L3750CDW)";
deviceUri = "ipp://klio.lo.m-0.eu/ipp";
model = "everywhere";
}];
};
services = {
borgbackup.repos.hera = {
path = "/backup/hera-borg-repo";
authorizedKeys = pkgs.privateValue ["dummy-key"] "backup-ssh-keys";
authorizedKeys = pkgs.privateValue [ "dummy-key" ] "backup-ssh-keys";
};
printing = {
enable = true;
allowFrom = ["all"];
listenAddresses = ["[${localAddress}]:631"];
allowFrom = [ "all" ];
listenAddresses = [ "[${localAddress}]:631" ];
extraConf = "ServerAlias *";
defaultShared = true;
};

View file

@ -1,4 +1,4 @@
{device, ...}: {
{ device, ... }: {
disko.devices = {
disk.system = {
type = "disk";
@ -33,24 +33,16 @@
content = {
type = "luks";
name = "system";
extraOpenArgs = ["--allow-discards"];
extraOpenArgs = [ "--allow-discards" ];
content = {
type = "btrfs";
extraArgs = ["-f"]; # Override existing partition
extraArgs = [ "-f" ]; # Override existing partition
subvolumes = {
# Mountpoints inferred from subvolume name
"/disk" = {
mountOptions = ["compress=zstd"];
};
"/disk/persist" = {
mountOptions = ["compress=zstd"];
};
"/disk/volatile" = {
mountOptions = ["compress=zstd"];
};
"/nix" = {
mountOptions = ["compress=zstd" "noatime"];
};
"/disk" = { mountOptions = [ "compress=zstd" ]; };
"/disk/persist" = { mountOptions = [ "compress=zstd" ]; };
"/disk/volatile" = { mountOptions = [ "compress=zstd" ]; };
"/nix" = { mountOptions = [ "compress=zstd" "noatime" ]; };
};
};
};
@ -59,10 +51,7 @@
};
nodev."/" = {
fsType = "tmpfs";
mountOptions = [
"defaults"
"mode=755"
];
mountOptions = [ "defaults" "mode=755" ];
};
};
};

View file

@ -1,15 +1,10 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
pkgs,
modulesPath,
...
}: {
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sdhci_pci"];
boot.kernelModules = ["kvm-intel"];
{ config, lib, pkgs, modulesPath, ... }: {
boot.initrd.availableKernelModules =
[ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sdhci_pci" ];
boot.kernelModules = [ "kvm-intel" ];
fileSystems."/" = {
device = "tmpfs";
@ -31,14 +26,16 @@
fsType = "ext4";
};
boot.initrd.luks.devices."crypted-nixos".device = "/dev/disk/by-uuid/020fde09-f651-45a2-9c6a-9b060edf967d";
boot.initrd.luks.devices."crypted-nixos".device =
"/dev/disk/by-uuid/020fde09-f651-45a2-9c6a-9b060edf967d";
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/9acbc122-e818-49fa-bc2e-de7d9f822d5a";
fsType = "btrfs";
options = ["subvol=nix"];
options = [ "subvol=nix" ];
};
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
hardware.cpu.intel.updateMicrocode =
lib.mkDefault config.hardware.enableRedistributableFirmware;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

View file

@ -1,4 +1,4 @@
{pkgs, ...}: {
{ pkgs, ... }: {
m-0.server.initSSHKey = "/var/boot-ssh-key";
boot = {
@ -7,8 +7,8 @@
version = 2;
device = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0";
};
supportedFilesystems = ["exfat"];
kernelParams = ["ip=213.136.94.190::213.136.94.1:255.255.255.0:hera"];
supportedFilesystems = [ "exfat" ];
kernelParams = [ "ip=213.136.94.190::213.136.94.1:255.255.255.0:hera" ];
initrd.luks.devices.root = {
device = "/dev/disk/by-uuid/536fe284-36f2-425c-b0c5-a737280f9470";
preLVM = true;

View file

@ -1,21 +1,15 @@
{
pkgs,
config,
...
}: let
adminCreds =
pkgs.privateValue
{
adminpass = "";
dbpass = "";
adminuser = "";
} "nextcloud-admin";
{ pkgs, config, ... }:
let
adminCreds = pkgs.privateValue {
adminpass = "";
dbpass = "";
adminuser = "";
} "nextcloud-admin";
inherit (config.m-0) hosts;
certPath = "/var/lib/acme";
nextcloudServices = hostname: {
nextcloud-pg-backup = {
script = let
name = "nextcloud-psql-${hostname}";
script = let name = "nextcloud-psql-${hostname}";
in ''
${config.services.postgresql.package}/bin/pg_dump nextcloud > /var/lib/db-backup-dumps/${name}
'';
@ -26,8 +20,8 @@
};
prometheus-nginx-exporter.serviceConfig.RestartSec = 10;
nextcloud-setup = {
requires = ["postgresql.service" "redis.service"];
after = ["postgresql.service" "redis.service"];
requires = [ "postgresql.service" "redis.service" ];
after = [ "postgresql.service" "redis.service" ];
};
};
nextcloudConf = hostname: {
@ -45,18 +39,15 @@
dbtype = "pgsql";
defaultPhoneRegion = "DE";
adminuser = "maralorn";
adminpassFile = builtins.toFile "nextcloud-adminpass" adminCreds.adminpass;
adminpassFile =
builtins.toFile "nextcloud-adminpass" adminCreds.adminpass;
};
autoUpdateApps = {
enable = true;
startAt = "20:30";
};
};
nextcloud-container = {
v6,
v4,
hostname,
}: {
nextcloud-container = { v6, v4, hostname, }: {
bindMounts = {
"${certPath}" = {
hostPath = certPath;
@ -72,17 +63,15 @@
privateNetwork = true;
hostBridge = "bridge";
config = _: {
imports = [
../../roles
];
nixpkgs = {inherit pkgs;};
imports = [ ../../roles ];
nixpkgs = { inherit pkgs; };
systemd.network.networks."10-wan" = {
matchConfig.Name = "eth0";
address = ["${v6}/112" "${v4}/24"];
address = [ "${v6}/112" "${v4}/24" ];
routes = [
{routeConfig.Gateway = hosts.hera-intern;}
{routeConfig.Gateway = hosts.hera-intern-v4;}
{ routeConfig.Gateway = hosts.hera-intern; }
{ routeConfig.Gateway = hosts.hera-intern-v4; }
];
};
@ -92,7 +81,7 @@
networking = {
useHostResolvConf = false;
firewall.allowedTCPPorts = [80 443 9100 9113];
firewall.allowedTCPPorts = [ 80 443 9100 9113 ];
};
systemd.services = nextcloudServices hostname;
@ -104,7 +93,7 @@
postgresql = {
enable = true;
package = pkgs.postgresql_14;
ensureDatabases = ["nextcloud"];
ensureDatabases = [ "nextcloud" ];
};
};
system.stateVersion = "21.05";
@ -116,7 +105,7 @@ in {
services = {
redis.servers."".enable = true;
nextcloud = nextcloudConf mainHostName;
postgresql.ensureDatabases = ["nextcloud"];
postgresql.ensureDatabases = [ "nextcloud" ];
nginx = {
enable = true;
virtualHosts."cloud.maralorn.de" = {
@ -172,5 +161,5 @@ in {
v4 = hosts.chor-cloud-intern-v4;
};
};
users.users.nextcloud.extraGroups = ["nginx"];
users.users.nextcloud.extraGroups = [ "nginx" ];
}

View file

@ -1,12 +1,10 @@
flake-inputs: {
config,
pkgs,
lib,
...
}: let
inherit (import ../../../common/common.nix {inherit pkgs;}) syncthing;
backupJobs = pkgs.privateValue {} "borgbackup";
backupJobNames = map (name: "borgbackup-job-${name}") (lib.attrNames backupJobs);
flake-inputs:
{ config, pkgs, lib, ... }:
let
inherit (import ../../../common/common.nix { inherit pkgs; }) syncthing;
backupJobs = pkgs.privateValue { } "borgbackup";
backupJobNames =
map (name: "borgbackup-job-${name}") (lib.attrNames backupJobs);
in {
imports = [
(flake-inputs.secrets.lib.vpn "hera")
@ -54,61 +52,52 @@ in {
];
})
];
m-0.monitoring = [
{
name = "hera";
host = "hera-intern:9100";
}
];
m-0.monitoring = [{
name = "hera";
host = "hera-intern:9100";
}];
systemd.services =
{
pg_backup = {
script =
lib.concatMapStringsSep "\n"
(name: "${config.services.postgresql.package}/bin/pg_dump ${name} > /var/lib/db-backup-dumps/${name}")
config.services.postgresql.ensureDatabases;
serviceConfig = {
User = "postgres";
Type = "oneshot";
};
systemd.services = {
pg_backup = {
script = lib.concatMapStringsSep "\n" (name:
"${config.services.postgresql.package}/bin/pg_dump ${name} > /var/lib/db-backup-dumps/${name}")
config.services.postgresql.ensureDatabases;
serviceConfig = {
User = "postgres";
Type = "oneshot";
};
bump-config = {
script = ''
${pkgs.laminar}/bin/laminarc queue bump-config
'';
serviceConfig = {
Type = "oneshot";
};
startAt = "Sat 04:00";
};
night-routines = {
script = let
start = "${pkgs.systemd}/bin/systemctl start";
container = "${pkgs.nixos-container}/bin/nixos-container run";
# ${start} mysql-backup -- only needed for firefox-sync
in ''
set -x
set +e
${start} pg_backup
${container} chor-cloud -- ${start} nextcloud-pg-backup
${lib.concatMapStringsSep "\n" (name: "${start} ${name}") backupJobNames}
${pkgs.coreutils}/bin/rm -rf /var/lib/db-backup-dumps/*
${start} synapse-cleanup
${start} nix-gc
${start} nix-optimise
'';
serviceConfig = {
Type = "oneshot";
};
startAt = "03:00";
};
}
// lib.listToAttrs (map (name: {
inherit name;
value = {serviceConfig.Type = "oneshot";};
})
backupJobNames);
};
bump-config = {
script = ''
${pkgs.laminar}/bin/laminarc queue bump-config
'';
serviceConfig = { Type = "oneshot"; };
startAt = "Sat 04:00";
};
night-routines = {
script = let
start = "${pkgs.systemd}/bin/systemctl start";
container = "${pkgs.nixos-container}/bin/nixos-container run";
# ${start} mysql-backup -- only needed for firefox-sync
in ''
set -x
set +e
${start} pg_backup
${container} chor-cloud -- ${start} nextcloud-pg-backup
${lib.concatMapStringsSep "\n" (name: "${start} ${name}")
backupJobNames}
${pkgs.coreutils}/bin/rm -rf /var/lib/db-backup-dumps/*
${start} synapse-cleanup
${start} nix-gc
${start} nix-optimise
'';
serviceConfig = { Type = "oneshot"; };
startAt = "03:00";
};
} // lib.listToAttrs (map (name: {
inherit name;
value = { serviceConfig.Type = "oneshot"; };
}) backupJobNames);
services = {
postgresql = {
enable = true;
@ -119,24 +108,22 @@ in {
enable = true;
fqdn = "${config.m-0.virtualHosts.taskserver}";
listenHost = "::";
organisations."maralorn.de".users = ["maralorn"];
organisations."maralorn.de".users = [ "maralorn" ];
};
syncthing =
{
enable = true;
group = "nginx";
user = "maralorn";
openDefaultPorts = true;
cert = config.age.secrets."syncthing/hera/cert.pem".path;
key = config.age.secrets."syncthing/hera/key.pem".path;
}
// syncthing.declarativeWith ["apollo" "zeus" "pegasus"] "/media";
syncthing = {
enable = true;
group = "nginx";
user = "maralorn";
openDefaultPorts = true;
cert = config.age.secrets."syncthing/hera/cert.pem".path;
key = config.age.secrets."syncthing/hera/key.pem".path;
} // syncthing.declarativeWith [ "apollo" "zeus" "pegasus" ] "/media";
};
systemd.tmpfiles.rules = ["Z /media 0770 maralorn nginx - -"];
systemd.tmpfiles.rules = [ "Z /media 0770 maralorn nginx - -" ];
nix.sshServe = {
protocol = "ssh-ng";
enable = true;
keys = pkgs.privateValue [] "root-ssh-keys";
keys = pkgs.privateValue [ ] "root-ssh-keys";
};
users.users = {
@ -144,12 +131,14 @@ in {
description = "choreutes";
isNormalUser = true;
uid = 1001;
extraGroups = ["wheel" "systemd-journal"];
extraGroups = [ "wheel" "systemd-journal" ];
passwordFile = config.age.secrets.pam-login-password-choreutes.path;
};
ved-backup = {
isNormalUser = true;
openssh.authorizedKeys.keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDSldCn4LJcIos8PVI7PJZSM5aQ8FoDPUzMTwSHm6NUl root@bach"];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDSldCn4LJcIos8PVI7PJZSM5aQ8FoDPUzMTwSHm6NUl root@bach"
];
};
};

View file

@ -1,20 +1,13 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
pkgs,
modulesPath,
...
}: {
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
{ config, lib, pkgs, modulesPath, ... }: {
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
boot.initrd.availableKernelModules = ["ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk"];
boot.kernelModules = [];
boot.extraModulePackages = [];
boot.initrd.availableKernelModules =
[ "ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/8e92387a-6785-4b3c-bcdb-a4a423675173";
@ -26,7 +19,8 @@
fsType = "vfat";
};
swapDevices = [{device = "/dev/disk/by-uuid/1e651bde-94b5-4fe2-9e6a-7af916d80057";}];
swapDevices =
[{ device = "/dev/disk/by-uuid/1e651bde-94b5-4fe2-9e6a-7af916d80057"; }];
nix.settings.max-jobs = lib.mkDefault 4;

View file

@ -1,21 +1,16 @@
flake-inputs: {
pkgs,
config,
lib,
...
}: let
flake-inputs:
{ pkgs, config, lib, ... }:
let
certPath = "/var/lib/acme/hera.m-0.eu";
nonMailboxDomains = ["lists.maralorn.de"];
nonMailboxDomains = [ "lists.maralorn.de" ];
inherit (config.m-0) hosts virtualHosts;
rspamd-address = "[::1]:11334";
in {
imports = [flake-inputs.nixos-mailserver.nixosModules.default];
m-0.monitoring = [
{
name = "postfix on hera";
host = "hera-intern:9154";
}
];
imports = [ flake-inputs.nixos-mailserver.nixosModules.default ];
m-0.monitoring = [{
name = "postfix on hera";
host = "hera-intern:9154";
}];
services = {
nginx.virtualHosts.${virtualHosts.rspamd}.locations."/" = {
@ -33,18 +28,16 @@ in {
rspamd = {
workers = {
controller = {
bindSockets = [rspamd-address];
bindSockets = [ rspamd-address ];
extraConfig = ''
secure_ip = "::1/128 127.0.0.1/32";
'';
};
normal = {};
normal = { };
};
locals = {
"multimap.conf".text = let
allow-ip =
builtins.toFile "allow-ip.map" ''
'';
allow-ip = builtins.toFile "allow-ip.map" "";
allow-host = builtins.toFile "allow-host.map" ''
ccc.de
discourse.cloud
@ -73,12 +66,21 @@ in {
};
};
postfix = {
networks = ["[::1]/128" "127.0.0.1/32" "[${config.m-0.prefix}::]/64" "10.0.0.0/24"];
networks = [
"[::1]/128"
"127.0.0.1/32"
"[${config.m-0.prefix}::]/64"
"10.0.0.0/24"
];
transport = "email2matrix.maralorn.de smtp:[::1]:2525";
config = {
# Allow TLSv1 because we need to be able to receive mail from legacy servers.
smtpd_tls_protocols = lib.mkForce "TLSv1.3, TLSv1.2, TLSv1.1, TLSv1, !SSLv2, !SSLv3";
virtual_mailbox_domains = lib.mkForce (builtins.toFile "vhosts" (lib.concatStringsSep "\n" (builtins.filter (x: !builtins.elem x nonMailboxDomains) config.mailserver.domains)));
smtpd_tls_protocols =
lib.mkForce "TLSv1.3, TLSv1.2, TLSv1.1, TLSv1, !SSLv2, !SSLv3";
virtual_mailbox_domains = lib.mkForce (builtins.toFile "vhosts"
(lib.concatStringsSep "\n"
(builtins.filter (x: !builtins.elem x nonMailboxDomains)
config.mailserver.domains)));
smtp_bind_address = hosts.hera-v4;
smtp_bind_address6 = hosts.hera;
};
@ -93,9 +95,16 @@ in {
enableManageSieve = true;
fqdn = "hera.m-0.eu";
rewriteMessageId = true;
domains = ["m-0.eu" "maralorn.de" "choreutes.de" "mathechor.de" "lists.maralorn.de" "malte-und-clai.re"];
forwards = pkgs.privateValue {} "mail/forwards";
loginAccounts = pkgs.privateValue {} "mail/users";
domains = [
"m-0.eu"
"maralorn.de"
"choreutes.de"
"mathechor.de"
"lists.maralorn.de"
"malte-und-clai.re"
];
forwards = pkgs.privateValue { } "mail/forwards";
loginAccounts = pkgs.privateValue { } "mail/users";
hierarchySeparator = "/";
certificateScheme = 1;
certificateFile = "${certPath}/fullchain.pem";

View file

@ -1,8 +1,5 @@
{
pkgs,
config,
...
}: let
{ pkgs, config, ... }:
let
#wireguard = import ../../../common/wireguard.nix;
inherit (config.m-0) hosts;
in {
@ -10,13 +7,10 @@ in {
m-0.tailscale-routes = "fd42:ccc:da:64::/64,172.20.64.0/24";
systemd.network.networks."10-wan" = {
matchConfig.Name = "ens18";
address = [
"213.136.94.190/24"
"${hosts.hera}/128"
];
address = [ "213.136.94.190/24" "${hosts.hera}/128" ];
routes = [
{routeConfig.Gateway = "213.136.94.1";}
{routeConfig.Gateway = "fe80::1";}
{ routeConfig.Gateway = "213.136.94.1"; }
{ routeConfig.Gateway = "fe80::1"; }
];
};
networking = {
@ -54,24 +48,20 @@ in {
hostName = "hera";
domain = "m-0.eu";
interfaces.ens18.proxyARP = true;
bridges.bridge.interfaces = [];
bridges.bridge.interfaces = [ ];
interfaces.bridge = {
proxyARP = true;
ipv6.addresses = [
{
address = hosts.hera-intern;
prefixLength = 112;
}
];
ipv4.addresses = [
{
address = "10.0.0.1";
prefixLength = 24;
}
];
ipv6.addresses = [{
address = hosts.hera-intern;
prefixLength = 112;
}];
ipv4.addresses = [{
address = "10.0.0.1";
prefixLength = 24;
}];
};
nameservers = ["213.136.95.10" "2a02:c207::1:53" "2a02:c207::2:53"];
firewall.allowedTCPPorts = [8666];
nameservers = [ "213.136.95.10" "2a02:c207::1:53" "2a02:c207::2:53" ];
firewall.allowedTCPPorts = [ 8666 ];
};
services.ndppd = {

View file

@ -1,39 +1,30 @@
{
config,
pkgs,
lib,
...
}: let
locations."/".extraConfig = "return 301 https://blog.maralorn.de$request_uri;";
{ config, pkgs, lib, ... }:
let
locations."/".extraConfig =
"return 301 https://blog.maralorn.de$request_uri;";
in {
networking.firewall.allowedTCPPorts = [80 443];
m-0.monitoring = [
{
name = "hera-nginx";
host = "hera-intern:9113";
}
];
security.acme.certs = {
"hera.m-0.eu".keyType = "rsa4096";
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
m-0.monitoring = [{
name = "hera-nginx";
host = "hera-intern:9113";
}];
security.acme.certs = { "hera.m-0.eu".keyType = "rsa4096"; };
services = {
nginx = {
enable = true;
virtualHosts =
{
"hera.m-0.eu" = {
default = true;
forceSSL = true;
enableACME = true;
inherit locations;
};
"maralorn.de" = {
enableACME = true;
forceSSL = true;
inherit locations;
};
}
// pkgs.privateValue {} "extra-sites";
virtualHosts = {
"hera.m-0.eu" = {
default = true;
forceSSL = true;
enableACME = true;
inherit locations;
};
"maralorn.de" = {
enableACME = true;
forceSSL = true;
inherit locations;
};
} // pkgs.privateValue { } "extra-sites";
};
};
systemd.services.nginx.serviceConfig.Restart = "always";

View file

@ -1,10 +1,6 @@
flake-inputs: {
config,
pkgs,
lib,
...
}: let
inherit (import ../../../common/common.nix {inherit pkgs;}) syncthing;
flake-inputs:
{ config, pkgs, lib, ... }:
let inherit (import ../../../common/common.nix { inherit pkgs; }) syncthing;
in {
imports = [
(flake-inputs.secrets.lib.vpn "zeus")
@ -17,20 +13,20 @@ in {
../../roles/standalone
];
age.identityPaths = ["/disk/persist/etc/ssh/ssh_host_ed25519_key"];
age.identityPaths = [ "/disk/persist/etc/ssh/ssh_host_ed25519_key" ];
nix.distributedBuilds = false;
fileSystems = let
btrfsOptions = {options = ["compress=zstd" "autodefrag" "noatime"];};
btrfsOptions = { options = [ "compress=zstd" "autodefrag" "noatime" ]; };
in {
"/disk" = {neededForBoot = true;} // btrfsOptions;
"/disk" = { neededForBoot = true; } // btrfsOptions;
"/boot" = btrfsOptions;
"/nix" = btrfsOptions;
"/home/maralorn/.config/pulse" = {
mountPoint = "/home/maralorn/.config/pulse";
device = "/disk/persist/maralorn/.config/pulse";
options = ["bind"];
options = [ "bind" ];
};
};
@ -40,7 +36,7 @@ in {
};
systemd.services."activate-home-manager" = {
path = [pkgs.nix pkgs.dbus];
path = [ pkgs.nix pkgs.dbus ];
script = ''
if [[ -e /home/maralorn/.mode ]]; then
MODE="$(cat /home/maralorn/.mode)"
@ -53,9 +49,9 @@ in {
Type = "oneshot";
User = "maralorn";
};
wantedBy = ["multi-user.target"];
wantedBy = [ "multi-user.target" ];
# Try to avoid race conditions, when the user gets logged in before activation was completed.
before = ["display-manager.service"];
before = [ "display-manager.service" ];
};
systemd.tmpfiles.rules = [
@ -76,27 +72,23 @@ in {
"/var/lib/tailscale"
"/root/.ssh"
];
users.maralorn.directories = [
".cache/rbw"
".factorio"
];
users.maralorn.directories = [ ".cache/rbw" ".factorio" ];
};
boot = {
loader = {
efi = {
efiSysMountPoint = "/boot/efi";
};
efi = { efiSysMountPoint = "/boot/efi"; };
grub = {
# Enabled by default
device = "nodev"; # Dont write masterboot under efi
efiInstallAsRemovable = true; # Make loader discoverable by filename on efidisk without needing to write efivars to system
efiInstallAsRemovable =
true; # Make loader discoverable by filename on efidisk without needing to write efivars to system
efiSupport = true;
enableCryptodisk = true;
backgroundColor = "#000000";
};
};
kernelParams = ["amdgpu.cik_support=1"];
kernelParams = [ "amdgpu.cik_support=1" ];
initrd = {
luks.devices."crypted-nixos" = {
# device defined in hardware-configuration.nix
@ -107,7 +99,8 @@ in {
"amdgpu" # For earlier and better framebuffer
];
secrets = {
"diskkey.bin" = "/disk/persist/diskkey.bin"; # Key can live on crypted disk, is copied to initrd on install
"diskkey.bin" =
"/disk/persist/diskkey.bin"; # Key can live on crypted disk, is copied to initrd on install
};
};
};
@ -118,12 +111,10 @@ in {
networkmanager.enable = false;
interfaces.enp34s0 = {
useDHCP = true;
ipv6.addresses = [
{
address = "fdc0:1::4";
prefixLength = 64;
}
];
ipv6.addresses = [{
address = "fdc0:1::4";
prefixLength = 64;
}];
};
firewall.allowedTCPPorts = [
6600 # mpd
@ -167,17 +158,16 @@ in {
# firewallFilter = "-i m0wire -p tcp -m tcp -m multiport --dports 9100,9558";
# openFirewall = lib.mkForce false;
#};
syncthing =
{
enable = true;
group = "users";
user = "maralorn";
openDefaultPorts = true;
configDir = "/disk/persist/syncthing";
cert = config.age.secrets."syncthing/zeus/cert.pem".path;
key = config.age.secrets."syncthing/zeus/key.pem".path;
}
// syncthing.declarativeWith ["hera" "apollo" "pegasus"] "/disk/persist/maralorn/media";
syncthing = {
enable = true;
group = "users";
user = "maralorn";
openDefaultPorts = true;
configDir = "/disk/persist/syncthing";
cert = config.age.secrets."syncthing/zeus/cert.pem".path;
key = config.age.secrets."syncthing/zeus/key.pem".path;
} // syncthing.declarativeWith [ "hera" "apollo" "pegasus" ]
"/disk/persist/maralorn/media";
#minecraft-server = {
# enable = true;
# openFirewall = true;
@ -194,7 +184,7 @@ in {
support32Bit = true;
tcp = {
enable = true;
anonymousClients.allowedIpRanges = ["127.0.0.1" "::1"];
anonymousClients.allowedIpRanges = [ "127.0.0.1" "::1" ];
};
};
};

View file

@ -1,20 +1,14 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
modulesPath,
...
}: {
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
{ config, lib, modulesPath, ... }: {
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot.initrd.availableKernelModules = ["nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = ["kvm-amd"];
boot.extraModulePackages = [];
boot.initrd.availableKernelModules =
[ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "tmpfs";
@ -26,18 +20,19 @@
fsType = "btrfs";
};
boot.initrd.luks.devices."crypted-nixos".device = "/dev/disk/by-uuid/2518e0e0-c263-40bc-b378-419832dc62cc";
boot.initrd.luks.devices."crypted-nixos".device =
"/dev/disk/by-uuid/2518e0e0-c263-40bc-b378-419832dc62cc";
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/47552982-2abf-45c6-8c5c-d33091ce3f5a";
fsType = "btrfs";
options = ["subvol=nix"];
options = [ "subvol=nix" ];
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/47552982-2abf-45c6-8c5c-d33091ce3f5a";
fsType = "btrfs";
options = ["subvol=boot"];
options = [ "subvol=boot" ];
};
fileSystems."/boot/efi" = {
@ -45,7 +40,7 @@
fsType = "vfat";
};
swapDevices = [];
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
@ -58,6 +53,7 @@
# networking.interfaces.wlo1.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
hardware.cpu.amd.updateMicrocode =
lib.mkDefault config.hardware.enableRedistributableFirmware;
nix.settings.max-jobs = lib.mkDefault 12;
}

View file

@ -1,14 +1,10 @@
{
config,
pkgs,
lib,
...
}: let
inherit (config.m-0) virtualHosts;
{ config, pkgs, lib, ... }:
let inherit (config.m-0) virtualHosts;
in {
environment.persistence."/disk/persist".directories = ["/var/www/5etools"];
environment.persistence."/disk/persist".directories = [ "/var/www/5etools" ];
services.nginx.virtualHosts.${virtualHosts."5e"}. locations."/" .root = "/var/www/5etools";
services.nginx.virtualHosts.${virtualHosts."5e"}.locations."/".root =
"/var/www/5etools";
systemd.services.update-5etools = {
script = ''
@ -16,7 +12,9 @@ in {
if [[ -d ".git" ]]; then
${lib.getExe pkgs.git} pull
else
${lib.getExe pkgs.git} clone https://github.com/5etools-mirror-1/5etools-mirror-1.github.io.git .
${
lib.getExe pkgs.git
} clone https://github.com/5etools-mirror-1/5etools-mirror-1.github.io.git .
fi
'';
startAt = "daily";

View file

@ -1,11 +1,8 @@
{
config,
pkgs,
lib,
...
}: let
openssh.authorizedKeys.keys = pkgs.privateValue [] "ssh-keys";
passwordFile = lib.mkIf (config.networking.hostName != "chor-cloud") config.age.secrets.pam-login-password.path;
{ config, pkgs, lib, ... }:
let
openssh.authorizedKeys.keys = pkgs.privateValue [ ] "ssh-keys";
passwordFile = lib.mkIf (config.networking.hostName != "chor-cloud")
config.age.secrets.pam-login-password.path;
in {
users.users = {
maralorn = {
@ -24,6 +21,6 @@ in {
];
inherit openssh passwordFile;
};
root = {inherit openssh passwordFile;};
root = { inherit openssh passwordFile; };
};
}

View file

@ -1,9 +1,4 @@
{
config,
pkgs,
lib,
...
}: {
{ config, pkgs, lib, ... }: {
services = {
nginx = {
enable = true;
@ -20,9 +15,7 @@
add_header Cache-Control "public";
'';
};
"/" = {
tryFiles = "$uri $uri.html $uri/index.html =404";
};
"/" = { tryFiles = "$uri $uri.html $uri/index.html =404"; };
};
extraConfig = ''
error_page 404 /not-found.html;

View file

@ -1,9 +1,5 @@
{
lib,
config,
...
}: let
secretsFile = "/var/lib/luks-secret/key";
{ lib, config, ... }:
let secretsFile = "/var/lib/luks-secret/key";
in {
boot = {
initrd = {

View file

@ -1,20 +1,14 @@
{
config,
pkgs,
lib,
...
}: let
{ config, pkgs, lib, ... }:
let
fqdn = "${config.networking.hostName}.${config.networking.domain}";
key_dir = config.security.acme.certs."${fqdn}".directory;
in {
users.users.turnserver.extraGroups = ["nginx"]; # For read access to certs;
users.users.turnserver.extraGroups = [ "nginx" ]; # For read access to certs;
networking.firewall = let
range = [
{
from = config.services.coturn.min-port;
to = config.services.coturn.max-port;
}
];
range = [{
from = config.services.coturn.min-port;
to = config.services.coturn.max-port;
}];
ports = [
config.services.coturn.listening-port
config.services.coturn.alt-listening-port
@ -40,12 +34,10 @@ in {
max-port = 52100;
pkey = "${key_dir}/key.pem";
cert = "${key_dir}/fullchain.pem";
static-auth-secret =
(pkgs.privateValue {turn_shared_secret = "";}
"matrix/server-secrets")
.turn_shared_secret;
static-auth-secret = (pkgs.privateValue { turn_shared_secret = ""; }
"matrix/server-secrets").turn_shared_secret;
realm = fqdn;
listening-ips = [config.m-0.hosts.hera config.m-0.hosts.hera-v4];
listening-ips = [ config.m-0.hosts.hera config.m-0.hosts.hera-v4 ];
extraConfig = ''
fingerprint

View file

@ -1,25 +1,21 @@
{
pkgs,
config,
lib,
...
}: let
{ pkgs, config, lib, ... }:
let
inherit (config.m-0) hosts;
inherit (config.networking) hostName;
in {
imports = [
../../common
];
imports = [ ../../common ];
i18n = {
defaultLocale = "en_DK.UTF-8";
supportedLocales = ["en_DK.UTF-8/UTF-8" "de_DE.UTF-8/UTF-8" "en_US.UTF-8/UTF-8"];
supportedLocales =
[ "en_DK.UTF-8/UTF-8" "de_DE.UTF-8/UTF-8" "en_US.UTF-8/UTF-8" ];
};
time.timeZone = "Europe/Berlin";
networking = {
resolvconf.dnsExtensionMechanism = false; # this breaks dnssec but is necessary for certain bad-behaved hotspots
resolvconf.dnsExtensionMechanism =
false; # this breaks dnssec but is necessary for certain bad-behaved hotspots
firewall = {
enable = true; # Its the default, but better make sure.
allowPing = true;
@ -27,29 +23,27 @@ in {
nftables.enable = true; # Uses firewall variables since 23.05
useNetworkd = true;
useDHCP = false; # enabled per interface
hosts =
lib.zipAttrs
(
lib.mapAttrsToList
(host: ip:
if builtins.typeOf ip == "set"
then {}
else {"${ip}" = "${host} ${host}.m-0.eu";})
config.m-0.hosts
++ lib.mapAttrsToList
(host: ips: let
hosts = lib.zipAttrs (lib.mapAttrsToList (host: ip:
if builtins.typeOf ip == "set" then
{ }
else {
"${ip}" = "${host} ${host}.m-0.eu";
}) config.m-0.hosts ++ lib.mapAttrsToList (host: ips:
let
mkHost = name: "${name} ${name}.maralorn.de";
name = "${host} ${host}.vpn.m-0.eu ${lib.concatMapStringsSep " " mkHost config.m-0.hosts.aliases.${host} or []}";
name = "${host} ${host}.vpn.m-0.eu ${
lib.concatMapStringsSep " " mkHost
config.m-0.hosts.aliases.${host} or [ ]
}";
in {
${ips.AAAA} = name;
${ips.A} = name;
})
config.m-0.hosts.tailscale
);
}) config.m-0.hosts.tailscale);
};
m-0 = {
virtualHosts = lib.genAttrs (hosts.aliases.${hostName} or []) (name: "${name}.maralorn.de");
virtualHosts = lib.genAttrs (hosts.aliases.${hostName} or [ ])
(name: "${name}.maralorn.de");
};
nix = {
@ -77,68 +71,17 @@ in {
environment = {
systemPackages = builtins.attrValues {
inherit
(pkgs)
git
gnumake
mkpasswd
file
wget
curl
wireguard-tools
gnupg
bind
liboping
psmisc
unzip
rename
whois
lsof
parted
python3
binutils
ntfsprogs
ventoy-bin
htop
helix
btop
tree
pwgen
borgbackup
inotifyTools
direnv
socat
nmap
ncdu
tcpdump
tmux
tig
exa
fzf
fd
sd
bat
ripgrep
ranger
pass
sshuttle
vnstat
entr
libargon2
mblaze
niv
compsize
mediainfo
asciinema
nix-output-monitor
jq
home-manager
builders-configurator
;
inherit (pkgs)
git gnumake mkpasswd file wget curl wireguard-tools gnupg bind liboping
psmisc unzip rename whois lsof parted python3 binutils ntfsprogs
ventoy-bin htop helix btop tree pwgen borgbackup inotifyTools direnv
socat nmap ncdu tcpdump tmux tig exa fzf fd sd bat ripgrep ranger pass
sshuttle vnstat entr libargon2 mblaze niv compsize mediainfo asciinema
nix-output-monitor jq home-manager builders-configurator;
inherit (pkgs.python3Packages) qrcode;
};
variables =
lib.genAttrs ["CURL_CA_BUNDLE" "GIT_SSL_CAINFO" "SSL_CERT_FILE"]
lib.genAttrs [ "CURL_CA_BUNDLE" "GIT_SSL_CAINFO" "SSL_CERT_FILE" ]
(_: "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt");
};
@ -159,12 +102,10 @@ in {
};
};
};
in
{
nix-gc.serviceConfig.Type = "oneshot";
nix-optimise.serviceConfig.Type = "oneshot";
}
// builtins.listToAttrs (map makeConfig hosts);
in {
nix-gc.serviceConfig.Type = "oneshot";
nix-optimise.serviceConfig.Type = "oneshot";
} // builtins.listToAttrs (map makeConfig hosts);
oomd.enableRootSlice = true;
};
@ -175,24 +116,23 @@ in {
prometheus.exporters = {
node = {
enable = true;
enabledCollectors = ["systemd" "logind"];
disabledCollectors = ["timex"];
};
nginx = {
inherit (config.services.nginx) enable;
enabledCollectors = [ "systemd" "logind" ];
disabledCollectors = [ "timex" ];
};
nginx = { inherit (config.services.nginx) enable; };
};
nginx = {
virtualHosts =
lib.genAttrs
(map (name: "${name}.maralorn.de") (builtins.filter (name: !(builtins.elem name hosts.publicAliases.${hostName} or []))
(hosts.aliases.${hostName} or []))) (_: {
extraConfig = ''
satisfy any;
${lib.concatMapStringsSep "\n" (ip_range: "allow ${ip_range};") config.m-0.headscaleIPs}
deny all;
'';
});
virtualHosts = lib.genAttrs (map (name: "${name}.maralorn.de")
(builtins.filter
(name: !(builtins.elem name hosts.publicAliases.${hostName} or [ ]))
(hosts.aliases.${hostName} or [ ]))) (_: {
extraConfig = ''
satisfy any;
${lib.concatMapStringsSep "\n" (ip_range: "allow ${ip_range};")
config.m-0.headscaleIPs}
deny all;
'';
});
statusPage = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;

View file

@ -1,15 +1,11 @@
{
lib,
pkgs,
...
}: {
{ lib, pkgs, ... }: {
programs = {
adb.enable = true;
seahorse.enable = lib.mkForce false;
dconf.enable = true;
};
services = {
udev.packages = [pkgs.chrysalis];
udev.packages = [ pkgs.chrysalis ];
pipewire.enable = lib.mkForce false;
printing = {
enable = true;
@ -36,7 +32,7 @@
core-utilities.enable = lib.mkForce false;
};
};
environment.gnome.excludePackages = [pkgs.orca pkgs.gnome-tour];
environment.gnome.excludePackages = [ pkgs.orca pkgs.gnome-tour ];
sound.enable = true;
hardware = {
pulseaudio = {

View file

@ -1,4 +1,5 @@
{pkgs, ...}: let
{ pkgs, ... }:
let
default_mailbox = {
MailboxName = "<missing>";
MatrixRoomId = "<missing>";
@ -9,8 +10,7 @@
IgnoreBody = false;
SkipMarkdown = false;
};
email2matrix-config =
pkgs.writeText "email2matrix-config.json"
email2matrix-config = pkgs.writeText "email2matrix-config.json"
(builtins.toJSON {
Smtp = {
ListenInterface = "[::1]:2525";
@ -19,29 +19,27 @@
};
Matrix = {
Mappings = [
(default_mailbox
// {
MailboxName = "notify";
MatrixRoomId = "!kTKVQjRwxjaoMQmcve:maralorn.de";
})
(default_mailbox
// {
MailboxName = "subjects";
MatrixRoomId = "!kTKVQjRwxjaoMQmcve:maralorn.de";
IgnoreBody = true;
})
(default_mailbox
// {
MailboxName = "weather";
MatrixRoomId = "!ELeFcSrHXgMqOmwnxg:maralorn.de";
})
(default_mailbox // {
MailboxName = "notify";
MatrixRoomId = "!kTKVQjRwxjaoMQmcve:maralorn.de";
})
(default_mailbox // {
MailboxName = "subjects";
MatrixRoomId = "!kTKVQjRwxjaoMQmcve:maralorn.de";
IgnoreBody = true;
})
(default_mailbox // {
MailboxName = "weather";
MatrixRoomId = "!ELeFcSrHXgMqOmwnxg:maralorn.de";
})
];
};
Misc = {Debug = true;};
Misc = { Debug = true; };
});
in {
systemd.services.email2matrix = {
script = "${pkgs.email2matrix}/bin/devture-email2matrix --config ${email2matrix-config}";
wantedBy = ["multi-user.target"];
script =
"${pkgs.email2matrix}/bin/devture-email2matrix --config ${email2matrix-config}";
wantedBy = [ "multi-user.target" ];
};
}

View file

@ -1,9 +1,4 @@
{
pkgs,
lib,
config,
...
}: {
{ pkgs, lib, config, ... }: {
services.mysql = {
enable = true;
package = pkgs.mariadb;
@ -11,7 +6,7 @@
services.mysqlBackup = {
enable = true;
databases = ["firefox_syncserver"];
databases = [ "firefox_syncserver" ];
calendar = "";
singleTransaction = true;
};

View file

@ -1,66 +1,60 @@
{
config,
pkgs,
lib,
...
}: {
{ config, pkgs, lib, ... }: {
fonts = {
fontconfig = {
enable = true;
cache32Bit = true;
defaultFonts = let
unicode-fallback = ["Noto Sans Symbols" "Noto Sans Symbols2"];
in {
monospace = ["Symbols Nerd Font Mono" "CozetteVector" "Noto Sans Mono"] ++ unicode-fallback;
sansSerif = ["B612" "Noto Sans"] ++ unicode-fallback;
serif = ["Libertinus Serif" "Noto Serif"] ++ unicode-fallback;
};
defaultFonts =
let unicode-fallback = [ "Noto Sans Symbols" "Noto Sans Symbols2" ];
in {
monospace =
[ "Symbols Nerd Font Mono" "CozetteVector" "Noto Sans Mono" ]
++ unicode-fallback;
sansSerif = [ "B612" "Noto Sans" ] ++ unicode-fallback;
serif = [ "Libertinus Serif" "Noto Serif" ] ++ unicode-fallback;
};
};
fonts = builtins.attrValues {
inherit
(pkgs)
inherit (pkgs)
libertinus
# nice text font
material-icons
# icons in my app
tamzen
# 12px
cozette
# 13px
# too wide: dina-font
# cant find font in there: efont-unicode
# too wide: envypn-font
spleen
# Great if you need 8 px font, also nice on 12px.
gohufont
tewi-font
gohufont tewi-font
# Too wide tracking: curie
scientifica
# Quite cool on: 11px
# biwidth: too small
# Too wide tracking: creep
# For all my terminal needs.
b612
# sans font, very good for displays
noto-fonts
# for unicode fallback
nerdfonts
;
nerdfonts;
};
};
@ -69,11 +63,7 @@
environment.etc = let
# fonts with src attributes
font_sources = map (v: v.src) (lib.filter (v: v ? src) config.fonts.fonts);
in
builtins.listToAttrs (lib.imap0
(n: source:
lib.nameValuePair "src-cache/fonts/${toString n}" {
inherit source;
})
font_sources);
in builtins.listToAttrs (lib.imap0 (n: source:
lib.nameValuePair "src-cache/fonts/${toString n}" { inherit source; })
font_sources);
}

View file

@ -1,4 +1,5 @@
{pkgs, ...}: let
{ pkgs, ... }:
let
name = "foundryvtt";
stateDir = "/var/lib/${name}";
dataDir = "${stateDir}/data";
@ -13,11 +14,12 @@
minifyStaticFiles = true;
updateChannel = "release";
};
declarativeConfigFile = builtins.toFile "foundry-options.json" (builtins.toJSON config);
declarativeConfigFile =
builtins.toFile "foundry-options.json" (builtins.toJSON config);
in {
config = {
systemd.services."${name}" = {
wantedBy = ["multi-user.target"];
wantedBy = [ "multi-user.target" ];
description = "Foundryvtt server";
preStart = ''
mkdir -p ${dataDir}
@ -38,7 +40,8 @@ in {
DynamicUser = true;
Restart = "always";
Environment = "HOME=${stateDir}";
ExecStart = "${pkgs.nodejs}/bin/node ${stateDir}/app/resources/app/main.js --dataPath=\"${dataDir}\"";
ExecStart = ''
${pkgs.nodejs}/bin/node ${stateDir}/app/resources/app/main.js --dataPath="${dataDir}"'';
};
};
services = {
@ -60,10 +63,14 @@ in {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
if ($query_string ~ "pw=([A-Za-z]*)") {
add_header Set-Cookie "password=$1; path=/; Max-Age=${toString (365 * 24 * 60 * 60)}; Secure";
add_header Set-Cookie "password=$1; path=/; Max-Age=${
toString (365 * 24 * 60 * 60)
}; Secure";
return 303 /;
}
if ($http_cookie !~ "password=${pkgs.privateValue "" "foundry-pw"}") {
if ($http_cookie !~ "password=${
pkgs.privateValue "" "foundry-pw"
}") {
return 303 /logout;
}
'';

View file

@ -1,44 +1,36 @@
{
config,
pkgs,
lib,
...
}: let
{ config, pkgs, lib, ... }:
let
gitoliteCfg = config.services.gitolite;
post-update =
pkgs.writeHaskellScript
{
name = "post-update";
bins = [pkgs.git pkgs.laminar];
imports = [
"System.Directory (withCurrentDirectory)"
];
} ''
checkout :: String -> IO FilePath
checkout path = do
(decodeUtf8 -> repoDir) <- mktemp "-d" |> captureTrim
git "clone" path repoDir
pure repoDir
post-update = pkgs.writeHaskellScript {
name = "post-update";
bins = [ pkgs.git pkgs.laminar ];
imports = [ "System.Directory (withCurrentDirectory)" ];
} ''
checkout :: String -> IO FilePath
checkout path = do
(decodeUtf8 -> repoDir) <- mktemp "-d" |> captureTrim
git "clone" path repoDir
pure repoDir
main = do
jobMay <- lookupEnv "GL_OPTION_CI_JOB"
whenJust jobMay $ \job -> do
args <- toString . Text.intercalate " " . fmap toText <$> getArgs
setEnv "LAMINAR_REASON" [i|Build triggered by push to branch #{args}|]
jobName <- decodeUtf8 <$> (laminarc ["queue", job, [i|BRANCH=#{args}|]] |> captureTrim)
say [i|Queued job #{jobName}.\nSee https://ci.maralorn.de/jobs/#{Text.replace ":" "/" jobName}|]
mirrorMay <- lookupEnv "GL_OPTION_MIRROR"
whenJust mirrorMay $ \mirror -> do
say [i|Force pushing all branches to #{mirror}|]
git "push" "--all" "-f" mirror
deployMay <- lookupEnv "GL_OPTION_WEB_DEPLOY"
whenJust deployMay $ \deploy -> do
(maybe [] (\x -> ["-A", x]) -> target) <- lookupEnv "GL_OPTION_WEB_DEPLOY_NIX_TARGET"
(decodeUtf8 -> path) <- pwd |> captureTrim
say [i|Building default.nix #{show target} to /var/www/#{deploy}|]
bracket (checkout path) (rm "-rf") $ \repoDir -> withCurrentDirectory repoDir $ nix_build "-o" ([i|/var/www/#{deploy}|] :: String) target
say "Done"
'';
main = do
jobMay <- lookupEnv "GL_OPTION_CI_JOB"
whenJust jobMay $ \job -> do
args <- toString . Text.intercalate " " . fmap toText <$> getArgs
setEnv "LAMINAR_REASON" [i|Build triggered by push to branch #{args}|]
jobName <- decodeUtf8 <$> (laminarc ["queue", job, [i|BRANCH=#{args}|]] |> captureTrim)
say [i|Queued job #{jobName}.\nSee https://ci.maralorn.de/jobs/#{Text.replace ":" "/" jobName}|]
mirrorMay <- lookupEnv "GL_OPTION_MIRROR"
whenJust mirrorMay $ \mirror -> do
say [i|Force pushing all branches to #{mirror}|]
git "push" "--all" "-f" mirror
deployMay <- lookupEnv "GL_OPTION_WEB_DEPLOY"
whenJust deployMay $ \deploy -> do
(maybe [] (\x -> ["-A", x]) -> target) <- lookupEnv "GL_OPTION_WEB_DEPLOY_NIX_TARGET"
(decodeUtf8 -> path) <- pwd |> captureTrim
say [i|Building default.nix #{show target} to /var/www/#{deploy}|]
bracket (checkout path) (rm "-rf") $ \repoDir -> withCurrentDirectory repoDir $ nix_build "-o" ([i|/var/www/#{deploy}|] :: String) target
say "Done"
'';
cgitrc = ''
enable-git-config=1
remove-suffix=1
@ -93,12 +85,10 @@
scan-path=/var/lib/gitolite/repositories
'';
in {
systemd.tmpfiles.rules =
lib.mkAfter
[
"z ${gitoliteCfg.dataDir}/.ssh/id_ed25519 0600 ${gitoliteCfg.user} ${gitoliteCfg.group} - -"
"v /var/cache/cgit 0700 cgit ${gitoliteCfg.group} - -"
];
systemd.tmpfiles.rules = lib.mkAfter [
"z ${gitoliteCfg.dataDir}/.ssh/id_ed25519 0600 ${gitoliteCfg.user} ${gitoliteCfg.group} - -"
"v /var/cache/cgit 0700 cgit ${gitoliteCfg.group} - -"
];
users.users.cgit = {
isSystemUser = true;
inherit (gitoliteCfg) group;
@ -122,8 +112,8 @@ in {
gitolite = {
enable = true;
user = "git";
adminPubkey = builtins.elemAt (pkgs.privateValue [""] "ssh-keys") 0;
commonHooks = ["${post-update}/bin/post-update"];
adminPubkey = builtins.elemAt (pkgs.privateValue [ "" ] "ssh-keys") 0;
commonHooks = [ "${post-update}/bin/post-update" ];
extraGitoliteRc = ''
$RC{UMASK} = 0027;
$RC{GIT_CONFIG_KEYS} = 'gitweb\..*';
@ -141,9 +131,7 @@ in {
enableACME = true;
locations = {
"~* ^.+\.(css|png|ico)$" = {
root = "${pkgs.cgit}/cgit";
};
"~* ^.+.(css|png|ico)$" = { root = "${pkgs.cgit}/cgit"; };
"/" = {
extraConfig = ''

View file

@ -1,46 +1,39 @@
{
pkgs,
config,
...
}: {
{ pkgs, config, ... }: {
#imports = [ modules/go-neb.nix ];
services.go-neb = {
enable = true;
baseUrl = "http://localhost";
config = {
clients = [
{
UserId = "@marabot:maralorn.de";
AccessToken = pkgs.privateValue "" "matrix/marabot-token";
HomeServerUrl = "https://matrix.maralorn.de";
Sync = true;
AutoJoinRooms = true;
DisplayName = "marabot";
}
];
realms = [];
sessions = [];
services = [
{
ID = "alertmanager_service";
Type = "alertmanager";
UserId = "@marabot:maralorn.de";
Config = {
webhook_url = "http://localhost:4050/services/hooks/YWxlcnRtYW5hZ2VyX3NlcnZpY2UK";
rooms = {
"!negVsngnYOmXYCLKiO:maralorn.de" = {
text_template = ''
{{range .Alerts -}} [{{ .Status }}] {{index .Annotations "description"}} ({{index .Labels "alertname" }}){{ end -}}'';
html_template = ''
{{range .Alerts -}}{{ $severity := index .Labels "severity" }}{{ if eq .Status "firing" }}{{ if eq $severity "critical"}}<font color='red'><b>[FIRING - CRITICAL]</b></font>{{ else if eq $severity "warning"}}<font color='orange'><b>[FIRING - WARNING]</b></font>{{ else }}<font color='yellow'><b>[FIRING - {{ $severity }}]</b></font>{{ end }}{{ else }}<font color='green'><b>[RESOLVED]</b></font>{{ end }} {{ index .Annotations "description"}} {{ $url := index .Labels "url" }}{{ if eq $url "" }}{{ else }}<a href="{{ $url }}">more infos</a> {{ end }}({{ index .Labels "alertname"}}, <a href="https://stats.maralorn.de/d/health-status">dashboard</a>, <a href="{{ .SilenceURL }}">silence</a>)<br/>{{end -}}
'';
msg_type = "m.text"; # Must be either `m.text` or `m.notice`
};
clients = [{
UserId = "@marabot:maralorn.de";
AccessToken = pkgs.privateValue "" "matrix/marabot-token";
HomeServerUrl = "https://matrix.maralorn.de";
Sync = true;
AutoJoinRooms = true;
DisplayName = "marabot";
}];
realms = [ ];
sessions = [ ];
services = [{
ID = "alertmanager_service";
Type = "alertmanager";
UserId = "@marabot:maralorn.de";
Config = {
webhook_url =
"http://localhost:4050/services/hooks/YWxlcnRtYW5hZ2VyX3NlcnZpY2UK";
rooms = {
"!negVsngnYOmXYCLKiO:maralorn.de" = {
text_template = ''
{{range .Alerts -}} [{{ .Status }}] {{index .Annotations "description"}} ({{index .Labels "alertname" }}){{ end -}}'';
html_template = ''
{{range .Alerts -}}{{ $severity := index .Labels "severity" }}{{ if eq .Status "firing" }}{{ if eq $severity "critical"}}<font color='red'><b>[FIRING - CRITICAL]</b></font>{{ else if eq $severity "warning"}}<font color='orange'><b>[FIRING - WARNING]</b></font>{{ else }}<font color='yellow'><b>[FIRING - {{ $severity }}]</b></font>{{ end }}{{ else }}<font color='green'><b>[RESOLVED]</b></font>{{ end }} {{ index .Annotations "description"}} {{ $url := index .Labels "url" }}{{ if eq $url "" }}{{ else }}<a href="{{ $url }}">more infos</a> {{ end }}({{ index .Labels "alertname"}}, <a href="https://stats.maralorn.de/d/health-status">dashboard</a>, <a href="{{ .SilenceURL }}">silence</a>)<br/>{{end -}}
'';
msg_type = "m.text"; # Must be either `m.text` or `m.notice`
};
};
}
];
};
}];
};
};
}

View file

@ -1,38 +1,32 @@
{
pkgs,
lib,
...
}: let
{ pkgs, lib, ... }:
let
src = pkgs.fetchurl {
url = "https://github.com/zgoat/goatcounter/releases/download/v2.0.4/goatcounter-v2.0.4-linux-amd64.gz";
url =
"https://github.com/zgoat/goatcounter/releases/download/v2.0.4/goatcounter-v2.0.4-linux-amd64.gz";
sha256 = "1h7hv5lk2gm3klbfbgwfa7xn31az9zmlryd8bqqq38lp5r56cpb4";
};
goatcounter-bin = pkgs.runCommand "goatcounter-bin" {} ''
goatcounter-bin = pkgs.runCommand "goatcounter-bin" { } ''
mkdir -p $out/bin
gunzip -c ${src} > $out/bin/goatcounter
chmod +x $out/bin/goatcounter
'';
goatcounter-token = pkgs.privateValue "" "goatcounter-token";
in {
environment.systemPackages = [goatcounter-bin];
environment.systemPackages = [ goatcounter-bin ];
users = {
users.goatcounter = {
isSystemUser = true;
group = "goatcounter";
};
groups.goatcounter = {};
groups.goatcounter = { };
};
services.postgresql = {
enable = true;
ensureUsers = [
{
name = "goatcounter";
ensurePermissions = {
"DATABASE goatcounter" = "ALL PRIVILEGES";
};
}
];
ensureDatabases = ["goatcounter"];
ensureUsers = [{
name = "goatcounter";
ensurePermissions = { "DATABASE goatcounter" = "ALL PRIVILEGES"; };
}];
ensureDatabases = [ "goatcounter" ];
};
services.nginx = {
appendHttpConfig = lib.mkAfter ''
@ -49,20 +43,21 @@ in {
};
systemd.services = {
goatcounter = {
requires = ["postgresql.service"];
after = ["postgresql.service"];
requires = [ "postgresql.service" ];
after = [ "postgresql.service" ];
serviceConfig = {
User = "goatcounter";
ExecStart = "${goatcounter-bin}/bin/goatcounter serve -db 'postgresql://host=/run/postgresql dbname=goatcounter' -listen *:8081 -tls http -automigrate";
ExecStart =
"${goatcounter-bin}/bin/goatcounter serve -db 'postgresql://host=/run/postgresql dbname=goatcounter' -listen *:8081 -tls http -automigrate";
WatchdogSignal = "SIGTERM";
WatchdogSec = "20m";
Restart = "always";
};
wantedBy = ["multi-user.target"];
wantedBy = [ "multi-user.target" ];
};
goatcounter-feeder = {
requires = ["goatcounter.service"];
after = ["goatcounter.service"];
requires = [ "goatcounter.service" ];
after = [ "goatcounter.service" ];
serviceConfig = {
User = "nginx";
Type = "oneshot";
@ -82,7 +77,7 @@ in {
systemd.timers = {
goatcounter-feeder = {
timerConfig.OnCalendar = "minutely";
wantedBy = ["timers.target"];
wantedBy = [ "timers.target" ];
};
};
}

View file

@ -1,20 +1,15 @@
{
config,
lib,
...
}: let
{ config, lib, ... }:
let
inherit (config.m-0) hosts;
domain = "headscale.maralorn.de";
zone = "maralorn.de";
derp_port = 3479;
in {
m-0.monitoring = [
{
name = "hera-headscale";
host = "[::1]:9098";
}
];
networking.firewall.allowedUDPPorts = [derp_port];
m-0.monitoring = [{
name = "hera-headscale";
host = "[::1]:9098";
}];
networking.firewall.allowedUDPPorts = [ derp_port ];
services = {
headscale = {
enable = true;
@ -30,28 +25,20 @@ in {
region_code = "hera";
region_name = "Hera";
};
urls = [];
urls = [ ];
};
dns_config = {
base_domain = "m-0.eu";
nameservers = [
config.m-0.hosts.tailscale.hera.AAAA
"9.9.9.9"
];
domains = [zone];
extra_records = lib.concatLists (lib.concatLists (lib.mapAttrsToList (
host: ips: (
map (alias:
lib.mapAttrsToList
(type: value: {
name = "${alias}.${zone}";
inherit type value;
})
(lib.filterAttrs (_: addr: addr != "") ips))
(hosts.aliases.${host} or [])
)
)
hosts.tailscale));
nameservers = [ config.m-0.hosts.tailscale.hera.AAAA "9.9.9.9" ];
domains = [ zone ];
extra_records = lib.concatLists (lib.concatLists (lib.mapAttrsToList
(host: ips:
(map (alias:
lib.mapAttrsToList (type: value: {
name = "${alias}.${zone}";
inherit type value;
}) (lib.filterAttrs (_: addr: addr != "") ips))
(hosts.aliases.${host} or [ ]))) hosts.tailscale));
};
logtail.enabled = false;
metrics_listen_addr = "[::1]:9098";
@ -63,11 +50,12 @@ in {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.headscale.port}";
proxyPass =
"http://localhost:${toString config.services.headscale.port}";
proxyWebsockets = true;
};
};
};
environment.systemPackages = [config.services.headscale.package];
environment.systemPackages = [ config.services.headscale.package ];
}

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,5 @@
{pkgs, ...}: let
{ pkgs, ... }:
let
nur = pkgs.flake-inputs'.hexa-nur-packages.packages;
mkLovelaceModule = name: {

View file

@ -1,13 +1,19 @@
lib: let
inherit (builtins) foldl';
lib:
let inherit (builtins) foldl';
in rec {
case = default: attrs: ''
{% if ${lib.concatStringsSep "\n{% elseif " (lib.mapAttrsToList (condition: result: "${condition} %}\n ${result}") attrs)}
{% if ${
lib.concatStringsSep ''
{% elseif '' (lib.mapAttrsToList (condition: result: ''
${condition} %}
${result}'') attrs)
}
{% else %}
${default}
{% endif %}
'';
if' = condition: ifTrue: ifFalse: case ifFalse {"${condition}" = ifTrue;};
if' = condition: ifTrue: ifFalse: case ifFalse { "${condition}" = ifTrue; };
or = lhs: rhs: "(${lhs} or ${rhs})";
and = lhs: rhs: "(${lhs} and ${rhs})";
isState = entity: state: "is_state('${entity}','${state}')";

View file

@ -8,12 +8,7 @@ rec {
fromServiceAction = action: {
action = "call-service";
inherit (action) service;
service_data =
action.data
or {}
// {
inherit (action) entity_id;
};
service_data = action.data or { } // { inherit (action) entity_id; };
};
in {
setMode = mode: option: fromServiceAction (actions.setMode mode option);
@ -22,7 +17,7 @@ rec {
actions = {
notify = message: {
service = "notify.matrix";
data = {inherit message;};
data = { inherit message; };
};
cycleMode = mode: {
service = "input_select.select_next";
@ -30,17 +25,18 @@ rec {
};
setMode = mode: option: {
service = "input_select.select_option";
data = {inherit option;};
data = { inherit option; };
entity_id = util.modeSelectEntity mode;
};
};
util = rec {
mkIcon = name: "mdi:${name}";
mkMode = name: options: {inherit name options;};
mkMode = name: options: { inherit name options; };
modeSelectEntity = mode: "input_select.${modeSelectName mode}";
modeSelectName = mode: "mode_${mode.name}";
modeBinarySensorName = mode: option: "${modeSelectName mode}_is_${option}";
modeBinarySensorEntity = mode: option: "binary_sensor.${modeBinarySensorName mode option}";
modeBinarySensorEntity = mode: option:
"binary_sensor.${modeBinarySensorName mode option}";
};
triggers = rec {
stateTrigger = entity_id: {
@ -57,42 +53,45 @@ rec {
};
};
modules = rec {
mkHAConfig = attrs: {
services.home-assistant.config = attrs;
};
mkModeSwitcher = mode: let
options = builtins.attrNames mode.options;
in
attrs: _:
mkHAConfig {
input_select."${util.modeSelectName mode}" =
{
inherit options;
name = mode.title;
}
// attrs;
template = builtins.map (templates.binarySensorForMode mode) options;
};
mkHAConfig = attrs: { services.home-assistant.config = attrs; };
mkModeSwitcher = mode:
let options = builtins.attrNames mode.options;
in attrs: _:
mkHAConfig {
input_select."${util.modeSelectName mode}" = {
inherit options;
name = mode.title;
} // attrs;
template = builtins.map (templates.binarySensorForMode mode) options;
};
};
cards = {
modeSwitcher = mode: let
mkEntity = optionName: option: {
entity = util.modeBinarySensorEntity mode optionName;
name = option.title;
inherit (option) icon;
tap_action = tap_actions.setMode mode optionName;
modeSwitcher = mode:
let
mkEntity = optionName: option: {
entity = util.modeBinarySensorEntity mode optionName;
name = option.title;
inherit (option) icon;
tap_action = tap_actions.setMode mode optionName;
};
in {
type = "glance";
inherit (mode) title;
columns = builtins.length (builtins.attrNames mode.options);
show_state = false;
entities = lib.mapAttrsToList mkEntity mode.options;
};
in {
type = "glance";
inherit (mode) title;
columns = builtins.length (builtins.attrNames mode.options);
show_state = false;
entities = lib.mapAttrsToList mkEntity mode.options;
};
};
templates = rec {
binarySensor = state: attrs: {binary_sensor = [({inherit state;} // attrs)];};
binarySensorFromCondition = condition: binarySensor (jinja.if' condition "1" "0");
binarySensorForMode = mode: option: binarySensorFromCondition (jinja.isState (util.modeSelectEntity mode) option) {name = util.modeBinarySensorName mode option;};
binarySensor = state: attrs: {
binary_sensor = [ ({ inherit state; } // attrs) ];
};
binarySensorFromCondition = condition:
binarySensor (jinja.if' condition "1" "0");
binarySensorForMode = mode: option:
binarySensorFromCondition
(jinja.isState (util.modeSelectEntity mode) option) {
name = util.modeBinarySensorName mode option;
};
};
}

View file

@ -1,9 +1,11 @@
flake-inputs: {config, ...}: {
imports = [flake-inputs.home-manager.nixosModules.home-manager];
flake-inputs:
{ config, ... }: {
imports = [ flake-inputs.home-manager.nixosModules.home-manager ];
home-manager = {
backupFileExtension = "home-manager-backup";
useGlobalPkgs = true;
useUserPackages = true;
users.maralorn = (import ../../home-manager/machines.nix).${config.networking.hostName}.default;
users.maralorn = (import
../../home-manager/machines.nix).${config.networking.hostName}.default;
};
}

View file

@ -1,24 +1,26 @@
{
pkgs,
lib,
config,
...
}: let
{ pkgs, lib, config, ... }:
let
inherit (lib) types mkOption;
stateDir = "/var/lib/laminar";
cfgDir = "${stateDir}/cfg";
cfg = config.services.laminar;
mkTimeoutConf = run_name: {"${lib.removeSuffix ".run" run_name}.conf" = builtins.toFile "timeout.conf" "TIMEOUT=10800";};
addTimeouts = cfg_files: cfg_files // {jobs = lib.foldr lib.mergeAttrs cfg_files.jobs (map mkTimeoutConf (builtins.filter (lib.hasSuffix ".run") (lib.attrNames cfg_files.jobs)));};
mkTimeoutConf = run_name: {
"${lib.removeSuffix ".run" run_name}.conf" =
builtins.toFile "timeout.conf" "TIMEOUT=10800";
};
addTimeouts = cfg_files:
cfg_files // {
jobs = lib.foldr lib.mergeAttrs cfg_files.jobs (map mkTimeoutConf
(builtins.filter (lib.hasSuffix ".run")
(lib.attrNames cfg_files.jobs)));
};
in {
options = {
services.laminar = {
cfgFiles = mkOption {
type = let
valueType = with types; oneOf [path (attrsOf valueType)];
in
valueType;
default = {};
type = let valueType = with types; oneOf [ path (attrsOf valueType) ];
in valueType;
default = { };
description = ''
Every entry will be copied to /var/lib/laminar/cfg/<name>
@ -27,7 +29,7 @@ in {
};
};
};
imports = [./test-config.nix ./projects.nix];
imports = [ ./test-config.nix ./projects.nix ];
config = {
services.laminar.cfgFiles = {
env = builtins.toFile "laminar-env" ''
@ -50,16 +52,16 @@ in {
};
};
users = {
groups.laminar = {};
groups.laminar = { };
users.laminar = {
group = "laminar";
home = stateDir;
isSystemUser = true;
};
};
environment.systemPackages = [pkgs.laminar];
environment.systemPackages = [ pkgs.laminar ];
systemd.services.laminar = {
wantedBy = ["multi-user.target"];
wantedBy = [ "multi-user.target" ];
description = "Laminar continuous integration service";
serviceConfig = {
WorkingDirectory = stateDir;
@ -69,8 +71,10 @@ in {
Restart = "always";
LimitNOFILE = "1024000";
};
after = ["network.target"];
preStart = "ln -sfT ${pkgs.recursiveLinkFarm "laminar-config-dir" (addTimeouts cfg.cfgFiles)} ${cfgDir}";
after = [ "network.target" ];
preStart = "ln -sfT ${
pkgs.recursiveLinkFarm "laminar-config-dir" (addTimeouts cfg.cfgFiles)
} ${cfgDir}";
};
services = {
nginx = {

View file

@ -1,10 +1,6 @@
{
pkgs,
lib,
config,
...
}: let
path = [pkgs.git pkgs.nix pkgs.gnutar pkgs.gzip pkgs.openssh pkgs.laminar];
{ pkgs, lib, config, ... }:
let
path = [ pkgs.git pkgs.nix pkgs.gnutar pkgs.gzip pkgs.openssh pkgs.laminar ];
mkJob = name:
pkgs.writeShellScript "${name}.run" ''
set -e

View file

@ -1,70 +1,50 @@
{
pkgs,
lib,
config,
...
}: let
bins = lib.attrValues {inherit (pkgs) git nix gnutar xz gzip openssh laminar builders-configurator;};
{ pkgs, lib, config, ... }:
let
bins = lib.attrValues {
inherit (pkgs) git nix gnutar xz gzip openssh laminar builders-configurator;
};
standardPath = lib.makeBinPath bins;
systems = builtins.attrNames (builtins.readDir ../../machines);
homes = lib.attrNames (import ../../../home-manager/machines.nix);
deployCommand = "${
pkgs.writeShellScript "deploy-system-config"
"${pkgs.systemd}/bin/systemctl start --no-block update-config"
}";
deployCommand = "${pkgs.writeShellScript "deploy-system-config"
"${pkgs.systemd}/bin/systemctl start --no-block update-config"}";
in {
services.laminar.cfgFiles.jobs = {
"test-config.run" = let
test-config =
pkgs.writeHaskell "test-config"
{
libraries = builtins.attrValues pkgs.myHaskellScriptPackages;
ghcEnv = {
HOMES = lib.concatStringsSep " " homes;
SYSTEMS = lib.concatStringsSep " " systems;
DEPLOY = deployCommand;
PATH = "${standardPath}:$PATH";
};
ghcArgs = ["-threaded"];
}
(builtins.readFile ./test-config.hs);
in
pkgs.writeShellScript "test-config" ''
FLAGS="" PATH=${standardPath}:$PATH ${test-config}
'';
test-config = pkgs.writeHaskell "test-config" {
libraries = builtins.attrValues pkgs.myHaskellScriptPackages;
ghcEnv = {
HOMES = lib.concatStringsSep " " homes;
SYSTEMS = lib.concatStringsSep " " systems;
DEPLOY = deployCommand;
PATH = "${standardPath}:$PATH";
};
ghcArgs = [ "-threaded" ];
} (builtins.readFile ./test-config.hs);
in pkgs.writeShellScript "test-config" ''
FLAGS="" PATH=${standardPath}:$PATH ${test-config}
'';
"bump-config.run" = let
bump-config =
pkgs.writeHaskell "bump-config"
{
libraries = builtins.attrValues pkgs.myHaskellScriptPackages;
ghcEnv.PATH = "${standardPath}:$PATH";
ghcArgs = ["-threaded"];
}
(builtins.readFile ./bump-config.hs);
in
pkgs.writeShellScript "bump-config" ''
PATH=${standardPath}:$PATH ${bump-config}
'';
bump-config = pkgs.writeHaskell "bump-config" {
libraries = builtins.attrValues pkgs.myHaskellScriptPackages;
ghcEnv.PATH = "${standardPath}:$PATH";
ghcArgs = [ "-threaded" ];
} (builtins.readFile ./bump-config.hs);
in pkgs.writeShellScript "bump-config" ''
PATH=${standardPath}:$PATH ${bump-config}
'';
};
security.sudo.extraRules = let
allowedCommands = [deployCommand];
in [
{
commands =
map
(
command: {
inherit command;
options = ["NOPASSWD"];
}
)
allowedCommands;
users = ["laminar"];
}
];
security.sudo.extraRules = let allowedCommands = [ deployCommand ];
in [{
commands = map (command: {
inherit command;
options = [ "NOPASSWD" ];
}) allowedCommands;
users = [ "laminar" ];
}];
systemd.services = {
update-config = {
path = [pkgs.git pkgs.openssh pkgs.nix];
path = [ pkgs.git pkgs.openssh pkgs.nix ];
restartIfChanged = false;
unitConfig.X-StopOnRemoval = false;
serviceConfig = {
@ -74,41 +54,40 @@ in {
script = let
user = "maralorn";
name = "update-config-after-build-if-forward";
haskell_script =
pkgs.writeHaskellScript
{
inherit name;
imports = [
"Control.Exception qualified as Exception"
"Data.ByteString.Char8 qualified as BSC"
];
bins = [pkgs.nix-diff pkgs.jq];
} ''
exitOnError = \msg action -> try action >>= \case
Left (_ :: Exception.IOException) -> say msg >> exitSuccess
Right value -> pure value
haskell_script = pkgs.writeHaskellScript {
inherit name;
imports = [
"Control.Exception qualified as Exception"
"Data.ByteString.Char8 qualified as BSC"
];
bins = [ pkgs.nix-diff pkgs.jq ];
} ''
exitOnError = \msg action -> try action >>= \case
Left (_ :: Exception.IOException) -> say msg >> exitSuccess
Right value -> pure value
git arg = exe "/run/wrappers/bin/sudo" "-u" "${user}" "${lib.getExe pkgs.git}" arg |> captureTrim
git arg = exe "/run/wrappers/bin/sudo" "-u" "${user}" "${
lib.getExe pkgs.git
}" arg |> captureTrim
main = do
cd "/etc/nixos"
void $ git ["pull", "--ff-only"]
new_system <- readlink "-f" "/var/cache/gc-links/test-config/nixos-configurations/hera" |> captureTrim
old_system <- readlink "-f" "/run/current-system" |> captureTrim
when (new_system == old_system) do say "No changes."; exitSuccess
let switch = do
nix_env "-p" "/nix/var/nix/profiles/system" "--set" (decodeUtf8 new_system :: String)
exe ([i|#{new_system}/bin/switch-to-configuration|] :: String) "switch"
exitSuccess
diff_is_small <- (== "[]") <$> (nix_diff "--json" [new_system, "/run/current-system"] |> jq ".inputsDiff.inputDerivationDiffs" |> captureTrim)
when diff_is_small switch
current_commit <- BSC.strip <$> (exitOnError "Current system is from a dirty commit." do readFileBS "/run/current-system/config-commit")
new_commit <- BSC.strip <$> readFileBS [i|#{new_system}/config-commit|]
is_direct_forward <- ("" ==) <$> exitOnError "Unknown commit." (git ["log", "-n1", "--oneline", [i|^#{new_commit}|], decodeUtf8 current_commit])
when is_direct_forward switch
'';
in
lib.getExe haskell_script;
main = do
cd "/etc/nixos"
void $ git ["pull", "--ff-only"]
new_system <- readlink "-f" "/var/cache/gc-links/test-config/nixos-configurations/hera" |> captureTrim
old_system <- readlink "-f" "/run/current-system" |> captureTrim
when (new_system == old_system) do say "No changes."; exitSuccess
let switch = do
nix_env "-p" "/nix/var/nix/profiles/system" "--set" (decodeUtf8 new_system :: String)
exe ([i|#{new_system}/bin/switch-to-configuration|] :: String) "switch"
exitSuccess
diff_is_small <- (== "[]") <$> (nix_diff "--json" [new_system, "/run/current-system"] |> jq ".inputsDiff.inputDerivationDiffs" |> captureTrim)
when diff_is_small switch
current_commit <- BSC.strip <$> (exitOnError "Current system is from a dirty commit." do readFileBS "/run/current-system/config-commit")
new_commit <- BSC.strip <$> readFileBS [i|#{new_system}/config-commit|]
is_direct_forward <- ("" ==) <$> exitOnError "Unknown commit." (git ["log", "-n1", "--oneline", [i|^#{new_commit}|], decodeUtf8 current_commit])
when is_direct_forward switch
'';
in lib.getExe haskell_script;
};
};
}

View file

@ -1,71 +1,59 @@
{
pkgs,
lib,
config,
...
}: let
{ pkgs, lib, config, ... }:
let
hostname = "lists.maralorn.de";
lists = pkgs.privateValue {} "mail/lists";
me = pkgs.privateValue {mail = "";} "mail/me";
lists = pkgs.privateValue { } "mail/lists";
me = pkgs.privateValue { mail = ""; } "mail/me";
admin = me.mail;
in {
systemd.services.mailman.postStart = lib.concatStringsSep "\n" (
map
(
x: ''
${(pkgs.mailmanPackages.buildEnvs {}).mailmanEnv}/bin/mailman syncmembers -W -G - "${x}" << EOF
${lib.concatStringsSep "\n" lists."${x}"}
EOF
''
)
(builtins.attrNames lists)
);
systemd.services.mailman.postStart = lib.concatStringsSep "\n" (map (x: ''
${
(pkgs.mailmanPackages.buildEnvs { }).mailmanEnv
}/bin/mailman syncmembers -W -G - "${x}" << EOF
${lib.concatStringsSep "\n" lists."${x}"}
EOF
'') (builtins.attrNames lists));
services = {
mailman = {
enable = true;
webHosts = [hostname];
webHosts = [ hostname ];
serve.enable = true;
enablePostfix = true;
siteOwner = admin;
webSettings = {
ACCOUNT_ADAPTER = "django_mailman3.views.user_adapter.DisableSignupAdapter";
ACCOUNT_ADAPTER =
"django_mailman3.views.user_adapter.DisableSignupAdapter";
};
hyperkitty.enable = true; # Annoyingly mailman crashes when it cant find
# a hyperkitty. This is stupid, but I have no patience to find a fix for
# this.
settings = {
mailman.default_language = "de";
"paths.fhs".template_dir =
lib.mkForce
(
pkgs.recursiveLinkFarm "mailman-templates" {
site.de = {
"list:user:notice:goodbye.txt" = builtins.toFile "goodbye" ''
Du erhältst nun keine E-Mails mehr über diese Mailingliste.
"paths.fhs".template_dir = lib.mkForce
(pkgs.recursiveLinkFarm "mailman-templates" {
site.de = {
"list:user:notice:goodbye.txt" = builtins.toFile "goodbye" ''
Du erhältst nun keine E-Mails mehr über diese Mailingliste.
Bei Fragen oder wenn Du doch E-Mails von dieser Liste bekommen möchtest wende Dich an ${admin}.
'';
"list:member:generic:footer.txt" = builtins.toFile "footer" ''
---
Du erhältst diese E-Mail über die Mailingliste "$display_name".
Bei Fragen oder wenn Du diese E-Mails nicht mehr bekommen möchtest wende Dich an ${admin}.
'';
Bei Fragen oder wenn Du doch E-Mails von dieser Liste bekommen möchtest wende Dich an ${admin}.
'';
"list:member:generic:footer.txt" = builtins.toFile "footer" ''
---
Du erhältst diese E-Mail über die Mailingliste "$display_name".
Bei Fragen oder wenn Du diese E-Mails nicht mehr bekommen möchtest wende Dich an ${admin}.
'';
"list:user:notice:welcome.txt" = builtins.toFile "welcome" ''
Herzlich Willkommen auf der Mailingliste "$display_name".
"list:user:notice:welcome.txt" = builtins.toFile "welcome" ''
Herzlich Willkommen auf der Mailingliste "$display_name".
Bei Fragen und wenn Du keine E-Mails von dieser Liste mehr bekommen möchtest wende Dich an ${admin}.
'';
};
}
)
.outPath;
Bei Fragen und wenn Du keine E-Mails von dieser Liste mehr bekommen möchtest wende Dich an ${admin}.
'';
};
}).outPath;
};
};
postfix = {
relayDomains = ["hash:/var/lib/mailman/data/postfix_domains"];
config = let
lmtp = ["hash:/var/lib/mailman/data/postfix_lmtp"];
relayDomains = [ "hash:/var/lib/mailman/data/postfix_domains" ];
config = let lmtp = [ "hash:/var/lib/mailman/data/postfix_lmtp" ];
in {
transport_maps = lmtp;
local_recipient_maps = lmtp;

Some files were not shown because too many files have changed in this diff Show more