workhorse done and nixpkgs-fmt
This commit is contained in:
parent
87be340dfa
commit
fc33e57a54
124 changed files with 3142 additions and 2590 deletions
|
@ -19,7 +19,8 @@
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
writeCommand = krops.packages.${system}.writeCommand;
|
writeCommand = krops.packages.${system}.writeCommand;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
# deploy like this:
|
# deploy like this:
|
||||||
# nix run ".#deploy.sterni"
|
# nix run ".#deploy.sterni"
|
||||||
apps.${system}.deploy = pkgs.callPackage ./nixos/krops.nix {
|
apps.${system}.deploy = pkgs.callPackage ./nixos/krops.nix {
|
||||||
|
|
|
@ -11,7 +11,8 @@ let
|
||||||
rev = "2f5c44f017bdfd8abfe908d419ef26bac300f809";
|
rev = "2f5c44f017bdfd8abfe908d419ef26bac300f809";
|
||||||
sha256 = "0dxhk1ah6wwbsxyk4hd32rz7886w7r5gfy16485gjbvky1qsi8gd";
|
sha256 = "0dxhk1ah6wwbsxyk4hd32rz7886w7r5gfy16485gjbvky1qsi8gd";
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
# setup ftp
|
# setup ftp
|
||||||
services.vsftpd = {
|
services.vsftpd = {
|
||||||
|
|
|
@ -4,28 +4,31 @@
|
||||||
{ modulesPath, config, lib, pkgs, ... }:
|
{ modulesPath, config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [ "${modulesPath}/installer/scan/not-detected.nix"
|
imports = [
|
||||||
|
"${modulesPath}/installer/scan/not-detected.nix"
|
||||||
|
|
||||||
(let mediaUUID = "29ebe5ba-7599-4dd3-99a3-37b9bf8e4d61";
|
(
|
||||||
in {
|
let mediaUUID = "29ebe5ba-7599-4dd3-99a3-37b9bf8e4d61";
|
||||||
fileSystems."/media" = {
|
in {
|
||||||
device = "/dev/disk/by-uuid/${mediaUUID}";
|
fileSystems."/media" = {
|
||||||
fsType = "ext4";
|
device = "/dev/disk/by-uuid/${mediaUUID}";
|
||||||
options = [
|
fsType = "ext4";
|
||||||
"nofail"
|
options = [
|
||||||
"noauto"
|
"nofail"
|
||||||
#"x-systemd.device-timeout=1ms"
|
"noauto"
|
||||||
];
|
#"x-systemd.device-timeout=1ms"
|
||||||
};
|
];
|
||||||
systemd.mounts = [{
|
};
|
||||||
enable = true;
|
systemd.mounts = [{
|
||||||
options = "nofail,noauto";
|
enable = true;
|
||||||
type = "ext4";
|
options = "nofail,noauto";
|
||||||
wantedBy = [ "multi-user.target" ];
|
type = "ext4";
|
||||||
what = "/dev/disk/by-uuid/${mediaUUID}";
|
wantedBy = [ "multi-user.target" ];
|
||||||
where = "/media";
|
what = "/dev/disk/by-uuid/${mediaUUID}";
|
||||||
}];
|
where = "/media";
|
||||||
})
|
}];
|
||||||
|
}
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.initrd.availableKernelModules =
|
boot.initrd.availableKernelModules =
|
||||||
|
|
|
@ -154,12 +154,13 @@
|
||||||
|
|
||||||
{
|
{
|
||||||
alias = "reset everything when back home";
|
alias = "reset everything when back home";
|
||||||
trigger = map (entity_id: {
|
trigger = map
|
||||||
platform = "state";
|
(entity_id: {
|
||||||
entity_id = entity_id;
|
platform = "state";
|
||||||
from = "off";
|
entity_id = entity_id;
|
||||||
to = "on";
|
from = "off";
|
||||||
}) [
|
to = "on";
|
||||||
|
}) [
|
||||||
"binary_sensor.motion_sensor_1"
|
"binary_sensor.motion_sensor_1"
|
||||||
"binary_sensor.motion_sensor_2"
|
"binary_sensor.motion_sensor_2"
|
||||||
"binary_sensor.motion_sensor_3"
|
"binary_sensor.motion_sensor_3"
|
||||||
|
@ -185,57 +186,59 @@
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
group = let
|
group =
|
||||||
create_room = { name, description }: {
|
let
|
||||||
"${name}" = {
|
create_room = { name, description }: {
|
||||||
name = "${description}";
|
"${name}" = {
|
||||||
|
name = "${description}";
|
||||||
|
entities = [ ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
create_rooms = rooms:
|
||||||
|
lib.foldr (a: b: a // b) { } (map create_room rooms);
|
||||||
|
# rooms
|
||||||
|
# -----
|
||||||
|
in
|
||||||
|
(create_rooms [
|
||||||
|
{
|
||||||
|
name = "floor_room";
|
||||||
|
description = "Flur";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "bed_room";
|
||||||
|
description = "Schlafzimmer";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "living_room";
|
||||||
|
description = "Wohnzimmer";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "kitchen_room";
|
||||||
|
description = "Küche";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "bath_room";
|
||||||
|
description = "Klo";
|
||||||
|
}
|
||||||
|
]) // {
|
||||||
|
|
||||||
|
# overview
|
||||||
|
# --------
|
||||||
|
all_sensors = { name = "Alle Sensoren"; };
|
||||||
|
today = {
|
||||||
|
name = "Today";
|
||||||
|
entities = [ "input_select.scene" ];
|
||||||
|
};
|
||||||
|
# other stuff
|
||||||
|
# -----------
|
||||||
|
tv = { name = "TV"; };
|
||||||
|
all_lights = { name = "Alle Lampen"; };
|
||||||
|
unknown = {
|
||||||
|
name = "Not Used";
|
||||||
entities = [ ];
|
entities = [ ];
|
||||||
};
|
};
|
||||||
};
|
|
||||||
create_rooms = rooms:
|
|
||||||
lib.foldr (a: b: a // b) { } (map create_room rooms);
|
|
||||||
# rooms
|
|
||||||
# -----
|
|
||||||
in (create_rooms [
|
|
||||||
{
|
|
||||||
name = "floor_room";
|
|
||||||
description = "Flur";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "bed_room";
|
|
||||||
description = "Schlafzimmer";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "living_room";
|
|
||||||
description = "Wohnzimmer";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "kitchen_room";
|
|
||||||
description = "Küche";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "bath_room";
|
|
||||||
description = "Klo";
|
|
||||||
}
|
|
||||||
]) // {
|
|
||||||
|
|
||||||
# overview
|
|
||||||
# --------
|
|
||||||
all_sensors = { name = "Alle Sensoren"; };
|
|
||||||
today = {
|
|
||||||
name = "Today";
|
|
||||||
entities = [ "input_select.scene" ];
|
|
||||||
};
|
};
|
||||||
# other stuff
|
|
||||||
# -----------
|
|
||||||
tv = { name = "TV"; };
|
|
||||||
all_lights = { name = "Alle Lampen"; };
|
|
||||||
unknown = {
|
|
||||||
name = "Not Used";
|
|
||||||
entities = [ ];
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@ let
|
||||||
folderPath = config.services.home-assistant.configDir;
|
folderPath = config.services.home-assistant.configDir;
|
||||||
filePath = "${folderPath}/${name}.json";
|
filePath = "${folderPath}/${name}.json";
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
services.homeAssistantConfig = {
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
sensor = [
|
sensor = [
|
||||||
|
|
|
@ -66,163 +66,167 @@
|
||||||
[ "zigbee2mqtt/motion_sensor_7" "zigbee2mqtt/door_sensor_4" ];
|
[ "zigbee2mqtt/motion_sensor_7" "zigbee2mqtt/door_sensor_4" ];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
sensors = let
|
sensors =
|
||||||
door = { topic, room }: {
|
let
|
||||||
topic = topic;
|
door = { topic, room }: {
|
||||||
key = "contact";
|
topic = topic;
|
||||||
room = room;
|
key = "contact";
|
||||||
invert_state = true;
|
room = room;
|
||||||
delay = 90;
|
invert_state = true;
|
||||||
};
|
delay = 90;
|
||||||
motion = { topic, room }: {
|
|
||||||
topic = topic;
|
|
||||||
key = "occupancy";
|
|
||||||
room = room;
|
|
||||||
delay = 60;
|
|
||||||
};
|
|
||||||
in [
|
|
||||||
|
|
||||||
(motion {
|
|
||||||
topic = "zigbee2mqtt/motion_sensor_1";
|
|
||||||
room = "office_room";
|
|
||||||
})
|
|
||||||
(motion {
|
|
||||||
topic = "zigbee2mqtt/motion_sensor_2";
|
|
||||||
room = "office_room";
|
|
||||||
})
|
|
||||||
(motion {
|
|
||||||
topic = "zigbee2mqtt/motion_sensor_6";
|
|
||||||
room = "office_room";
|
|
||||||
})
|
|
||||||
(motion {
|
|
||||||
topic = "zigbee2mqtt/motion_sensor_8";
|
|
||||||
room = "office_room";
|
|
||||||
})
|
|
||||||
(motion {
|
|
||||||
topic = "zigbee2mqtt/motion_sensor_7";
|
|
||||||
room = "sleeping_room";
|
|
||||||
})
|
|
||||||
(motion {
|
|
||||||
topic = "zigbee2mqtt/motion_sensor_5";
|
|
||||||
room = "kitchen";
|
|
||||||
})
|
|
||||||
(motion {
|
|
||||||
topic = "zigbee2mqtt/motion_sensor_4";
|
|
||||||
room = "storage_room";
|
|
||||||
})
|
|
||||||
|
|
||||||
(door {
|
|
||||||
topic = "zigbee2mqtt/door_sensor_1";
|
|
||||||
room = "storage_room";
|
|
||||||
})
|
|
||||||
(door {
|
|
||||||
topic = "zigbee2mqtt/door_sensor_5";
|
|
||||||
room = "sleeping_room";
|
|
||||||
})
|
|
||||||
(door {
|
|
||||||
# house door
|
|
||||||
topic = "zigbee2mqtt/door_sensor_4";
|
|
||||||
room = "floor";
|
|
||||||
})
|
|
||||||
|
|
||||||
];
|
|
||||||
switches = let
|
|
||||||
sonoff = { id, rooms, delay ? 0 }: {
|
|
||||||
topic = "stat/${id}/RESULT";
|
|
||||||
key = "POWER";
|
|
||||||
rooms = rooms;
|
|
||||||
delay = delay;
|
|
||||||
command = {
|
|
||||||
command = "{{state}}";
|
|
||||||
init_command = "(null)";
|
|
||||||
topic = "cmnd/${id}/POWER";
|
|
||||||
on = "ON";
|
|
||||||
off = "OFF";
|
|
||||||
};
|
};
|
||||||
};
|
motion = { topic, room }: {
|
||||||
light = { topic, rooms, delay ? 0 }: {
|
topic = topic;
|
||||||
topic = topic;
|
key = "occupancy";
|
||||||
key = "state";
|
room = room;
|
||||||
rooms = rooms;
|
delay = 60;
|
||||||
delay = delay;
|
|
||||||
command = {
|
|
||||||
command = ''{"state":"{{state}}","brightness":{{brightness}}}'';
|
|
||||||
topic = "${topic}/set";
|
|
||||||
on = "ON";
|
|
||||||
off = "OFF";
|
|
||||||
};
|
};
|
||||||
};
|
in
|
||||||
led = { topic, rooms, delay ? 0 }: {
|
[
|
||||||
topic = topic;
|
|
||||||
key = "state";
|
(motion {
|
||||||
rooms = rooms;
|
topic = "zigbee2mqtt/motion_sensor_1";
|
||||||
delay = delay;
|
room = "office_room";
|
||||||
command = {
|
})
|
||||||
# Configure it once to the color you like
|
(motion {
|
||||||
# {"state":"{{state}}","brightness":{{brightness}},"color":{"hex":"#FFFFFF},"color_temp":255","transition":0}
|
topic = "zigbee2mqtt/motion_sensor_2";
|
||||||
command = ''
|
room = "office_room";
|
||||||
{"state":"{{state}}","brightness":{{brightness}},"transition":0}'';
|
})
|
||||||
topic = "${topic}/set";
|
(motion {
|
||||||
on = "ON";
|
topic = "zigbee2mqtt/motion_sensor_6";
|
||||||
off = "OFF";
|
room = "office_room";
|
||||||
|
})
|
||||||
|
(motion {
|
||||||
|
topic = "zigbee2mqtt/motion_sensor_8";
|
||||||
|
room = "office_room";
|
||||||
|
})
|
||||||
|
(motion {
|
||||||
|
topic = "zigbee2mqtt/motion_sensor_7";
|
||||||
|
room = "sleeping_room";
|
||||||
|
})
|
||||||
|
(motion {
|
||||||
|
topic = "zigbee2mqtt/motion_sensor_5";
|
||||||
|
room = "kitchen";
|
||||||
|
})
|
||||||
|
(motion {
|
||||||
|
topic = "zigbee2mqtt/motion_sensor_4";
|
||||||
|
room = "storage_room";
|
||||||
|
})
|
||||||
|
|
||||||
|
(door {
|
||||||
|
topic = "zigbee2mqtt/door_sensor_1";
|
||||||
|
room = "storage_room";
|
||||||
|
})
|
||||||
|
(door {
|
||||||
|
topic = "zigbee2mqtt/door_sensor_5";
|
||||||
|
room = "sleeping_room";
|
||||||
|
})
|
||||||
|
(door {
|
||||||
|
# house door
|
||||||
|
topic = "zigbee2mqtt/door_sensor_4";
|
||||||
|
room = "floor";
|
||||||
|
})
|
||||||
|
|
||||||
|
];
|
||||||
|
switches =
|
||||||
|
let
|
||||||
|
sonoff = { id, rooms, delay ? 0 }: {
|
||||||
|
topic = "stat/${id}/RESULT";
|
||||||
|
key = "POWER";
|
||||||
|
rooms = rooms;
|
||||||
|
delay = delay;
|
||||||
|
command = {
|
||||||
|
command = "{{state}}";
|
||||||
|
init_command = "(null)";
|
||||||
|
topic = "cmnd/${id}/POWER";
|
||||||
|
on = "ON";
|
||||||
|
off = "OFF";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
light = { topic, rooms, delay ? 0 }: {
|
||||||
in [
|
topic = topic;
|
||||||
|
key = "state";
|
||||||
|
rooms = rooms;
|
||||||
|
delay = delay;
|
||||||
|
command = {
|
||||||
|
command = ''{"state":"{{state}}","brightness":{{brightness}}}'';
|
||||||
|
topic = "${topic}/set";
|
||||||
|
on = "ON";
|
||||||
|
off = "OFF";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
led = { topic, rooms, delay ? 0 }: {
|
||||||
|
topic = topic;
|
||||||
|
key = "state";
|
||||||
|
rooms = rooms;
|
||||||
|
delay = delay;
|
||||||
|
command = {
|
||||||
|
# Configure it once to the color you like
|
||||||
|
# {"state":"{{state}}","brightness":{{brightness}},"color":{"hex":"#FFFFFF},"color_temp":255","transition":0}
|
||||||
|
command = ''
|
||||||
|
{"state":"{{state}}","brightness":{{brightness}},"transition":0}'';
|
||||||
|
topic = "${topic}/set";
|
||||||
|
on = "ON";
|
||||||
|
off = "OFF";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
[
|
||||||
|
|
||||||
(light {
|
(light {
|
||||||
topic = "zigbee2mqtt/light_2";
|
topic = "zigbee2mqtt/light_2";
|
||||||
rooms = [ "office_room" ];
|
rooms = [ "office_room" ];
|
||||||
})
|
})
|
||||||
(light {
|
(light {
|
||||||
topic = "zigbee2mqtt/light_4";
|
topic = "zigbee2mqtt/light_4";
|
||||||
rooms = [ "office_room" ];
|
rooms = [ "office_room" ];
|
||||||
})
|
})
|
||||||
(light {
|
(light {
|
||||||
topic = "zigbee2mqtt/light_5";
|
topic = "zigbee2mqtt/light_5";
|
||||||
rooms = [ "storage_room" ];
|
rooms = [ "storage_room" ];
|
||||||
})
|
})
|
||||||
(light {
|
(light {
|
||||||
topic = "zigbee2mqtt/light_7";
|
topic = "zigbee2mqtt/light_7";
|
||||||
rooms = [ "sleeping_room" ];
|
rooms = [ "sleeping_room" ];
|
||||||
})
|
})
|
||||||
(led {
|
(led {
|
||||||
topic = "zigbee2mqtt/led_1";
|
topic = "zigbee2mqtt/led_1";
|
||||||
rooms = [ "office_room" ];
|
rooms = [ "office_room" ];
|
||||||
})
|
})
|
||||||
(led {
|
(led {
|
||||||
topic = "zigbee2mqtt/led_2";
|
topic = "zigbee2mqtt/led_2";
|
||||||
rooms = [ "kitchen" ];
|
rooms = [ "kitchen" ];
|
||||||
})
|
})
|
||||||
|
|
||||||
#(sonoff {
|
#(sonoff {
|
||||||
# id = "PAL01";
|
# id = "PAL01";
|
||||||
# rooms = [ "bed_room" ];
|
# rooms = [ "bed_room" ];
|
||||||
#})
|
#})
|
||||||
#(sonoff {
|
#(sonoff {
|
||||||
# id = "PAL03";
|
# id = "PAL03";
|
||||||
# rooms = [ "living_room" ];
|
# rooms = [ "living_room" ];
|
||||||
#})
|
#})
|
||||||
#(sonoff {
|
#(sonoff {
|
||||||
# id = "PAL04";
|
# id = "PAL04";
|
||||||
# rooms = [ "bed_room" ];
|
# rooms = [ "bed_room" ];
|
||||||
#})
|
#})
|
||||||
#(sonoff {
|
#(sonoff {
|
||||||
# id = "PAL06";
|
# id = "PAL06";
|
||||||
# rooms = [ "kitchen" ];
|
# rooms = [ "kitchen" ];
|
||||||
#})
|
#})
|
||||||
## monitor and speakers
|
## monitor and speakers
|
||||||
#(sonoff {
|
#(sonoff {
|
||||||
# id = "PAL07";
|
# id = "PAL07";
|
||||||
# rooms = [ "bed_room" ];
|
# rooms = [ "bed_room" ];
|
||||||
# delay = 180;
|
# delay = 180;
|
||||||
#})
|
#})
|
||||||
#(sonoff {
|
#(sonoff {
|
||||||
# id = "PAL08";
|
# id = "PAL08";
|
||||||
# rooms = [ "bed_room" ];
|
# rooms = [ "bed_room" ];
|
||||||
# delay = 180;
|
# delay = 180;
|
||||||
#})
|
#})
|
||||||
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,8 @@ let
|
||||||
|
|
||||||
toSwitch = name: "switch.${name}";
|
toSwitch = name: "switch.${name}";
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
imports = [ ./mqtt.nix ];
|
imports = [ ./mqtt.nix ];
|
||||||
|
|
||||||
|
@ -47,28 +48,32 @@ in {
|
||||||
|
|
||||||
# nicer names
|
# nicer names
|
||||||
# -----------
|
# -----------
|
||||||
homeassistant.customize = lib.mapAttrs' (entity:
|
homeassistant.customize = lib.mapAttrs'
|
||||||
{ label, icon ? "mdi:power-plug-off", ... }: {
|
(entity:
|
||||||
name = toSwitch entity;
|
{ label, icon ? "mdi:power-plug-off", ... }: {
|
||||||
value = {
|
name = toSwitch entity;
|
||||||
friendly_name = label;
|
value = {
|
||||||
icon = icon;
|
friendly_name = label;
|
||||||
};
|
icon = icon;
|
||||||
}) sonoffSwitches;
|
};
|
||||||
|
})
|
||||||
|
sonoffSwitches;
|
||||||
|
|
||||||
# define switches
|
# define switches
|
||||||
# ---------------
|
# ---------------
|
||||||
switch = lib.mapAttrsToList (name:
|
switch = lib.mapAttrsToList
|
||||||
{ ... }: {
|
(name:
|
||||||
name = name;
|
{ ... }: {
|
||||||
platform = "mqtt";
|
name = name;
|
||||||
command_topic = "cmnd/${lib.toUpper name}/POWER";
|
platform = "mqtt";
|
||||||
state_topic = "stat/${lib.toUpper name}/POWER";
|
command_topic = "cmnd/${lib.toUpper name}/POWER";
|
||||||
payload_on = "ON";
|
state_topic = "stat/${lib.toUpper name}/POWER";
|
||||||
payload_off = "OFF";
|
payload_on = "ON";
|
||||||
state_on = "ON";
|
payload_off = "OFF";
|
||||||
state_off = "OFF";
|
state_on = "ON";
|
||||||
}) sonoffSwitches;
|
state_off = "OFF";
|
||||||
|
})
|
||||||
|
sonoffSwitches;
|
||||||
|
|
||||||
# discover state on init
|
# discover state on init
|
||||||
# ----------------------
|
# ----------------------
|
||||||
|
@ -78,27 +83,34 @@ in {
|
||||||
platform = "homeassistant";
|
platform = "homeassistant";
|
||||||
event = "start";
|
event = "start";
|
||||||
};
|
};
|
||||||
action = lib.mapAttrsToList (name:
|
action = lib.mapAttrsToList
|
||||||
{ ... }: {
|
(name:
|
||||||
service = "mqtt.publish";
|
{ ... }: {
|
||||||
data = {
|
service = "mqtt.publish";
|
||||||
topic = "cmnd/${lib.toUpper name}/power";
|
data = {
|
||||||
payload = "";
|
topic = "cmnd/${lib.toUpper name}/power";
|
||||||
};
|
payload = "";
|
||||||
}) sonoffSwitches;
|
};
|
||||||
|
})
|
||||||
|
sonoffSwitches;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
# append to groups
|
# append to groups
|
||||||
# ----------------
|
# ----------------
|
||||||
group = let
|
group =
|
||||||
# sort lights into given groups.
|
let
|
||||||
sortedInGroups = let
|
# sort lights into given groups.
|
||||||
groupEntries = lib.zipAttrs (lib.flatten (lib.mapAttrsToList (name:
|
sortedInGroups =
|
||||||
{ groups ? [ ], ... }:
|
let
|
||||||
map (groupName: { "${groupName}" = "switch.${name}"; }) groups)
|
groupEntries = lib.zipAttrs (lib.flatten (lib.mapAttrsToList
|
||||||
sonoffSwitches));
|
(name:
|
||||||
in lib.mapAttrs (name: entities: { inherit entities; }) groupEntries;
|
{ groups ? [ ], ... }:
|
||||||
in sortedInGroups;
|
map (groupName: { "${groupName}" = "switch.${name}"; }) groups)
|
||||||
|
sonoffSwitches));
|
||||||
|
in
|
||||||
|
lib.mapAttrs (name: entities: { inherit entities; }) groupEntries;
|
||||||
|
in
|
||||||
|
sortedInGroups;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,40 +27,43 @@ let
|
||||||
|
|
||||||
cleanup_list = list: lib.filter (entry: entry != { }) (lib.flatten list);
|
cleanup_list = list: lib.filter (entry: entry != { }) (lib.flatten list);
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
services.homeAssistantConfig = {
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
sensor = cleanup_list (map ({ name, currency, own ? { }, ... }: [
|
sensor = cleanup_list (map
|
||||||
{
|
({ name, currency, own ? { }, ... }: [
|
||||||
platform = "file";
|
{
|
||||||
name = "stock_${name}";
|
platform = "file";
|
||||||
file_path = filePath name;
|
name = "stock_${name}";
|
||||||
value_template = "{{ value_json.price}} ${currency}";
|
file_path = filePath name;
|
||||||
|
value_template = "{{ value_json.price}} ${currency}";
|
||||||
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
platform = "file";
|
platform = "file";
|
||||||
name = "stock_${name}_change";
|
name = "stock_${name}_change";
|
||||||
file_path = filePath name;
|
file_path = filePath name;
|
||||||
value_template = "{{ value_json.change}} ${currency}";
|
value_template = "{{ value_json.change}} ${currency}";
|
||||||
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
platform = "file";
|
platform = "file";
|
||||||
name = "stock_${name}_change_percent";
|
name = "stock_${name}_change_percent";
|
||||||
file_path = filePath name;
|
file_path = filePath name;
|
||||||
value_template = "{{ value_json.change_percent}} %";
|
value_template = "{{ value_json.change_percent}} %";
|
||||||
}
|
}
|
||||||
(lib.optionalAttrs (own != { }) {
|
(lib.optionalAttrs (own != { }) {
|
||||||
platform = "file";
|
platform = "file";
|
||||||
name = "stock_${name}_profit";
|
name = "stock_${name}_profit";
|
||||||
file_path = filePath name;
|
file_path = filePath name;
|
||||||
value_template = ''
|
value_template = ''
|
||||||
{{ "{:,.2f}".format( value_json.price * ${toString own.pieces} - ${
|
{{ "{:,.2f}".format( value_json.price * ${toString own.pieces} - ${
|
||||||
toString (own.pieces * own.price)
|
toString (own.pieces * own.price)
|
||||||
} ) }} ${currency}'';
|
} ) }} ${currency}'';
|
||||||
})
|
})
|
||||||
]) stocks);
|
])
|
||||||
|
stocks);
|
||||||
|
|
||||||
homeassistant = {
|
homeassistant = {
|
||||||
whitelist_external_dirs = [ folderPath ];
|
whitelist_external_dirs = [ folderPath ];
|
||||||
|
@ -94,7 +97,8 @@ in {
|
||||||
friendly_name = "Profit";
|
friendly_name = "Profit";
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
]) stocks));
|
])
|
||||||
|
stocks));
|
||||||
};
|
};
|
||||||
|
|
||||||
group = (builtins.listToAttrs (map
|
group = (builtins.listToAttrs (map
|
||||||
|
@ -108,66 +112,71 @@ in {
|
||||||
"sensor.stock_${name}_change_percent"
|
"sensor.stock_${name}_change_percent"
|
||||||
] ++ (lib.optional (own != { }) "sensor.stock_${name}_profit");
|
] ++ (lib.optional (own != { }) "sensor.stock_${name}_profit");
|
||||||
};
|
};
|
||||||
}) stocks));
|
})
|
||||||
|
stocks));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services = let
|
systemd.services =
|
||||||
pullService = { name, symbol, currency, ... }: {
|
let
|
||||||
name = "pull_stock_${name}";
|
pullService = { name, symbol, currency, ... }: {
|
||||||
value = {
|
name = "pull_stock_${name}";
|
||||||
enable = true;
|
value = {
|
||||||
before = [ "home-assistant.service" ];
|
enable = true;
|
||||||
wantedBy = [ "home-assistant.service" ];
|
before = [ "home-assistant.service" ];
|
||||||
serviceConfig = {
|
wantedBy = [ "home-assistant.service" ];
|
||||||
User = "hass";
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
User = "hass";
|
||||||
};
|
Type = "oneshot";
|
||||||
description = "pull stock_${name} for homeassistant";
|
};
|
||||||
script = ''
|
description = "pull stock_${name} for homeassistant";
|
||||||
SYMBOL="${symbol}"
|
script = ''
|
||||||
CURRENCY="${currency}"
|
SYMBOL="${symbol}"
|
||||||
APIKEY=${
|
CURRENCY="${currency}"
|
||||||
lib.fileContents <secrets/home-assistant/alphavantage/apikey>
|
APIKEY=${
|
||||||
}
|
lib.fileContents <secrets/home-assistant/alphavantage/apikey>
|
||||||
|
}
|
||||||
|
|
||||||
${pkgs.curl}/bin/curl --location --silent \
|
${pkgs.curl}/bin/curl --location --silent \
|
||||||
"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=$SYMBOL&apikey=$APIKEY" \
|
"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=$SYMBOL&apikey=$APIKEY" \
|
||||||
| ${pkgs.jq}/bin/jq --compact-output \
|
| ${pkgs.jq}/bin/jq --compact-output \
|
||||||
'.["Global Quote"] |
|
'.["Global Quote"] |
|
||||||
{
|
{
|
||||||
price: .["05. price"] | tonumber,
|
price: .["05. price"] | tonumber,
|
||||||
currency: "'$CURRENCY'",
|
currency: "'$CURRENCY'",
|
||||||
change_percent: .["10. change percent"] | .[0:-1] | tonumber,
|
change_percent: .["10. change percent"] | .[0:-1] | tonumber,
|
||||||
change: .["09. change"] | tonumber,
|
change: .["09. change"] | tonumber,
|
||||||
last_date: .["07. latest trading day"],
|
last_date: .["07. latest trading day"],
|
||||||
}' \
|
}' \
|
||||||
>> ${filePath name}
|
>> ${filePath name}
|
||||||
|
|
||||||
# old and stupid
|
# old and stupid
|
||||||
#${pkgs.curl}/bin/curl --location --silent \
|
#${pkgs.curl}/bin/curl --location --silent \
|
||||||
#"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=$SYMBOL&interval=5min&apikey=$APIKEY" \
|
#"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=$SYMBOL&interval=5min&apikey=$APIKEY" \
|
||||||
#| ${pkgs.jq}/bin/jq --compact-output \
|
#| ${pkgs.jq}/bin/jq --compact-output \
|
||||||
# '.["Time Series (5min)"] | to_entries | [ .[]
|
# '.["Time Series (5min)"] | to_entries | [ .[]
|
||||||
# | { date : .key , value : .value["4. close"], currency: "'$CURRENCY'" } ]
|
# | { date : .key , value : .value["4. close"], currency: "'$CURRENCY'" } ]
|
||||||
# | sort_by(.date) | reverse | .[0]' \
|
# | sort_by(.date) | reverse | .[0]' \
|
||||||
'';
|
'';
|
||||||
};
|
|
||||||
};
|
|
||||||
in builtins.listToAttrs (map pullService stocks);
|
|
||||||
|
|
||||||
systemd.timers = let
|
|
||||||
pullTimer = { name, ... }: {
|
|
||||||
name = "pull_stock_${name}";
|
|
||||||
value = {
|
|
||||||
enable = true;
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
timerConfig = {
|
|
||||||
OnCalendar = "hourly";
|
|
||||||
Persistent = "true";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
in
|
||||||
in builtins.listToAttrs (map pullTimer stocks);
|
builtins.listToAttrs (map pullService stocks);
|
||||||
|
|
||||||
|
systemd.timers =
|
||||||
|
let
|
||||||
|
pullTimer = { name, ... }: {
|
||||||
|
name = "pull_stock_${name}";
|
||||||
|
value = {
|
||||||
|
enable = true;
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
timerConfig = {
|
||||||
|
OnCalendar = "hourly";
|
||||||
|
Persistent = "true";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
builtins.listToAttrs (map pullTimer stocks);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
let
|
let
|
||||||
holiday-range = month: dayA: dayB:
|
holiday-range = month: dayA: dayB:
|
||||||
map (day: "${month}-${toString day}")
|
map (day: "${month}-${toString day}")
|
||||||
(map (lib.fixedWidthNumber 2) (lib.range dayA dayB));
|
(map (lib.fixedWidthNumber 2) (lib.range dayA dayB));
|
||||||
privateHolidays = import <secrets/home-assistant/holidays>;
|
privateHolidays = import <secrets/home-assistant/holidays>;
|
||||||
# for example :
|
# for example :
|
||||||
# holidays = lib.flatten [
|
# holidays = lib.flatten [
|
||||||
|
@ -11,7 +11,8 @@ let
|
||||||
#];
|
#];
|
||||||
holidays = lib.flatten (privateHolidays holiday-range);
|
holidays = lib.flatten (privateHolidays holiday-range);
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
services.homeAssistantConfig = {
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
binary_sensor = [
|
binary_sensor = [
|
||||||
|
|
|
@ -32,81 +32,91 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
{ id, ... }: {
|
(name:
|
||||||
name = id;
|
{ id, ... }: {
|
||||||
value = {
|
name = id;
|
||||||
retain = false;
|
value = {
|
||||||
friendly_name = name;
|
retain = false;
|
||||||
};
|
friendly_name = name;
|
||||||
}) allDevices;
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
# define input_boolean
|
# define input_boolean
|
||||||
# --------------------
|
# --------------------
|
||||||
# which get toggled by the buttons
|
# which get toggled by the buttons
|
||||||
input_boolean = let stripEmpty = lib.filter (a: a != { });
|
input_boolean =
|
||||||
in builtins.listToAttrs (stripEmpty (lib.flatten (lib.mapAttrsToList (name:
|
let stripEmpty = lib.filter (a: a != { });
|
||||||
{ states ? { }, ... }: [
|
in builtins.listToAttrs (stripEmpty (lib.flatten (lib.mapAttrsToList
|
||||||
(lib.optionalAttrs (!lib.hasAttr "single" states) {
|
(name:
|
||||||
name = "single_${name}";
|
{ states ? { }, ... }: [
|
||||||
value = { icon = "mdi:toggle-switch"; };
|
(lib.optionalAttrs (!lib.hasAttr "single" states) {
|
||||||
})
|
name = "single_${name}";
|
||||||
(lib.optionalAttrs (!lib.hasAttr "double" states) {
|
value = { icon = "mdi:toggle-switch"; };
|
||||||
name = "double_${name}";
|
})
|
||||||
value = { icon = "mdi:toggle-switch"; };
|
(lib.optionalAttrs (!lib.hasAttr "double" states) {
|
||||||
})
|
name = "double_${name}";
|
||||||
(lib.optionalAttrs (!lib.hasAttr "hold" states) {
|
value = { icon = "mdi:toggle-switch"; };
|
||||||
name = "hold_${name}";
|
})
|
||||||
value = { icon = "mdi:toggle-switch"; };
|
(lib.optionalAttrs (!lib.hasAttr "hold" states) {
|
||||||
})
|
name = "hold_${name}";
|
||||||
]) allDevices)));
|
value = { icon = "mdi:toggle-switch"; };
|
||||||
|
})
|
||||||
|
])
|
||||||
|
allDevices)));
|
||||||
|
|
||||||
# define meta information sensors
|
# define meta information sensors
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
{ ... }: [
|
(name:
|
||||||
{
|
{ ... }: [
|
||||||
platform = "mqtt";
|
{
|
||||||
name = name;
|
platform = "mqtt";
|
||||||
icon = "mdi:toggle-switch";
|
name = name;
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
icon = "mdi:toggle-switch";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
value_template = "{{ value_json.click }}";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
}
|
value_template = "{{ value_json.click }}";
|
||||||
{
|
}
|
||||||
name = "battery_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "battery_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
unit_of_measurement = "%";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
icon = "mdi:battery-10";
|
unit_of_measurement = "%";
|
||||||
value_template = "{{ value_json.battery }}";
|
icon = "mdi:battery-10";
|
||||||
}
|
value_template = "{{ value_json.battery }}";
|
||||||
{
|
}
|
||||||
name = "link_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "link_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
icon = "mdi:signal";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
unit_of_measurement = "lqi";
|
icon = "mdi:signal";
|
||||||
value_template = "{{ value_json.linkquality }}";
|
unit_of_measurement = "lqi";
|
||||||
}
|
value_template = "{{ value_json.linkquality }}";
|
||||||
]) allDevices);
|
}
|
||||||
|
])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
binary_sensor = lib.mapAttrsToList (name:
|
binary_sensor = lib.mapAttrsToList
|
||||||
{ ... }: {
|
(name:
|
||||||
name = name;
|
{ ... }: {
|
||||||
platform = "mqtt";
|
name = name;
|
||||||
device_class = "motion";
|
platform = "mqtt";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
device_class = "motion";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
payload_on = true;
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
payload_off = false;
|
payload_on = true;
|
||||||
value_template = "{{ value_json.occupancy }}";
|
payload_off = false;
|
||||||
}) allDevices;
|
value_template = "{{ value_json.occupancy }}";
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
# create groups
|
# create groups
|
||||||
# -------------
|
# -------------
|
||||||
|
@ -144,82 +154,96 @@ in {
|
||||||
|
|
||||||
# create automation
|
# create automation
|
||||||
# -----------------
|
# -----------------
|
||||||
automation = let
|
automation =
|
||||||
|
let
|
||||||
|
|
||||||
# single click
|
# single click
|
||||||
toggle_single_button_input = lib.mapAttrsToList (name:
|
toggle_single_button_input = lib.mapAttrsToList
|
||||||
{ states ? { }, ... }:
|
(name:
|
||||||
let
|
{ states ? { }, ... }:
|
||||||
entityId = if (lib.hasAttr "single" states) then
|
let
|
||||||
states.single
|
entityId =
|
||||||
else
|
if (lib.hasAttr "single" states) then
|
||||||
"input_boolean.single_${name}";
|
states.single
|
||||||
in {
|
else
|
||||||
alias = "toggle single click ${name}";
|
"input_boolean.single_${name}";
|
||||||
trigger = {
|
in
|
||||||
platform = "mqtt";
|
{
|
||||||
topic = "zigbee2mqtt/${name}";
|
alias = "toggle single click ${name}";
|
||||||
};
|
trigger = {
|
||||||
condition = {
|
platform = "mqtt";
|
||||||
condition = "template";
|
topic = "zigbee2mqtt/${name}";
|
||||||
value_template = ''{{ "single" == trigger.payload_json.click}}'';
|
};
|
||||||
};
|
condition = {
|
||||||
action = {
|
condition = "template";
|
||||||
service = "input_boolean.toggle";
|
value_template = ''{{ "single" == trigger.payload_json.click}}'';
|
||||||
data.entity_id = entityId;
|
};
|
||||||
};
|
action = {
|
||||||
}) allDevices;
|
service = "input_boolean.toggle";
|
||||||
|
data.entity_id = entityId;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
# double click
|
# double click
|
||||||
toggle_double_button_input = lib.mapAttrsToList (name:
|
toggle_double_button_input = lib.mapAttrsToList
|
||||||
{ states ? { }, ... }:
|
(name:
|
||||||
let
|
{ states ? { }, ... }:
|
||||||
entityId = if (lib.hasAttr "double" states) then
|
let
|
||||||
states.double
|
entityId =
|
||||||
else
|
if (lib.hasAttr "double" states) then
|
||||||
"input_boolean.double_${name}";
|
states.double
|
||||||
in {
|
else
|
||||||
alias = "toggle double click ${name}";
|
"input_boolean.double_${name}";
|
||||||
trigger = {
|
in
|
||||||
platform = "mqtt";
|
{
|
||||||
topic = "zigbee2mqtt/${name}";
|
alias = "toggle double click ${name}";
|
||||||
};
|
trigger = {
|
||||||
condition = {
|
platform = "mqtt";
|
||||||
condition = "template";
|
topic = "zigbee2mqtt/${name}";
|
||||||
value_template = ''{{ "double" == trigger.payload_json.click}}'';
|
};
|
||||||
};
|
condition = {
|
||||||
action = {
|
condition = "template";
|
||||||
service = "input_boolean.toggle";
|
value_template = ''{{ "double" == trigger.payload_json.click}}'';
|
||||||
data.entity_id = entityId;
|
};
|
||||||
};
|
action = {
|
||||||
}) allDevices;
|
service = "input_boolean.toggle";
|
||||||
|
data.entity_id = entityId;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
# hold
|
# hold
|
||||||
toggle_hold_button_input = lib.mapAttrsToList (name:
|
toggle_hold_button_input = lib.mapAttrsToList
|
||||||
{ states ? { }, ... }:
|
(name:
|
||||||
let
|
{ states ? { }, ... }:
|
||||||
entityId = if (lib.hasAttr "hold" states) then
|
let
|
||||||
states.hold
|
entityId =
|
||||||
else
|
if (lib.hasAttr "hold" states) then
|
||||||
"input_boolean.hold_${name}";
|
states.hold
|
||||||
in {
|
else
|
||||||
alias = "toggle hold ${name}";
|
"input_boolean.hold_${name}";
|
||||||
trigger = {
|
in
|
||||||
platform = "mqtt";
|
{
|
||||||
topic = "zigbee2mqtt/${name}";
|
alias = "toggle hold ${name}";
|
||||||
};
|
trigger = {
|
||||||
condition = {
|
platform = "mqtt";
|
||||||
condition = "template";
|
topic = "zigbee2mqtt/${name}";
|
||||||
value_template = ''{{ "hold" == trigger.payload_json.action}}'';
|
};
|
||||||
};
|
condition = {
|
||||||
action = {
|
condition = "template";
|
||||||
service = "input_boolean.toggle";
|
value_template = ''{{ "hold" == trigger.payload_json.action}}'';
|
||||||
data.entity_id = entityId;
|
};
|
||||||
};
|
action = {
|
||||||
}) allDevices;
|
service = "input_boolean.toggle";
|
||||||
|
data.entity_id = entityId;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
in lib.flatten (toggle_single_button_input ++ toggle_double_button_input
|
in
|
||||||
++ toggle_hold_button_input);
|
lib.flatten (toggle_single_button_input ++ toggle_double_button_input
|
||||||
|
++ toggle_hold_button_input);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,77 +10,91 @@ let
|
||||||
"door_sensor_5" = { id = "0x00158d0003120d3e"; };
|
"door_sensor_5" = { id = "0x00158d0003120d3e"; };
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
{ id, ... }: {
|
(name:
|
||||||
name = id;
|
{ id, ... }: {
|
||||||
value = {
|
name = id;
|
||||||
retain = false;
|
value = {
|
||||||
friendly_name = name;
|
retain = false;
|
||||||
};
|
friendly_name = name;
|
||||||
}) allDevices;
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
# define meta information sensors
|
# define meta information sensors
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
{ ... }: [
|
(name:
|
||||||
{
|
{ ... }: [
|
||||||
name = "battery_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "battery_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
unit_of_measurement = "%";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
icon = "mdi:battery-10";
|
unit_of_measurement = "%";
|
||||||
value_template = "{{ value_json.battery }}";
|
icon = "mdi:battery-10";
|
||||||
}
|
value_template = "{{ value_json.battery }}";
|
||||||
{
|
}
|
||||||
name = "link_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "link_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
icon = "mdi:signal";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
unit_of_measurement = "lqi";
|
icon = "mdi:signal";
|
||||||
value_template = "{{ value_json.linkquality }}";
|
unit_of_measurement = "lqi";
|
||||||
}
|
value_template = "{{ value_json.linkquality }}";
|
||||||
]) allDevices);
|
}
|
||||||
|
])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
binary_sensor = lib.mapAttrsToList (name:
|
binary_sensor = lib.mapAttrsToList
|
||||||
{ ... }: {
|
(name:
|
||||||
name = name;
|
{ ... }: {
|
||||||
platform = "mqtt";
|
name = name;
|
||||||
device_class = "door";
|
platform = "mqtt";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
device_class = "door";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
payload_on = false;
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
payload_off = true;
|
payload_on = false;
|
||||||
value_template = "{{ value_json.contact}}";
|
payload_off = true;
|
||||||
}) allDevices;
|
value_template = "{{ value_json.contact}}";
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
# create groups
|
# create groups
|
||||||
# -------------
|
# -------------
|
||||||
group = let
|
group =
|
||||||
# to have nice panels for every device
|
let
|
||||||
sensorGroups = lib.mapAttrs (name:
|
# to have nice panels for every device
|
||||||
{ ... }: {
|
sensorGroups = lib.mapAttrs
|
||||||
entities = [
|
(name:
|
||||||
"binary_sensor.${name}"
|
{ ... }: {
|
||||||
"sensor.battery_${name}"
|
entities = [
|
||||||
"sensor.link_${name}"
|
"binary_sensor.${name}"
|
||||||
];
|
"sensor.battery_${name}"
|
||||||
}) allDevices;
|
"sensor.link_${name}"
|
||||||
# sort lights into given groups.
|
];
|
||||||
sortedInGroups = let
|
})
|
||||||
groupEntries = lib.zipAttrs (lib.flatten (lib.mapAttrsToList (name:
|
allDevices;
|
||||||
{ groups ? [ ], ... }:
|
# sort lights into given groups.
|
||||||
map (groupName: { "${groupName}" = "binary_sensor.${name}"; }) groups)
|
sortedInGroups =
|
||||||
allDevices));
|
let
|
||||||
in lib.mapAttrs (name: entities: { inherit entities; }) groupEntries;
|
groupEntries = lib.zipAttrs (lib.flatten (lib.mapAttrsToList
|
||||||
in sortedInGroups // sensorGroups // {
|
(name:
|
||||||
all_sensors.entities =
|
{ groups ? [ ], ... }:
|
||||||
lib.mapAttrsToList (name: { ... }: "binary_sensor.${name}") allDevices;
|
map (groupName: { "${groupName}" = "binary_sensor.${name}"; }) groups)
|
||||||
};
|
allDevices));
|
||||||
|
in
|
||||||
|
lib.mapAttrs (name: entities: { inherit entities; }) groupEntries;
|
||||||
|
in
|
||||||
|
sortedInGroups // sensorGroups // {
|
||||||
|
all_sensors.entities =
|
||||||
|
lib.mapAttrsToList (name: { ... }: "binary_sensor.${name}") allDevices;
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,41 +11,46 @@ let
|
||||||
|
|
||||||
# -t "zigbee2mqtt/fyrtur1/set" -m '{"position":100}'
|
# -t "zigbee2mqtt/fyrtur1/set" -m '{"position":100}'
|
||||||
# -t "zigbee2mqtt/fyrtur1/set" -m '{"position":15}'
|
# -t "zigbee2mqtt/fyrtur1/set" -m '{"position":15}'
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
{ id, ... }: {
|
(name:
|
||||||
name = id;
|
{ id, ... }: {
|
||||||
value = {
|
name = id;
|
||||||
retain = false;
|
value = {
|
||||||
friendly_name = name;
|
retain = false;
|
||||||
transition = 0.1;
|
friendly_name = name;
|
||||||
};
|
transition = 0.1;
|
||||||
}) allDevices;
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
{ ... }: [
|
(name:
|
||||||
{
|
{ ... }: [
|
||||||
name = "battery_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "battery_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
unit_of_measurement = "%";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
icon = "mdi:battery-10";
|
unit_of_measurement = "%";
|
||||||
value_template = "{{ value_json.battery }}";
|
icon = "mdi:battery-10";
|
||||||
}
|
value_template = "{{ value_json.battery }}";
|
||||||
{
|
}
|
||||||
name = "link_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "link_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
icon = "mdi:signal";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
unit_of_measurement = "lqi";
|
icon = "mdi:signal";
|
||||||
value_template = "{{ value_json.linkquality }}";
|
unit_of_measurement = "lqi";
|
||||||
}
|
value_template = "{{ value_json.linkquality }}";
|
||||||
]) allDevices);
|
}
|
||||||
|
])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,68 +12,73 @@ let
|
||||||
# -t "zigbee2mqtt/heater3/set" -m '{"system_mode":"auto","current_heating_setpoint":23}'
|
# -t "zigbee2mqtt/heater3/set" -m '{"system_mode":"auto","current_heating_setpoint":23}'
|
||||||
# -t "zigbee2mqtt/heater3/set" -m '{"system_mode":"off"}'
|
# -t "zigbee2mqtt/heater3/set" -m '{"system_mode":"off"}'
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
{ id, ... }: {
|
(name:
|
||||||
name = id;
|
{ id, ... }: {
|
||||||
value = {
|
name = id;
|
||||||
legacy = false;
|
value = {
|
||||||
retain = false;
|
legacy = false;
|
||||||
friendly_name = name;
|
retain = false;
|
||||||
transition = 1;
|
friendly_name = name;
|
||||||
debounce = 0.5;
|
transition = 1;
|
||||||
filtered_attributes = [
|
debounce = 0.5;
|
||||||
"battery_low"
|
filtered_attributes = [
|
||||||
"eurotronic_host_flags"
|
"battery_low"
|
||||||
"eurotronic_system_mode"
|
"eurotronic_host_flags"
|
||||||
#"occupied_heating_setpoint"
|
"eurotronic_system_mode"
|
||||||
#"pi_heating_demand"
|
#"occupied_heating_setpoint"
|
||||||
#"unoccupied_heating_setpoint"
|
#"pi_heating_demand"
|
||||||
];
|
#"unoccupied_heating_setpoint"
|
||||||
};
|
];
|
||||||
}) allDevices;
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
{ ... }: [
|
(name:
|
||||||
{
|
{ ... }: [
|
||||||
name = "battery_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "battery_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
unit_of_measurement = "%";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
icon = "mdi:battery-10";
|
unit_of_measurement = "%";
|
||||||
value_template = "{{ value_json.battery }}";
|
icon = "mdi:battery-10";
|
||||||
}
|
value_template = "{{ value_json.battery }}";
|
||||||
{
|
}
|
||||||
name = "link_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "link_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
icon = "mdi:signal";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
unit_of_measurement = "lqi";
|
icon = "mdi:signal";
|
||||||
value_template = "{{ value_json.linkquality }}";
|
unit_of_measurement = "lqi";
|
||||||
}
|
value_template = "{{ value_json.linkquality }}";
|
||||||
{
|
}
|
||||||
platform = "mqtt";
|
{
|
||||||
name = "temperature_${name}";
|
platform = "mqtt";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
name = "temperature_${name}";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
unit_of_measurement = "°C";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
device_class = "temperature";
|
unit_of_measurement = "°C";
|
||||||
value_template = "{{ value_json.local_temperature }}";
|
device_class = "temperature";
|
||||||
}
|
value_template = "{{ value_json.local_temperature }}";
|
||||||
{
|
}
|
||||||
platform = "mqtt";
|
{
|
||||||
name = "pi_heating_demand_${name}";
|
platform = "mqtt";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
name = "pi_heating_demand_${name}";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
unit_of_measurement = "%";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
value_template = "{{ value_json.pi_heating_demand }}";
|
unit_of_measurement = "%";
|
||||||
}
|
value_template = "{{ value_json.pi_heating_demand }}";
|
||||||
]) allDevices);
|
}
|
||||||
|
])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,32 +11,37 @@ let
|
||||||
# -t "zigbee2mqtt/led_1/set" -m '{"state":"OFF","transition":0, "color_temp":255}'
|
# -t "zigbee2mqtt/led_1/set" -m '{"state":"OFF","transition":0, "color_temp":255}'
|
||||||
# -t "zigbee2mqtt/led_1/set" -m '{"state":"ON","brightness":255,"color":{"hex":"#00FFFF"}}'
|
# -t "zigbee2mqtt/led_1/set" -m '{"state":"ON","brightness":255,"color":{"hex":"#00FFFF"}}'
|
||||||
# -t "zigbee2mqtt/led_1/set" -m '{"state":"OFF"}'
|
# -t "zigbee2mqtt/led_1/set" -m '{"state":"OFF"}'
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
{ id, ... }: {
|
(name:
|
||||||
name = id;
|
{ id, ... }: {
|
||||||
value = {
|
name = id;
|
||||||
retain = false;
|
value = {
|
||||||
friendly_name = name;
|
retain = false;
|
||||||
transition = 1;
|
friendly_name = name;
|
||||||
};
|
transition = 1;
|
||||||
}) allDevices;
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
light = lib.mapAttrsToList (name:
|
light = lib.mapAttrsToList
|
||||||
{ ... }: {
|
(name:
|
||||||
platform = "mqtt";
|
{ ... }: {
|
||||||
name = name;
|
platform = "mqtt";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
name = name;
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
command_topic = "zigbee2mqtt/${name}/set";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
value_template = "{{ value_json.click }}";
|
command_topic = "zigbee2mqtt/${name}/set";
|
||||||
brightness = true;
|
value_template = "{{ value_json.click }}";
|
||||||
color_temp = true;
|
brightness = true;
|
||||||
schema = "json";
|
color_temp = true;
|
||||||
}) allDevices;
|
schema = "json";
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,32 +13,37 @@ let
|
||||||
"light_8" = { id = "0x7cb03eaa0a0384d3"; };
|
"light_8" = { id = "0x7cb03eaa0a0384d3"; };
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
{ id, ... }: {
|
(name:
|
||||||
name = id;
|
{ id, ... }: {
|
||||||
value = {
|
name = id;
|
||||||
retain = false;
|
value = {
|
||||||
friendly_name = name;
|
retain = false;
|
||||||
osram_set_transition = 2; # time in seconds (integer or float)
|
friendly_name = name;
|
||||||
};
|
osram_set_transition = 2; # time in seconds (integer or float)
|
||||||
}) allDevices;
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
light = lib.mapAttrsToList (name:
|
light = lib.mapAttrsToList
|
||||||
{ ... }: {
|
(name:
|
||||||
platform = "mqtt";
|
{ ... }: {
|
||||||
name = name;
|
platform = "mqtt";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
name = name;
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
command_topic = "zigbee2mqtt/${name}/set";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
value_template = "{{ value_json.click }}";
|
command_topic = "zigbee2mqtt/${name}/set";
|
||||||
brightness = true;
|
value_template = "{{ value_json.click }}";
|
||||||
color_temp = true;
|
brightness = true;
|
||||||
schema = "json";
|
color_temp = true;
|
||||||
}) allDevices;
|
schema = "json";
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
# sensor = with lib;
|
# sensor = with lib;
|
||||||
# mapAttrsToList (name:
|
# mapAttrsToList (name:
|
||||||
|
|
|
@ -14,56 +14,63 @@ let
|
||||||
"motion_sensor_8" = { id = "0x00158d0002f04637"; };
|
"motion_sensor_8" = { id = "0x00158d0002f04637"; };
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
{ id, timeout ? 65, ... }: {
|
(name:
|
||||||
name = id;
|
{ id, timeout ? 65, ... }: {
|
||||||
value = {
|
name = id;
|
||||||
retain = false;
|
value = {
|
||||||
friendly_name = name;
|
retain = false;
|
||||||
# should not be set below 60 seconds
|
friendly_name = name;
|
||||||
occupancy_timeout = timeout;
|
# should not be set below 60 seconds
|
||||||
};
|
occupancy_timeout = timeout;
|
||||||
}) allDevices;
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
# define meta information sensors
|
# define meta information sensors
|
||||||
binary_sensor = lib.flatten (lib.mapAttrsToList (name:
|
binary_sensor = lib.flatten (lib.mapAttrsToList
|
||||||
{ ... }: [{
|
(name:
|
||||||
name = "${name}";
|
{ ... }: [{
|
||||||
platform = "mqtt";
|
name = "${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
value_template = "{{ value_json.occupancy }}";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
#icon = "mdi:battery-10";
|
value_template = "{{ value_json.occupancy }}";
|
||||||
payload_on = true;
|
#icon = "mdi:battery-10";
|
||||||
payload_off = false;
|
payload_on = true;
|
||||||
device_class = "motion";
|
payload_off = false;
|
||||||
}]) allDevices);
|
device_class = "motion";
|
||||||
|
}])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
# define meta information sensors
|
# define meta information sensors
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
{ ... }: [
|
(name:
|
||||||
{
|
{ ... }: [
|
||||||
name = "battery_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "battery_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
unit_of_measurement = "%";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
icon = "mdi:battery-10";
|
unit_of_measurement = "%";
|
||||||
value_template = "{{ value_json.battery }}";
|
icon = "mdi:battery-10";
|
||||||
}
|
value_template = "{{ value_json.battery }}";
|
||||||
{
|
}
|
||||||
name = "link_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "link_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
icon = "mdi:signal";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
unit_of_measurement = "lqi";
|
icon = "mdi:signal";
|
||||||
value_template = "{{ value_json.linkquality }}";
|
unit_of_measurement = "lqi";
|
||||||
}
|
value_template = "{{ value_json.linkquality }}";
|
||||||
]) allDevices);
|
}
|
||||||
|
])
|
||||||
|
allDevices);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,13 @@ let
|
||||||
"repeater4" = { id = "0x680ae2fffe8e2e71"; };
|
"repeater4" = { id = "0x680ae2fffe8e2e71"; };
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
{
|
||||||
{ id, ... }: {
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
name = id;
|
(name:
|
||||||
value = { friendly_name = name; };
|
{ id, ... }: {
|
||||||
}) allDevices;
|
name = id;
|
||||||
|
value = { friendly_name = name; };
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@ let
|
||||||
# is copied from the store on startup
|
# is copied from the store on startup
|
||||||
devices = "devices.yaml";
|
devices = "devices.yaml";
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
options.custom.services.zigbee2mqtt = {
|
options.custom.services.zigbee2mqtt = {
|
||||||
enable = mkEnableOption "enable zigbee2mqtt service";
|
enable = mkEnableOption "enable zigbee2mqtt service";
|
||||||
|
|
||||||
|
|
|
@ -13,68 +13,73 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
{ id, ... }: {
|
(name:
|
||||||
name = id;
|
{ id, ... }: {
|
||||||
value = {
|
name = id;
|
||||||
retain = false;
|
value = {
|
||||||
friendly_name = name;
|
retain = false;
|
||||||
};
|
friendly_name = name;
|
||||||
}) allDevices;
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
# define meta information sensors
|
# define meta information sensors
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
{ ... }: [
|
(name:
|
||||||
{
|
{ ... }: [
|
||||||
platform = "mqtt";
|
{
|
||||||
name = name;
|
platform = "mqtt";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
name = name;
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
unit_of_measurement = "°C";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
device_class = "temperature";
|
unit_of_measurement = "°C";
|
||||||
value_template = "{{ value_json.temperature }}";
|
device_class = "temperature";
|
||||||
}
|
value_template = "{{ value_json.temperature }}";
|
||||||
{
|
}
|
||||||
platform = "mqtt";
|
{
|
||||||
name = "humidity_${name}";
|
platform = "mqtt";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
name = "humidity_${name}";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
unit_of_measurement = "%";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
device_class = "humidity";
|
unit_of_measurement = "%";
|
||||||
value_template = "{{ value_json.humidity }}";
|
device_class = "humidity";
|
||||||
}
|
value_template = "{{ value_json.humidity }}";
|
||||||
#{
|
}
|
||||||
# platform = "mqtt";
|
#{
|
||||||
# name = "pressure_${name}";
|
# platform = "mqtt";
|
||||||
# state_topic = "zigbee2mqtt/${name}";
|
# name = "pressure_${name}";
|
||||||
# availability_topic = "zigbee2mqtt/bridge/state";
|
# state_topic = "zigbee2mqtt/${name}";
|
||||||
# unit_of_measurement = "hPa";
|
# availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
# device_class = "pressure";
|
# unit_of_measurement = "hPa";
|
||||||
# value_template = "{{ value_json.pressure }}";
|
# device_class = "pressure";
|
||||||
#}
|
# value_template = "{{ value_json.pressure }}";
|
||||||
{
|
#}
|
||||||
name = "battery_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "battery_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
unit_of_measurement = "%";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
icon = "mdi:battery-10";
|
unit_of_measurement = "%";
|
||||||
value_template = "{{ value_json.battery }}";
|
icon = "mdi:battery-10";
|
||||||
}
|
value_template = "{{ value_json.battery }}";
|
||||||
{
|
}
|
||||||
name = "link_${name}";
|
{
|
||||||
platform = "mqtt";
|
name = "link_${name}";
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
platform = "mqtt";
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
icon = "mdi:signal";
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
unit_of_measurement = "lqi";
|
icon = "mdi:signal";
|
||||||
value_template = "{{ value_json.linkquality }}";
|
unit_of_measurement = "lqi";
|
||||||
}
|
value_template = "{{ value_json.linkquality }}";
|
||||||
]) allDevices);
|
}
|
||||||
|
])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
# create groups
|
# create groups
|
||||||
# -------------
|
# -------------
|
||||||
|
|
|
@ -5,7 +5,8 @@ let
|
||||||
ipAddress = "10.1.0.2";
|
ipAddress = "10.1.0.2";
|
||||||
prefixLength = 24;
|
prefixLength = 24;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
networking.extraHosts = ''
|
networking.extraHosts = ''
|
||||||
10.1.0.1 workout.lan
|
10.1.0.1 workout.lan
|
||||||
|
|
|
@ -30,63 +30,63 @@
|
||||||
|
|
||||||
services.spotifyd.enable = true;
|
services.spotifyd.enable = true;
|
||||||
services.spotifyd.config = ''
|
services.spotifyd.config = ''
|
||||||
[global]
|
[global]
|
||||||
username_cmd = "cat ${config.sops.secrets.spotify_user.path}"
|
username_cmd = "cat ${config.sops.secrets.spotify_user.path}"
|
||||||
password_cmd = "cat ${config.sops.secrets.spotify_pass.path}"
|
password_cmd = "cat ${config.sops.secrets.spotify_pass.path}"
|
||||||
backend = "alsa" # use portaudio for macOS [homebrew]
|
backend = "alsa" # use portaudio for macOS [homebrew]
|
||||||
# The alsa audio device to stream audio to. To get a
|
# The alsa audio device to stream audio to. To get a
|
||||||
# list of valid devices, run `aplay -L`,
|
# list of valid devices, run `aplay -L`,
|
||||||
#device = "alsa_audio_device" # omit for macOS
|
#device = "alsa_audio_device" # omit for macOS
|
||||||
# The alsa mixer used by `spotifyd`.
|
# The alsa mixer used by `spotifyd`.
|
||||||
mixer = "PCM" # omit for macOS
|
mixer = "PCM" # omit for macOS
|
||||||
|
|
||||||
# A script that gets evaluated in the user's shell when the song changes [aliases: onevent]
|
# A script that gets evaluated in the user's shell when the song changes [aliases: onevent]
|
||||||
on-song-change-hook = "${pkgs.mpc_cli}/bin/mpc --host localhost --port 6600 stop"
|
on-song-change-hook = "${pkgs.mpc_cli}/bin/mpc --host localhost --port 6600 stop"
|
||||||
|
|
||||||
# The volume controller. Each one behaves different to
|
# The volume controller. Each one behaves different to
|
||||||
# volume increases. For possible values, run
|
# volume increases. For possible values, run
|
||||||
# `spotifyd --help`.
|
# `spotifyd --help`.
|
||||||
volume_controller = "alsa" # use softvol for macOS
|
volume_controller = "alsa" # use softvol for macOS
|
||||||
|
|
||||||
# The name that gets displayed under the connect tab on
|
# The name that gets displayed under the connect tab on
|
||||||
# official clients. Spaces are not allowed!
|
# official clients. Spaces are not allowed!
|
||||||
device_name = "DJane"
|
device_name = "DJane"
|
||||||
|
|
||||||
# The audio bitrate. 96, 160 or 320 kbit/s
|
# The audio bitrate. 96, 160 or 320 kbit/s
|
||||||
bitrate = 320
|
bitrate = 320
|
||||||
|
|
||||||
# The directory used to cache audio data. This setting can save
|
# The directory used to cache audio data. This setting can save
|
||||||
# a lot of bandwidth when activated, as it will avoid re-downloading
|
# a lot of bandwidth when activated, as it will avoid re-downloading
|
||||||
# audio files when replaying them.
|
# audio files when replaying them.
|
||||||
#
|
#
|
||||||
# Note: The file path does not get expanded. Environment variables and
|
# Note: The file path does not get expanded. Environment variables and
|
||||||
# shell placeholders like $HOME or ~ don't work!
|
# shell placeholders like $HOME or ~ don't work!
|
||||||
#cache_path = "cache_directory"
|
#cache_path = "cache_directory"
|
||||||
|
|
||||||
# If set to true, audio data does NOT get cached.
|
# If set to true, audio data does NOT get cached.
|
||||||
no_audio_cache = true
|
no_audio_cache = true
|
||||||
|
|
||||||
# Volume on startup between 0 and 100
|
# Volume on startup between 0 and 100
|
||||||
# NOTE: This variable's type will change in v0.4, to a number (instead of string)
|
# NOTE: This variable's type will change in v0.4, to a number (instead of string)
|
||||||
initial_volume = "90"
|
initial_volume = "90"
|
||||||
|
|
||||||
# If set to true, enables volume normalisation between songs.
|
# If set to true, enables volume normalisation between songs.
|
||||||
volume_normalisation = false
|
volume_normalisation = false
|
||||||
|
|
||||||
# The normalisation pregain that is applied for each song.
|
# The normalisation pregain that is applied for each song.
|
||||||
# normalisation_pregain = -10
|
# normalisation_pregain = -10
|
||||||
|
|
||||||
# The port `spotifyd` uses to announce its service over the network.
|
# The port `spotifyd` uses to announce its service over the network.
|
||||||
zeroconf_port = 1234
|
zeroconf_port = 1234
|
||||||
|
|
||||||
# The proxy `spotifyd` will use to connect to spotify.
|
# The proxy `spotifyd` will use to connect to spotify.
|
||||||
#proxy = "http://proxy.example.org:8080"
|
#proxy = "http://proxy.example.org:8080"
|
||||||
|
|
||||||
# The displayed device type in Spotify clients.
|
# The displayed device type in Spotify clients.
|
||||||
# Can be unknown, computer, tablet, smartphone, speaker, t_v,
|
# Can be unknown, computer, tablet, smartphone, speaker, t_v,
|
||||||
# a_v_r (Audio/Video Receiver), s_t_b (Set-Top Box), and audio_dongle.
|
# a_v_r (Audio/Video Receiver), s_t_b (Set-Top Box), and audio_dongle.
|
||||||
device_type = "computer"
|
device_type = "computer"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
services.taskwarrior-pushover = {
|
services.taskwarrior-pushover = {
|
||||||
enable = true;
|
enable = true;
|
||||||
recurrence="on";
|
recurrence = "on";
|
||||||
onCalendar = "06:30:00";
|
onCalendar = "06:30:00";
|
||||||
server = "taskd.ingolf-wagner.de:53589";
|
server = "taskd.ingolf-wagner.de:53589";
|
||||||
pushoverApiTokenFile = config.sops.secrets.pushoverApiToken.path;
|
pushoverApiTokenFile = config.sops.secrets.pushoverApiToken.path;
|
||||||
|
@ -19,6 +19,6 @@
|
||||||
caFile = config.sops.secrets.taskwarriorCa.path;
|
caFile = config.sops.secrets.taskwarriorCa.path;
|
||||||
certificateFile = config.sops.secrets.taskwarriorCertificate.path;
|
certificateFile = config.sops.secrets.taskwarriorCertificate.path;
|
||||||
keyFile = config.sops.secrets.taskwarriorKey.path;
|
keyFile = config.sops.secrets.taskwarriorKey.path;
|
||||||
credentials= "1337/palo/ed0fdbe8-2dc3-408b-84cb-d07d363bccd2";
|
credentials = "1337/palo/ed0fdbe8-2dc3-408b-84cb-d07d363bccd2";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@ let
|
||||||
ssid = "palosiot";
|
ssid = "palosiot";
|
||||||
wifiPassword = lib.fileContents <secrets/iot_wifi>;
|
wifiPassword = lib.fileContents <secrets/iot_wifi>;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
# todo only open needed ports
|
# todo only open needed ports
|
||||||
networking.firewall.trustedInterfaces = [ wifi ];
|
networking.firewall.trustedInterfaces = [ wifi ];
|
||||||
|
|
|
@ -27,26 +27,28 @@
|
||||||
|
|
||||||
# automount
|
# automount
|
||||||
# ---------
|
# ---------
|
||||||
(let mediaUUID = "3d106f56-89e5-400d-9d6b-1dd957919548";
|
(
|
||||||
in {
|
let mediaUUID = "3d106f56-89e5-400d-9d6b-1dd957919548";
|
||||||
fileSystems."/media" = {
|
in {
|
||||||
device = "/dev/disk/by-uuid/${mediaUUID}";
|
fileSystems."/media" = {
|
||||||
fsType = "ext4";
|
device = "/dev/disk/by-uuid/${mediaUUID}";
|
||||||
options = [
|
fsType = "ext4";
|
||||||
"nofail"
|
options = [
|
||||||
"noauto"
|
"nofail"
|
||||||
#"x-systemd.device-timeout=1ms"
|
"noauto"
|
||||||
];
|
#"x-systemd.device-timeout=1ms"
|
||||||
};
|
];
|
||||||
systemd.mounts = [{
|
};
|
||||||
enable = true;
|
systemd.mounts = [{
|
||||||
options = "nofail,noauto";
|
enable = true;
|
||||||
type = "ext4";
|
options = "nofail,noauto";
|
||||||
wantedBy = [ "multi-user.target" ];
|
type = "ext4";
|
||||||
what = "/dev/disk/by-uuid/${mediaUUID}";
|
wantedBy = [ "multi-user.target" ];
|
||||||
where = "/media";
|
what = "/dev/disk/by-uuid/${mediaUUID}";
|
||||||
}];
|
where = "/media";
|
||||||
})
|
}];
|
||||||
|
}
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
# NTFS support
|
# NTFS support
|
||||||
|
|
|
@ -54,7 +54,12 @@
|
||||||
after = [ "media.mount" ];
|
after = [ "media.mount" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
users.groups."syncthing".members = [ mpd" "syncthing" "kodi" "palo" ];
|
users.groups."syncthing".members = [
|
||||||
|
"mpd"
|
||||||
|
"syncthing"
|
||||||
|
"kodi"
|
||||||
|
"palo"
|
||||||
|
];
|
||||||
|
|
||||||
backup.dirs = [ "/var/lib/syncthing/finance" ];
|
backup.dirs = [ "/var/lib/syncthing/finance" ];
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,8 @@ let
|
||||||
ssid = "palosiot";
|
ssid = "palosiot";
|
||||||
wifiPassword = lib.fileContents <secrets/iot_wifi>;
|
wifiPassword = lib.fileContents <secrets/iot_wifi>;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
# todo only open needed ports
|
# todo only open needed ports
|
||||||
networking.firewall.trustedInterfaces = [ wifi ];
|
networking.firewall.trustedInterfaces = [ wifi ];
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,2 @@
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
{
|
{ }
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,8 @@ let
|
||||||
domain = "io.ingolf-wagner.de";
|
domain = "io.ingolf-wagner.de";
|
||||||
publicIp = "195.201.134.247";
|
publicIp = "195.201.134.247";
|
||||||
pw = import <secrets/iodinepw.nix>;
|
pw = import <secrets/iodinepw.nix>;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
services.iodine.server = {
|
services.iodine.server = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
@ -28,7 +28,8 @@ let
|
||||||
root = "${errorPages}/";
|
root = "${errorPages}/";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts =
|
networking.firewall.allowedTCPPorts =
|
||||||
[ 80 443 4443 config.services.taskserver.listenPort ];
|
[ 80 443 4443 config.services.taskserver.listenPort ];
|
||||||
|
@ -117,7 +118,7 @@ in {
|
||||||
} // error.locations;
|
} // error.locations;
|
||||||
};
|
};
|
||||||
|
|
||||||
"grocy.ingolf-wagner.de" = {
|
"grocy.ingolf-wagner.de" = {
|
||||||
listen = [
|
listen = [
|
||||||
{
|
{
|
||||||
addr = "0.0.0.0";
|
addr = "0.0.0.0";
|
||||||
|
@ -439,10 +440,11 @@ in {
|
||||||
|
|
||||||
systemd.services."socat-taskd" = {
|
systemd.services."socat-taskd" = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
script = let port = toString config.services.taskserver.listenPort;
|
script =
|
||||||
in ''
|
let port = toString config.services.taskserver.listenPort;
|
||||||
${pkgs.socat}/bin/socat TCP-LISTEN:${port},fork TCP:workhorse.private:${port}
|
in ''
|
||||||
'';
|
${pkgs.socat}/bin/socat TCP-LISTEN:${port},fork TCP:workhorse.private:${port}
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,8 @@ let
|
||||||
ssid = "bumbumbum";
|
ssid = "bumbumbum";
|
||||||
wifiPassword = lib.fileContents <secrets/wifi-access-point>;
|
wifiPassword = lib.fileContents <secrets/wifi-access-point>;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
# todo only open needed ports
|
# todo only open needed ports
|
||||||
networking.firewall.trustedInterfaces = [ wifi ];
|
networking.firewall.trustedInterfaces = [ wifi ];
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@ let
|
||||||
https://nextcloud.ingolf-wagner.de/remote.php/webdav/${folder}
|
https://nextcloud.ingolf-wagner.de/remote.php/webdav/${folder}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,8 @@ let
|
||||||
ssid = "bumbumbum";
|
ssid = "bumbumbum";
|
||||||
wifiPassword = lib.fileContents <secrets/wifi-access-point>;
|
wifiPassword = lib.fileContents <secrets/wifi-access-point>;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
# todo only open needed ports
|
# todo only open needed ports
|
||||||
networking.firewall.trustedInterfaces = [ wifi ];
|
networking.firewall.trustedInterfaces = [ wifi ];
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,8 @@ let
|
||||||
|
|
||||||
home = "/home/syncthing/podcasts";
|
home = "/home/syncthing/podcasts";
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
custom.services.castget = {
|
custom.services.castget = {
|
||||||
enable = true;
|
enable = true;
|
||||||
user = "root";
|
user = "root";
|
||||||
|
|
|
@ -20,7 +20,8 @@ let
|
||||||
stocks = import ../../private_assets/finance/stocks;
|
stocks = import ../../private_assets/finance/stocks;
|
||||||
stocksFile = toString /home/syncthing/finance/hledger/stocks.journal;
|
stocksFile = toString /home/syncthing/finance/hledger/stocks.journal;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
systemd.services.pull_stocks = {
|
systemd.services.pull_stocks = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -30,18 +31,20 @@ in {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
};
|
};
|
||||||
|
|
||||||
script = let
|
script =
|
||||||
command = { symbol, name, currency, ... }: ''
|
let
|
||||||
APIKEY=${lib.fileContents ../../private_assets/finance/alphavantage/apiKey}
|
command = { symbol, name, currency, ... }: ''
|
||||||
SYMBOL="${symbol}"
|
APIKEY=${lib.fileContents ../../private_assets/finance/alphavantage/apiKey}
|
||||||
${pkgs.curl}/bin/curl --location --silent \
|
SYMBOL="${symbol}"
|
||||||
"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=$SYMBOL&apikey=$APIKEY" \
|
${pkgs.curl}/bin/curl --location --silent \
|
||||||
| ${pkgs.jq}/bin/jq --raw-output '.["Global Quote"]
|
"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=$SYMBOL&apikey=$APIKEY" \
|
||||||
| "P \(.["07. latest trading day"]) ${name} ${currency}\(.["05. price"] | tonumber)"' \
|
| ${pkgs.jq}/bin/jq --raw-output '.["Global Quote"]
|
||||||
>> ${stocksFile}
|
| "P \(.["07. latest trading day"]) ${name} ${currency}\(.["05. price"] | tonumber)"' \
|
||||||
sleep 1
|
>> ${stocksFile}
|
||||||
'';
|
sleep 1
|
||||||
in lib.concatStringsSep "\n" (map command stocks);
|
'';
|
||||||
|
in
|
||||||
|
lib.concatStringsSep "\n" (map command stocks);
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.timers.pull_stocks = {
|
systemd.timers.pull_stocks = {
|
||||||
|
|
|
@ -28,7 +28,8 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
@ -70,47 +70,51 @@ in {
|
||||||
imports = [
|
imports = [
|
||||||
# automount
|
# automount
|
||||||
# ---------
|
# ---------
|
||||||
(let mediaUUID = "b8ba192e-e2aa-47dd-85ec-dcf97ec9310a";
|
(
|
||||||
in {
|
let mediaUUID = "b8ba192e-e2aa-47dd-85ec-dcf97ec9310a";
|
||||||
fileSystems."/media" = {
|
in {
|
||||||
device = "/dev/disk/by-uuid/${mediaUUID}";
|
fileSystems."/media" = {
|
||||||
fsType = "ext4";
|
device = "/dev/disk/by-uuid/${mediaUUID}";
|
||||||
options = [
|
fsType = "ext4";
|
||||||
"nofail"
|
options = [
|
||||||
"noauto"
|
"nofail"
|
||||||
#"x-systemd.device-timeout=1ms"
|
"noauto"
|
||||||
];
|
#"x-systemd.device-timeout=1ms"
|
||||||
};
|
];
|
||||||
systemd.mounts = [{
|
};
|
||||||
enable = true;
|
systemd.mounts = [{
|
||||||
options = "nofail,noauto";
|
enable = true;
|
||||||
type = "ext4";
|
options = "nofail,noauto";
|
||||||
wantedBy = [ "multi-user.target" ];
|
type = "ext4";
|
||||||
what = "/dev/disk/by-uuid/${mediaUUID}";
|
wantedBy = [ "multi-user.target" ];
|
||||||
where = "/media";
|
what = "/dev/disk/by-uuid/${mediaUUID}";
|
||||||
}];
|
where = "/media";
|
||||||
})
|
}];
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
(let backupUUID = "f7fa1c0e-ac9f-4955-b4bd-644c1ddb0d89";
|
(
|
||||||
in {
|
let backupUUID = "f7fa1c0e-ac9f-4955-b4bd-644c1ddb0d89";
|
||||||
fileSystems."/backup" = {
|
in {
|
||||||
device = "/dev/disk/by-uuid/${backupUUID}";
|
fileSystems."/backup" = {
|
||||||
fsType = "ext4";
|
device = "/dev/disk/by-uuid/${backupUUID}";
|
||||||
options = [
|
fsType = "ext4";
|
||||||
"nofail"
|
options = [
|
||||||
"noauto"
|
"nofail"
|
||||||
#"x-systemd.device-timeout=1ms"
|
"noauto"
|
||||||
];
|
#"x-systemd.device-timeout=1ms"
|
||||||
};
|
];
|
||||||
systemd.mounts = [{
|
};
|
||||||
enable = true;
|
systemd.mounts = [{
|
||||||
options = "nofail,noauto";
|
enable = true;
|
||||||
type = "ext4";
|
options = "nofail,noauto";
|
||||||
wantedBy = [ "multi-user.target" ];
|
type = "ext4";
|
||||||
what = "/dev/disk/by-uuid/${backupUUID}";
|
wantedBy = [ "multi-user.target" ];
|
||||||
where = "/backup";
|
what = "/dev/disk/by-uuid/${backupUUID}";
|
||||||
}];
|
where = "/backup";
|
||||||
})
|
}];
|
||||||
|
}
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@ let
|
||||||
sync-repo = library.jenkins.syncJob;
|
sync-repo = library.jenkins.syncJob;
|
||||||
job = library.jenkins.job;
|
job = library.jenkins.job;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.cabal-install ];
|
environment.systemPackages = [ pkgs.cabal-install ];
|
||||||
|
|
||||||
|
@ -62,139 +63,145 @@ in {
|
||||||
accessUser = "admin";
|
accessUser = "admin";
|
||||||
|
|
||||||
# https://docs.openstack.org/infra/jenkins-job-builder/definition.html#modules
|
# https://docs.openstack.org/infra/jenkins-job-builder/definition.html#modules
|
||||||
nixJobs = let
|
nixJobs =
|
||||||
# ssh username + key
|
let
|
||||||
gogs-id = "bc584c99-0fb7-43fb-af75-4076d64c51b2";
|
# ssh username + key
|
||||||
# ssh username + key
|
gogs-id = "bc584c99-0fb7-43fb-af75-4076d64c51b2";
|
||||||
github-id = "bc584c99-0fb7-43fb-af75-4076d64c51b2";
|
# ssh username + key
|
||||||
# ssh username + key
|
github-id = "bc584c99-0fb7-43fb-af75-4076d64c51b2";
|
||||||
sshSputnik = "d91eb57c-5bff-434c-b317-68aad46848d7";
|
# ssh username + key
|
||||||
|
sshSputnik = "d91eb57c-5bff-434c-b317-68aad46848d7";
|
||||||
|
|
||||||
sync-to-github = name: source: target:
|
sync-to-github = name: source: target:
|
||||||
sync-repo name {
|
sync-repo name
|
||||||
url = source;
|
{
|
||||||
credentialsId = gogs-id;
|
url = source;
|
||||||
} {
|
credentialsId = gogs-id;
|
||||||
url = target;
|
}
|
||||||
credentialsId = github-id;
|
{
|
||||||
};
|
url = target;
|
||||||
|
credentialsId = github-id;
|
||||||
|
};
|
||||||
|
|
||||||
in [
|
in
|
||||||
|
[
|
||||||
|
|
||||||
(job "sync-retiolum" {
|
(job "sync-retiolum"
|
||||||
url = "git@github.com:krebs/retiolum.git";
|
{
|
||||||
credentialsId = github-id;
|
url = "git@github.com:krebs/retiolum.git";
|
||||||
triggers = [{ timed = "H/30 * * * *"; }];
|
|
||||||
} [
|
|
||||||
{
|
|
||||||
"Download Files" = [
|
|
||||||
"chmod 755 hosts"
|
|
||||||
"chmod 755 -R hosts"
|
|
||||||
''
|
|
||||||
nix-shell -p curl -p gnutar -p bzip2 --run "curl https://lassul.us/retiolum-hosts.tar.bz2 | tar xvjf - || true"''
|
|
||||||
"chmod 755 -R etc.hosts"
|
|
||||||
''
|
|
||||||
nix-shell -p curl --run "curl https://lassul.us/retiolum.hosts > etc.hosts || true"''
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
"update repo" = [
|
|
||||||
''nix-shell -p git --run "git add ."''
|
|
||||||
''
|
|
||||||
nix-shell -p git --run "git -c user.name=\'Ingolf Wagner\' -c user.email=\'contact@ingolf-wagner.de\' commit -m update-`date +%Y-%m-%dT%H:%M:%S` || exit 0"''
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Push = [{
|
|
||||||
script = ''nix-shell -p git --run "git push origin master"'';
|
|
||||||
credentialsId = github-id;
|
credentialsId = github-id;
|
||||||
}];
|
triggers = [{ timed = "H/30 * * * *"; }];
|
||||||
}
|
} [
|
||||||
])
|
{
|
||||||
|
"Download Files" = [
|
||||||
|
"chmod 755 hosts"
|
||||||
|
"chmod 755 -R hosts"
|
||||||
|
''
|
||||||
|
nix-shell -p curl -p gnutar -p bzip2 --run "curl https://lassul.us/retiolum-hosts.tar.bz2 | tar xvjf - || true"''
|
||||||
|
"chmod 755 -R etc.hosts"
|
||||||
|
''
|
||||||
|
nix-shell -p curl --run "curl https://lassul.us/retiolum.hosts > etc.hosts || true"''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"update repo" = [
|
||||||
|
''nix-shell -p git --run "git add ."''
|
||||||
|
''
|
||||||
|
nix-shell -p git --run "git -c user.name=\'Ingolf Wagner\' -c user.email=\'contact@ingolf-wagner.de\' commit -m update-`date +%Y-%m-%dT%H:%M:%S` || exit 0"''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Push = [{
|
||||||
|
script = ''nix-shell -p git --run "git push origin master"'';
|
||||||
|
credentialsId = github-id;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
(job "test-taskninja" {
|
(job "test-taskninja"
|
||||||
url = "ssh://gogs@workhorse.private:2222/palo/taskninja.git";
|
{
|
||||||
credentialsId = gogs-id;
|
url = "ssh://gogs@workhorse.private:2222/palo/taskninja.git";
|
||||||
} [
|
credentialsId = gogs-id;
|
||||||
{
|
} [
|
||||||
"Create Shell" = [
|
{
|
||||||
''
|
"Create Shell" = [
|
||||||
nix-shell -p cabal2nix --run "cabal2nix --shell file://. > jenkins.nix"''
|
''
|
||||||
];
|
nix-shell -p cabal2nix --run "cabal2nix --shell file://. > jenkins.nix"''
|
||||||
}
|
];
|
||||||
{ Update = [ ''nix-shell ./jenkins.nix --run "cabal update"'' ]; }
|
}
|
||||||
{
|
{ Update = [ ''nix-shell ./jenkins.nix --run "cabal update"'' ]; }
|
||||||
Configure = [
|
{
|
||||||
''nix-shell ./jenkins.nix --run "cabal configure --enable-tests"''
|
Configure = [
|
||||||
''
|
''nix-shell ./jenkins.nix --run "cabal configure --enable-tests"''
|
||||||
nix-shell ./jenkins.nix --run "cabal install --only-dependencies"''
|
''
|
||||||
];
|
nix-shell ./jenkins.nix --run "cabal install --only-dependencies"''
|
||||||
}
|
];
|
||||||
{ Build = [ ''nix-shell ./jenkins.nix --run "cabal build"'' ]; }
|
}
|
||||||
{ Test = [ ''nix-shell ./jenkins.nix --run "cabal test"'' ]; }
|
{ Build = [ ''nix-shell ./jenkins.nix --run "cabal build"'' ]; }
|
||||||
])
|
{ Test = [ ''nix-shell ./jenkins.nix --run "cabal test"'' ]; }
|
||||||
|
])
|
||||||
|
|
||||||
# sync to github
|
# sync to github
|
||||||
# --------------
|
# --------------
|
||||||
(sync-to-github "sync-radiodj"
|
(sync-to-github "sync-radiodj"
|
||||||
"ssh://gogs@workhorse.private:2222/crashburn_radio/radio-dj2.git"
|
"ssh://gogs@workhorse.private:2222/crashburn_radio/radio-dj2.git"
|
||||||
"git@github.com:crashburn-radio/radio-dj.git")
|
"git@github.com:crashburn-radio/radio-dj.git")
|
||||||
(sync-to-github "sync-radiodj-tracks"
|
(sync-to-github "sync-radiodj-tracks"
|
||||||
"ssh://gogs@workhorse.private:2222/crashburn_radio/radio-dj-tracks.git"
|
"ssh://gogs@workhorse.private:2222/crashburn_radio/radio-dj-tracks.git"
|
||||||
"git@github.com:crashburn-radio/radio-dj-tracks.git")
|
"git@github.com:crashburn-radio/radio-dj-tracks.git")
|
||||||
|
|
||||||
(sync-to-github "sync-krops-module"
|
(sync-to-github "sync-krops-module"
|
||||||
"ssh://gogs@workhorse.private:2222/nix-modules/krops.git"
|
"ssh://gogs@workhorse.private:2222/nix-modules/krops.git"
|
||||||
"git@github.com:mrVanDalo/module.krops.git")
|
"git@github.com:mrVanDalo/module.krops.git")
|
||||||
|
|
||||||
(sync-to-github "sync-cluster-module"
|
(sync-to-github "sync-cluster-module"
|
||||||
"ssh://gogs@workhorse.private:2222/nix-modules/cluster.git"
|
"ssh://gogs@workhorse.private:2222/nix-modules/cluster.git"
|
||||||
"git@github.com:mrVanDalo/module.cluster.git")
|
"git@github.com:mrVanDalo/module.cluster.git")
|
||||||
|
|
||||||
(sync-to-github "sync-backup-module"
|
(sync-to-github "sync-backup-module"
|
||||||
"ssh://gogs@workhorse.private:2222/nix-modules/backup.git"
|
"ssh://gogs@workhorse.private:2222/nix-modules/backup.git"
|
||||||
"git@github.com:mrVanDalo/module.backup.git")
|
"git@github.com:mrVanDalo/module.backup.git")
|
||||||
|
|
||||||
(sync-to-github "sync-module-tinc"
|
(sync-to-github "sync-module-tinc"
|
||||||
"ssh://gogs@workhorse.private:2222/palo/nixos-tinc.git"
|
"ssh://gogs@workhorse.private:2222/palo/nixos-tinc.git"
|
||||||
"git@github.com:mrVanDalo/nixos-tinc.git")
|
"git@github.com:mrVanDalo/nixos-tinc.git")
|
||||||
|
|
||||||
(sync-to-github "sync-memo"
|
(sync-to-github "sync-memo"
|
||||||
"ssh://gogs@workhorse.private:2222/palo/memo.git"
|
"ssh://gogs@workhorse.private:2222/palo/memo.git"
|
||||||
"git@github.com:mrVanDalo/memo.git")
|
"git@github.com:mrVanDalo/memo.git")
|
||||||
|
|
||||||
(sync-to-github "sync-diagrams-template"
|
(sync-to-github "sync-diagrams-template"
|
||||||
"ssh://gogs@workhorse.private:2222/palo/diagrams-template.git"
|
"ssh://gogs@workhorse.private:2222/palo/diagrams-template.git"
|
||||||
"git@github.com:mrVanDalo/diagrams.git")
|
"git@github.com:mrVanDalo/diagrams.git")
|
||||||
|
|
||||||
(sync-to-github "sync-plops"
|
(sync-to-github "sync-plops"
|
||||||
"ssh://gogs@workhorse.private:2222/palo/plops.git"
|
"ssh://gogs@workhorse.private:2222/palo/plops.git"
|
||||||
"git@github.com:mrVanDalo/plops.git")
|
"git@github.com:mrVanDalo/plops.git")
|
||||||
|
|
||||||
(sync-to-github "sync-image-generator"
|
(sync-to-github "sync-image-generator"
|
||||||
"ssh://gogs@workhorse.private:2222/palo/image-generator2.git"
|
"ssh://gogs@workhorse.private:2222/palo/image-generator2.git"
|
||||||
"git@github.com:mrVanDalo/image-generator.git")
|
"git@github.com:mrVanDalo/image-generator.git")
|
||||||
|
|
||||||
(sync-to-github "sync-image-generator-lib"
|
(sync-to-github "sync-image-generator-lib"
|
||||||
"ssh://gogs@workhorse.private:2222/palo/image-generator-lib.git"
|
"ssh://gogs@workhorse.private:2222/palo/image-generator-lib.git"
|
||||||
"git@github.com:mrVanDalo/image-generator-examples.git")
|
"git@github.com:mrVanDalo/image-generator-examples.git")
|
||||||
|
|
||||||
(sync-to-github "sync-tech.ingolf-wagner.de"
|
(sync-to-github "sync-tech.ingolf-wagner.de"
|
||||||
"ssh://gogs@workhorse.private:2222/palo/tech.ingolf-wagner.de.git"
|
"ssh://gogs@workhorse.private:2222/palo/tech.ingolf-wagner.de.git"
|
||||||
"git@github.com:mrVanDalo/tech.ingolf-wagner.de.git")
|
"git@github.com:mrVanDalo/tech.ingolf-wagner.de.git")
|
||||||
|
|
||||||
(sync-to-github "sync-LineageOS-build"
|
(sync-to-github "sync-LineageOS-build"
|
||||||
"ssh://gogs@git.ingolf-wagner.de:443/palo/LineagoOS-build.git"
|
"ssh://gogs@git.ingolf-wagner.de:443/palo/LineagoOS-build.git"
|
||||||
"git@github.com:mrVanDalo/LineagoOS-build.git")
|
"git@github.com:mrVanDalo/LineagoOS-build.git")
|
||||||
|
|
||||||
(sync-to-github "sync-http-errors"
|
(sync-to-github "sync-http-errors"
|
||||||
"ssh://gogs@git.ingolf-wagner.de:443/palo/http-errors.git"
|
"ssh://gogs@git.ingolf-wagner.de:443/palo/http-errors.git"
|
||||||
"git@github.com:mrVanDalo/http-errors.git")
|
"git@github.com:mrVanDalo/http-errors.git")
|
||||||
(sync-to-github "sync-light-control"
|
(sync-to-github "sync-light-control"
|
||||||
"ssh://gogs@git.ingolf-wagner.de:443/palo/light-control.git"
|
"ssh://gogs@git.ingolf-wagner.de:443/palo/light-control.git"
|
||||||
"git@github.com:mrVanDalo/light-control.git")
|
"git@github.com:mrVanDalo/light-control.git")
|
||||||
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,37 +9,39 @@
|
||||||
#NOTE: you need to keep the single quote inside nix string.
|
#NOTE: you need to keep the single quote inside nix string.
|
||||||
password = "'sha1:1b961dc713fb:88483270a63e57d18d43cf337e629539de1436ba'";
|
password = "'sha1:1b961dc713fb:88483270a63e57d18d43cf337e629539de1436ba'";
|
||||||
kernels = {
|
kernels = {
|
||||||
python3 = let
|
python3 =
|
||||||
env = (pkgs.python3.withPackages (pythonPackages:
|
let
|
||||||
with pythonPackages; [
|
env = (pkgs.python3.withPackages (pythonPackages:
|
||||||
ipykernel
|
with pythonPackages; [
|
||||||
pandas
|
ipykernel
|
||||||
|
pandas
|
||||||
|
|
||||||
# database stuff
|
# database stuff
|
||||||
mysqlclient
|
mysqlclient
|
||||||
databases
|
databases
|
||||||
asyncpg
|
asyncpg
|
||||||
psycopg2
|
psycopg2
|
||||||
aiomysql
|
aiomysql
|
||||||
pymysql
|
pymysql
|
||||||
aiosqlite
|
aiosqlite
|
||||||
#aiopg
|
#aiopg
|
||||||
sqlalchemy
|
sqlalchemy
|
||||||
|
|
||||||
# pdf export
|
# pdf export
|
||||||
nbconvert
|
nbconvert
|
||||||
]));
|
]));
|
||||||
in {
|
in
|
||||||
displayName = "Python 3";
|
{
|
||||||
argv = [
|
displayName = "Python 3";
|
||||||
"${env.interpreter}"
|
argv = [
|
||||||
"-m"
|
"${env.interpreter}"
|
||||||
"ipykernel_launcher"
|
"-m"
|
||||||
"-f"
|
"ipykernel_launcher"
|
||||||
"{connection_file}"
|
"-f"
|
||||||
];
|
"{connection_file}"
|
||||||
language = "python";
|
];
|
||||||
};
|
language = "python";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -364,55 +364,60 @@ let
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
notmuchTagging = let
|
notmuchTagging =
|
||||||
|
let
|
||||||
|
|
||||||
template = index:
|
template = index:
|
||||||
{ tags, query, message ? "generic", ... }:
|
{ tags, query, message ? "generic", ... }:
|
||||||
let
|
let
|
||||||
command = ''
|
command = ''
|
||||||
${pkgs.notmuch}/bin/notmuch tag ${
|
${pkgs.notmuch}/bin/notmuch tag ${lib.concatStringsSep " " tags} -- "${query}"
|
||||||
lib.concatStringsSep " " tags
|
'';
|
||||||
} -- "${query}"
|
in
|
||||||
|
''
|
||||||
|
echo '${command}'
|
||||||
|
${command}
|
||||||
'';
|
'';
|
||||||
in ''
|
junk_template = index: query:
|
||||||
echo '${command}'
|
template index {
|
||||||
${command}
|
tags = [ "+junk" "-unread" "-inbox" ];
|
||||||
'';
|
query = query;
|
||||||
junk_template = index: query:
|
message = "generic junk filter";
|
||||||
template index {
|
};
|
||||||
tags = [ "+junk" "-unread" "-inbox" ];
|
|
||||||
query = query;
|
|
||||||
message = "generic junk filter";
|
|
||||||
};
|
|
||||||
|
|
||||||
in pkgs.writers.writeBash "notmuch-tagging" (lib.concatStringsSep "\n"
|
in
|
||||||
((lib.imap0 junk_template junk_filter) ++ (lib.imap0 template filters)));
|
pkgs.writers.writeBash "notmuch-tagging" (lib.concatStringsSep "\n"
|
||||||
|
((lib.imap0 junk_template junk_filter) ++ (lib.imap0 template filters)));
|
||||||
|
|
||||||
notmuchTaggingNew = let
|
notmuchTaggingNew =
|
||||||
|
let
|
||||||
|
|
||||||
template = index:
|
template = index:
|
||||||
{ tags, query, message ? "generic", ... }:
|
{ tags, query, message ? "generic", ... }:
|
||||||
let
|
let
|
||||||
command = ''
|
command = ''
|
||||||
${pkgs.notmuch}/bin/notmuch tag ${
|
${pkgs.notmuch}/bin/notmuch tag ${
|
||||||
lib.concatStringsSep " " tags
|
lib.concatStringsSep " " tags
|
||||||
} -- "${query} AND tag:new"
|
} -- "${query} AND tag:new"
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
''
|
||||||
|
echo '${command}'
|
||||||
|
${command}
|
||||||
'';
|
'';
|
||||||
in ''
|
|
||||||
echo '${command}'
|
|
||||||
${command}
|
|
||||||
'';
|
|
||||||
|
|
||||||
junk_template = index: query:
|
junk_template = index: query:
|
||||||
template index {
|
template index {
|
||||||
tags = [ "+junk" "-unread" "-inbox" ];
|
tags = [ "+junk" "-unread" "-inbox" ];
|
||||||
query = query;
|
query = query;
|
||||||
message = "generic junk filter";
|
message = "generic junk filter";
|
||||||
};
|
};
|
||||||
in pkgs.writers.writeBash "notmuch-tagging-new" (lib.concatStringsSep "\n"
|
in
|
||||||
((lib.imap0 junk_template junk_filter) ++ (lib.imap0 template filters)));
|
pkgs.writers.writeBash "notmuch-tagging-new" (lib.concatStringsSep "\n"
|
||||||
|
((lib.imap0 junk_template junk_filter) ++ (lib.imap0 template filters)));
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
backup.dirs = [ "/home/mailfetcher" ];
|
backup.dirs = [ "/home/mailfetcher" ];
|
||||||
|
|
||||||
|
@ -431,12 +436,30 @@ in {
|
||||||
name = "mailfetcher";
|
name = "mailfetcher";
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets.mail_terranix.owner = "mailUser";
|
sops.secrets.mail_terranix = {
|
||||||
sops.secrets.mail_gmail.owner = "mailUser";
|
owner = config.users.users.mailUser.name;
|
||||||
sops.secrets.mail_gmx_palo.owner = "mailUser";
|
group = config.users.users.mailUser.group;
|
||||||
sops.secrets.mail_gmx_ingolf.owner = "mailUser";
|
};
|
||||||
sops.secrets.mail_web.owner = "mailUser";
|
sops.secrets.mail_gmail = {
|
||||||
sops.secrets.mail_siteground.owner = "mailUser";
|
owner = config.users.users.mailUser.name;
|
||||||
|
group = config.users.users.mailUser.group;
|
||||||
|
};
|
||||||
|
sops.secrets.mail_gmx_palo = {
|
||||||
|
owner = config.users.users.mailUser.name;
|
||||||
|
group = config.users.users.mailUser.group;
|
||||||
|
};
|
||||||
|
sops.secrets.mail_gmx_ingolf = {
|
||||||
|
owner = config.users.users.mailUser.name;
|
||||||
|
group = config.users.users.mailUser.group;
|
||||||
|
};
|
||||||
|
sops.secrets.mail_web = {
|
||||||
|
owner = config.users.users.mailUser.name;
|
||||||
|
group = config.users.users.mailUser.group;
|
||||||
|
};
|
||||||
|
sops.secrets.mail_siteground = {
|
||||||
|
owner = config.users.users.mailUser.name;
|
||||||
|
group = config.users.users.mailUser.group;
|
||||||
|
};
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.muchsync ];
|
environment.systemPackages = [ pkgs.muchsync ];
|
||||||
|
|
||||||
|
@ -595,34 +618,32 @@ in {
|
||||||
systemd.services.fetchmail =
|
systemd.services.fetchmail =
|
||||||
let
|
let
|
||||||
threadTag = tag: ''
|
threadTag = tag: ''
|
||||||
echo "tag threads with ${tag}"
|
echo "tag threads with ${tag}"
|
||||||
${pkgs.notmuch}/bin/notmuch tag +${tag} $(${pkgs.notmuch}/bin/notmuch search --output=threads tag:${tag})
|
${pkgs.notmuch}/bin/notmuch tag +${tag} $(${pkgs.notmuch}/bin/notmuch search --output=threads tag:${tag})
|
||||||
'';
|
'';
|
||||||
in {
|
in
|
||||||
enable = true;
|
{
|
||||||
serviceConfig = { User = config.users.users.mailUser.name; };
|
enable = true;
|
||||||
environment.NOTMUCH_CONFIG =
|
serviceConfig = { User = config.users.users.mailUser.name; };
|
||||||
"${config.users.users.mailUser.home}/.config/notmuch/notmuchrc";
|
environment.NOTMUCH_CONFIG =
|
||||||
script = ''
|
"${config.users.users.mailUser.home}/.config/notmuch/notmuchrc";
|
||||||
echo "run mbsync"
|
script = ''
|
||||||
${pkgs.isync}/bin/mbsync \
|
echo "run mbsync"
|
||||||
--all
|
${pkgs.isync}/bin/mbsync \
|
||||||
|
--all
|
||||||
|
echo "run getmail"
|
||||||
|
${pkgs.getmail}/bin/getmail \
|
||||||
|
--quiet \
|
||||||
|
--rcfile getmailingolf-wagner-de
|
||||||
|
|
||||||
echo "run getmail"
|
echo "run notmuch"
|
||||||
${pkgs.getmail}/bin/getmail \
|
${pkgs.notmuch}/bin/notmuch new
|
||||||
--quiet \
|
${notmuchTaggingNew}
|
||||||
--rcfile getmailingolf-wagner-de
|
${threadTag "muted"}
|
||||||
|
${threadTag "wohnung"}
|
||||||
echo "run notmuch"
|
${threadTag "flagged"}
|
||||||
${pkgs.notmuch}/bin/notmuch new
|
'';
|
||||||
${notmuchTaggingNew}
|
};
|
||||||
${threadTag "muted"}
|
|
||||||
${threadTag "wohnung"}
|
|
||||||
${threadTag "flagged"}
|
|
||||||
echo "delete threads"
|
|
||||||
${pkgs.notmuch}/bin/notmuch tag +deleted $(${pkgs.notmuch}/bin/notmuch search --output=threads tag:deleted)
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
systemd.timers.fetchmail = {
|
systemd.timers.fetchmail = {
|
||||||
enable = true;
|
enable = true;
|
||||||
# timerConfig.OnCalendar = " *-*-* *:00:00";
|
# timerConfig.OnCalendar = " *-*-* *:00:00";
|
||||||
|
@ -635,9 +656,5 @@ in {
|
||||||
enable = true;
|
enable = true;
|
||||||
new.tags = [ "unread" "inbox" "new" ];
|
new.tags = [ "unread" "inbox" "new" ];
|
||||||
};
|
};
|
||||||
#home-manager.users.mailUser.home.file."notmuch" = {
|
|
||||||
# source = "${config.users.users.mailUser.home}/.config/notmuch/notmuchrc";
|
|
||||||
# target = ".notmuch-config";
|
|
||||||
#};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@ let
|
||||||
rig = config.networking.hostName;
|
rig = config.networking.hostName;
|
||||||
recheckInterval = 2000;
|
recheckInterval = 2000;
|
||||||
package = pkgs.ethminer;
|
package = pkgs.ethminer;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
systemd.services.ethminer = {
|
systemd.services.ethminer = {
|
||||||
description = "ethminer ethereum mining service";
|
description = "ethminer ethereum mining service";
|
||||||
|
|
|
@ -4,11 +4,22 @@ let
|
||||||
hostAddress = "192.168.100.10";
|
hostAddress = "192.168.100.10";
|
||||||
containerAddress = "192.168.100.11";
|
containerAddress = "192.168.100.11";
|
||||||
#syncthingGid = config.users.groups.syncthing.gid;
|
#syncthingGid = config.users.groups.syncthing.gid;
|
||||||
|
nextcloudUid = 1000;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
sops.secrets.nextcloud_database_password = {};
|
sops.secrets.nextcloud_database_password = {
|
||||||
sops.secrets.nextcloud_root_password = {};
|
owner = "nextcloud";
|
||||||
|
};
|
||||||
|
sops.secrets.nextcloud_root_password = {
|
||||||
|
owner = "nextcloud";
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.nextcloud = {
|
||||||
|
isSystemUser = true;
|
||||||
|
uid = nextcloudUid;
|
||||||
|
};
|
||||||
|
|
||||||
containers.nextcloud = {
|
containers.nextcloud = {
|
||||||
|
|
||||||
|
@ -16,20 +27,20 @@ in {
|
||||||
bindMounts = {
|
bindMounts = {
|
||||||
rootpassword = {
|
rootpassword = {
|
||||||
hostPath =
|
hostPath =
|
||||||
"/run/secrets/nextcloud_root_password";
|
"/run/secrets/nextcloud_root_password";
|
||||||
#toString <secrets/nextcloud/root_password>;
|
#toString <secrets/nextcloud/root_password>;
|
||||||
mountPoint =
|
mountPoint =
|
||||||
"/run/secrets/nextcloud_root_password";
|
"/run/secrets/nextcloud_root_password";
|
||||||
#toString <secrets/nextcloud/root_password>;
|
#toString <secrets/nextcloud/root_password>;
|
||||||
isReadOnly = true;
|
isReadOnly = true;
|
||||||
};
|
};
|
||||||
databasepassword = {
|
databasepassword = {
|
||||||
hostPath =
|
hostPath =
|
||||||
"/run/secrets/nextcloud_database_password";
|
"/run/secrets/nextcloud_database_password";
|
||||||
#toString <secrets/nextcloud/database_password>;
|
#toString <secrets/nextcloud/database_password>;
|
||||||
mountPoint =
|
mountPoint =
|
||||||
"/run/secrets/nextcloud_database_password";
|
"/run/secrets/nextcloud_database_password";
|
||||||
#toString <secrets/nextcloud/database_password>;
|
#toString <secrets/nextcloud/database_password>;
|
||||||
isReadOnly = true;
|
isReadOnly = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,6 +96,8 @@ in {
|
||||||
|
|
||||||
config = { config, pkgs, lib, ... }: {
|
config = { config, pkgs, lib, ... }: {
|
||||||
|
|
||||||
|
users.users.nextcloud.uid = nextcloudUid;
|
||||||
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
# Use recommended settings
|
# Use recommended settings
|
||||||
recommendedGzipSettings = lib.mkDefault true;
|
recommendedGzipSettings = lib.mkDefault true;
|
||||||
|
@ -93,28 +106,30 @@ in {
|
||||||
recommendedTlsSettings = lib.mkDefault true;
|
recommendedTlsSettings = lib.mkDefault true;
|
||||||
|
|
||||||
# for graylog logging
|
# for graylog logging
|
||||||
commonHttpConfig = let
|
commonHttpConfig =
|
||||||
access_log_sink = "${hostAddress}:12304";
|
let
|
||||||
error_log_sink = "${hostAddress}:12305";
|
access_log_sink = "${hostAddress}:12304";
|
||||||
in ''
|
error_log_sink = "${hostAddress}:12305";
|
||||||
log_format graylog2_json escape=json '{ "timestamp": "$time_iso8601", '
|
in
|
||||||
'"facility": "nginx", '
|
''
|
||||||
'"src_addr": "$remote_addr", '
|
log_format graylog2_json escape=json '{ "timestamp": "$time_iso8601", '
|
||||||
'"body_bytes_sent": $body_bytes_sent, '
|
'"facility": "nginx", '
|
||||||
'"request_time": $request_time, '
|
'"src_addr": "$remote_addr", '
|
||||||
'"response_status": $status, '
|
'"body_bytes_sent": $body_bytes_sent, '
|
||||||
'"request": "$request", '
|
'"request_time": $request_time, '
|
||||||
'"request_method": "$request_method", '
|
'"response_status": $status, '
|
||||||
'"host": "$host",'
|
'"request": "$request", '
|
||||||
'"upstream_cache_status": "$upstream_cache_status",'
|
'"request_method": "$request_method", '
|
||||||
'"upstream_addr": "$upstream_addr",'
|
'"host": "$host",'
|
||||||
'"http_x_forwarded_for": "$http_x_forwarded_for",'
|
'"upstream_cache_status": "$upstream_cache_status",'
|
||||||
'"http_referrer": "$http_referer", '
|
'"upstream_addr": "$upstream_addr",'
|
||||||
'"http_user_agent": "$http_user_agent" }';
|
'"http_x_forwarded_for": "$http_x_forwarded_for",'
|
||||||
|
'"http_referrer": "$http_referer", '
|
||||||
|
'"http_user_agent": "$http_user_agent" }';
|
||||||
|
|
||||||
access_log syslog:server=${access_log_sink} graylog2_json;
|
access_log syslog:server=${access_log_sink} graylog2_json;
|
||||||
error_log syslog:server=${error_log_sink};
|
error_log syslog:server=${error_log_sink};
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
# don't forget the database backup before doing this
|
# don't forget the database backup before doing this
|
||||||
|
@ -331,8 +346,8 @@ in {
|
||||||
doInit = true;
|
doInit = true;
|
||||||
encryption = {
|
encryption = {
|
||||||
mode = "repokey-blake2";
|
mode = "repokey-blake2";
|
||||||
passCommand =
|
passCommand =
|
||||||
"cat ${config.sops.secrets.backup_repository_passphrase.path}";
|
"cat ${config.sops.secrets.backup_repository_passphrase.path}";
|
||||||
};
|
};
|
||||||
startAt = "0/3:00:00";
|
startAt = "0/3:00:00";
|
||||||
prune.keep = {
|
prune.keep = {
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
{ pkgs, ... }:
|
{ pkgs, config, ... }:
|
||||||
let
|
let
|
||||||
|
|
||||||
hostAddress = "192.168.100.30";
|
hostAddress = "192.168.100.30";
|
||||||
containerAddress = "192.168.100.31";
|
containerAddress = "192.168.100.31";
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
sops.secrets.nordvpn = {};
|
#users.users.transmission = {
|
||||||
|
# isSystemUser = true;
|
||||||
|
# uid = config.ids.uids.transmission;
|
||||||
|
#};
|
||||||
|
|
||||||
|
sops.secrets.nordvpn = { };
|
||||||
|
|
||||||
containers.torrent = {
|
containers.torrent = {
|
||||||
|
|
||||||
|
@ -185,7 +191,7 @@ in {
|
||||||
|
|
||||||
remote-cert-tls server
|
remote-cert-tls server
|
||||||
|
|
||||||
auth-user-pass /run/secrets/nordvpn.txt
|
auth-user-pass /run/secrets/nordvpn
|
||||||
|
|
||||||
verb 3
|
verb 3
|
||||||
pull
|
pull
|
||||||
|
|
|
@ -5,7 +5,8 @@ let
|
||||||
ipAddress = "10.1.0.1";
|
ipAddress = "10.1.0.1";
|
||||||
prefixLength = 24;
|
prefixLength = 24;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
networking.extraHosts = ''
|
networking.extraHosts = ''
|
||||||
10.1.0.1 workout.lan
|
10.1.0.1 workout.lan
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
nixpkgs.overlays = [ (import <mozilla-overlay/rust-overlay.nix>) ];
|
nixpkgs.overlays = [ (import <mozilla-overlay/rust-overlay.nix>) ];
|
||||||
|
|
||||||
nixpkgs.config.packageOverrides = pkgs: {
|
nixpkgs.config.packageOverrides = pkgs: {
|
||||||
nur = import (builtins.fetchTarball
|
nur = import
|
||||||
"https://github.com/nix-community/NUR/archive/master.tar.gz") {
|
(builtins.fetchTarball
|
||||||
|
"https://github.com/nix-community/NUR/archive/master.tar.gz")
|
||||||
|
{
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
101
nixos/flake.lock
101
nixos/flake.lock
|
@ -199,6 +199,28 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fenix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs-fmt",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1631067971,
|
||||||
|
"narHash": "sha256-z+qlJaCaw/OAoFGdzm0nDKkjRdCwstHzduF74nMn3bY=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"rev": "0771140f0a6a6622c509fb2d6d2c87f0bfda703d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1623875721,
|
"lastModified": 1623875721,
|
||||||
|
@ -215,6 +237,21 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flake-utils_2": {
|
"flake-utils_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1629481132,
|
||||||
|
"narHash": "sha256-JHgasjPR0/J1J3DRm4KxM4zTyAj4IOJY8vIl75v/kPI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "997f7efcb746a9c140ce1f13c72263189225f482",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1631561581,
|
"lastModified": 1631561581,
|
||||||
"narHash": "sha256-3VQMV5zvxaVLvqqUrNz3iJelLw30mIVSfZmAaauM3dA=",
|
"narHash": "sha256-3VQMV5zvxaVLvqqUrNz3iJelLw30mIVSfZmAaauM3dA=",
|
||||||
|
@ -286,6 +323,27 @@
|
||||||
"url": "https://git.ingolf-wagner.de/nix-modules/krops.git"
|
"url": "https://git.ingolf-wagner.de/nix-modules/krops.git"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"naersk": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs-fmt",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1631004250,
|
||||||
|
"narHash": "sha256-LGh0CjAZwh13AVkTi9w9lITEC7x6bwSQyFViOZ6HyNo=",
|
||||||
|
"owner": "nmattia",
|
||||||
|
"repo": "naersk",
|
||||||
|
"rev": "08afb3d1dbfe016108b72e05b02ba0f6ecb3c8e1",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nmattia",
|
||||||
|
"repo": "naersk",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nix-straight": {
|
"nix-straight": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
|
@ -319,6 +377,29 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs-fmt": {
|
||||||
|
"inputs": {
|
||||||
|
"fenix": "fenix",
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"naersk": "naersk",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1631557044,
|
||||||
|
"narHash": "sha256-5VPeqRvNhRxTv07NSvxQSXvtuGnrjWmmwss0PGhFzTI=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs-fmt",
|
||||||
|
"rev": "c7f66ec1b969ed118231fdf7f596c5ed2c2cfe49",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs-fmt",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs-unstable": {
|
"nixpkgs-unstable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1634782485,
|
"lastModified": 1634782485,
|
||||||
|
@ -463,7 +544,7 @@
|
||||||
},
|
},
|
||||||
"polygon-art": {
|
"polygon-art": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils_2",
|
"flake-utils": "flake-utils_3",
|
||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
|
@ -505,6 +586,7 @@
|
||||||
"home-manager-utils": "home-manager-utils",
|
"home-manager-utils": "home-manager-utils",
|
||||||
"krops-lib": "krops-lib",
|
"krops-lib": "krops-lib",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
|
"nixpkgs-fmt": "nixpkgs-fmt",
|
||||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||||
"polygon-art": "polygon-art",
|
"polygon-art": "polygon-art",
|
||||||
"sops-nix": "sops-nix"
|
"sops-nix": "sops-nix"
|
||||||
|
@ -526,6 +608,23 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rust-analyzer-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1630943734,
|
||||||
|
"narHash": "sha256-jqgAKhvrVDEkv8HB56hVIgvMDuuQ7X4D2zE9ATV+baI=",
|
||||||
|
"owner": "rust-analyzer",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"rev": "3dae94bf2b3e496adb049da589c7efef272a39b8",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "rust-analyzer",
|
||||||
|
"ref": "nightly",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"sops-nix": {
|
"sops-nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs_3"
|
"nixpkgs": "nixpkgs_3"
|
||||||
|
|
|
@ -33,11 +33,27 @@
|
||||||
"git+https://git.ingolf-wagner.de/nix-modules/cluster.git?rev=ef621797a30f8a57de16bf33672abdd411cbcece";
|
"git+https://git.ingolf-wagner.de/nix-modules/cluster.git?rev=ef621797a30f8a57de16bf33672abdd411cbcece";
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
nixpkgs-fmt = {
|
||||||
|
url = "github:nix-community/nixpkgs-fmt";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, sops-nix, nixpkgs, home-manager, home-manager-utils
|
outputs =
|
||||||
, doom-emacs-nix, backup-module, nixpkgs-unstable, krops-lib, cluster-module
|
{ self
|
||||||
, polygon-art, ... }:
|
, sops-nix
|
||||||
|
, nixpkgs
|
||||||
|
, home-manager
|
||||||
|
, home-manager-utils
|
||||||
|
, doom-emacs-nix
|
||||||
|
, backup-module
|
||||||
|
, nixpkgs-unstable
|
||||||
|
, krops-lib
|
||||||
|
, cluster-module
|
||||||
|
, polygon-art
|
||||||
|
, nixpkgs-fmt
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
nixosSystem = nixpkgs.lib.nixosSystem;
|
nixosSystem = nixpkgs.lib.nixosSystem;
|
||||||
|
@ -70,13 +86,13 @@
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
desktopModules = [
|
desktopModules = [
|
||||||
home-manager.nixosModules.home-manager
|
|
||||||
{
|
{
|
||||||
home-manager.users.mainUser = {
|
home-manager.users.mainUser = {
|
||||||
imports = [ doom-emacs-nix.hmModule home-manager-utils.hmModule ];
|
imports = [ doom-emacs-nix.hmModule home-manager-utils.hmModule ];
|
||||||
};
|
};
|
||||||
home-manager.useGlobalPkgs = true;
|
environment.systemPackages = [
|
||||||
home-manager.useUserPackages = true;
|
nixpkgs-fmt.defaultPackage."x86_64-linux"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
desktopConfiguration = initPath:
|
desktopConfiguration = initPath:
|
||||||
|
@ -89,7 +105,8 @@
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
modules = defaultModules ++ [ initPath ];
|
modules = defaultModules ++ [ initPath ];
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
nixosConfigurations = {
|
nixosConfigurations = {
|
||||||
sterni = desktopConfiguration ./configs/sterni/configuration.nix;
|
sterni = desktopConfiguration ./configs/sterni/configuration.nix;
|
||||||
sternchen = desktopConfiguration ./configs/sternchien/configuration.nix;
|
sternchen = desktopConfiguration ./configs/sternchien/configuration.nix;
|
||||||
|
|
|
@ -5,8 +5,9 @@ let
|
||||||
command = targetPath:
|
command = targetPath:
|
||||||
let
|
let
|
||||||
commandLine =
|
commandLine =
|
||||||
"TMPDIR=/tmp nixos-rebuild build --flake ${targetPath} -L --keep-going";
|
"TMPDIR=/tmp nixos-rebuild test --flake ${targetPath} -L --keep-going";
|
||||||
in ''
|
in
|
||||||
|
''
|
||||||
echo '${commandLine}'
|
echo '${commandLine}'
|
||||||
nix-shell \
|
nix-shell \
|
||||||
-E "with import <nixpkgs> {}; mkShell { buildInputs = [ git (nixos { nix.package = nixFlakes; }).nixos-rebuild ]; }" \
|
-E "with import <nixpkgs> {}; mkShell { buildInputs = [ git (nixos { nix.package = nixFlakes; }).nixos-rebuild ]; }" \
|
||||||
|
@ -64,7 +65,8 @@ let
|
||||||
target = lib.mkTarget "root@${host}/var/krops";
|
target = lib.mkTarget "root@${host}/var/krops";
|
||||||
inherit command;
|
inherit command;
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
"${name}" = pkgs.writers.writeBashBin name ''
|
"${name}" = pkgs.writers.writeBashBin name ''
|
||||||
echo "deploy system"
|
echo "deploy system"
|
||||||
${system}/bin/system
|
${system}/bin/system
|
||||||
|
@ -89,7 +91,8 @@ let
|
||||||
force = true;
|
force = true;
|
||||||
target = lib.mkTarget "root@${host}/etc/NetworkManager";
|
target = lib.mkTarget "root@${host}/etc/NetworkManager";
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
"${name}" = pkgs.writers.writeBashBin "${name}-all" ''
|
"${name}" = pkgs.writers.writeBashBin "${name}-all" ''
|
||||||
echo "deploy network secerts"
|
echo "deploy network secerts"
|
||||||
${network}/bin/secrets
|
${network}/bin/secrets
|
||||||
|
@ -98,7 +101,8 @@ let
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
in (desktop {
|
in
|
||||||
|
(desktop {
|
||||||
name = "sterni";
|
name = "sterni";
|
||||||
host = "sterni.private";
|
host = "sterni.private";
|
||||||
}) // (desktop {
|
}) // (desktop {
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
{ pkgs, lib, ... }: {
|
{ pkgs, lib, ... }: {
|
||||||
desktopFile = bin:
|
desktopFile = bin:
|
||||||
{ comment ? "No Comment", longName ? "Script"
|
{ comment ? "No Comment"
|
||||||
, command ? "${bin}/bin/${bin.name}", ... }:
|
, longName ? "Script"
|
||||||
|
, command ? "${bin}/bin/${bin.name}"
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
pkgs.writeTextFile {
|
pkgs.writeTextFile {
|
||||||
name = "${bin.name}.desktop";
|
name = "${bin.name}.desktop";
|
||||||
destination = "/share/applications/${bin.name}.desktop";
|
destination = "/share/applications/${bin.name}.desktop";
|
||||||
|
|
|
@ -7,79 +7,90 @@ with builtins;
|
||||||
{
|
{
|
||||||
# source container url and credentialsId
|
# source container url and credentialsId
|
||||||
job = name:
|
job = name:
|
||||||
{ url, credentialsId, branch ? "master",
|
{ url
|
||||||
# https://docs.openstack.org/infra/jenkins-job-builder/triggers.html
|
, credentialsId
|
||||||
triggers ? [{
|
, branch ? "master"
|
||||||
pollscm = {
|
, # https://docs.openstack.org/infra/jenkins-job-builder/triggers.html
|
||||||
cron = "H/30 * * * *";
|
triggers ? [{
|
||||||
ignore-post-commit-hooks = true;
|
pollscm = {
|
||||||
};
|
cron = "H/30 * * * *";
|
||||||
}], ... }:
|
ignore-post-commit-hooks = true;
|
||||||
|
};
|
||||||
|
}]
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
config: {
|
config: {
|
||||||
job = {
|
job = {
|
||||||
inherit name triggers;
|
inherit name triggers;
|
||||||
sandbox = true;
|
sandbox = true;
|
||||||
project-type = "pipeline";
|
project-type = "pipeline";
|
||||||
dsl = let
|
dsl =
|
||||||
stage = elem:
|
let
|
||||||
let
|
stage = elem:
|
||||||
stageName = head (attrNames elem);
|
let
|
||||||
stateScripts = map (stage:
|
stageName = head (attrNames elem);
|
||||||
lib.getAttr (typeOf stage) {
|
stateScripts = map
|
||||||
string = ''
|
(stage:
|
||||||
withEnv(['PATH=/run/current-system/sw/bin/','NIX_PATH=/var/src/']) {
|
lib.getAttr (typeOf stage) {
|
||||||
sh '${toString stage}'
|
string = ''
|
||||||
}'';
|
withEnv(['PATH=/run/current-system/sw/bin/','NIX_PATH=/var/src/']) {
|
||||||
set = let
|
sh '${toString stage}'
|
||||||
script = ''
|
}'';
|
||||||
withEnv(['PATH=/run/current-system/sw/bin/','NIX_PATH=/var/src/']) {
|
set =
|
||||||
sh '${toString stage.script}'
|
let
|
||||||
}
|
script = ''
|
||||||
'';
|
withEnv(['PATH=/run/current-system/sw/bin/','NIX_PATH=/var/src/']) {
|
||||||
in if (stage.credentialsId != null) then ''
|
sh '${toString stage.script}'
|
||||||
sshagent(['${stage.credentialsId}']) { ${script} }
|
}
|
||||||
'' else
|
'';
|
||||||
script;
|
in
|
||||||
}) (getAttr stageName elem);
|
if (stage.credentialsId != null) then ''
|
||||||
in ''
|
sshagent(['${stage.credentialsId}']) { ${script} }
|
||||||
stage('${stageName}') {
|
'' else
|
||||||
steps {
|
script;
|
||||||
${concatStringsSep "\n" stateScripts}
|
})
|
||||||
|
(getAttr stageName elem);
|
||||||
|
in
|
||||||
|
''
|
||||||
|
stage('${stageName}') {
|
||||||
|
steps {
|
||||||
|
${concatStringsSep "\n" stateScripts}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
stages = map stage config;
|
||||||
|
in
|
||||||
|
''
|
||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
post {
|
||||||
|
failure {
|
||||||
|
mattermostSend channel: 'notification', color: '#FF0000', message: "Failed to build : [''${env.JOB_NAME}-''${env.BUILD_NUMBER}](''${env.BUILD_URL})"
|
||||||
|
}
|
||||||
|
success {
|
||||||
|
mattermostSend channel: 'jenkins', color: '#00FF00', message: "Successfully build : [''${env.JOB_NAME}-''${env.BUILD_NUMBER}](''${env.JOB_URL})"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'';
|
stages{
|
||||||
stages = map stage config;
|
stage('Pull') {
|
||||||
in ''
|
steps {
|
||||||
pipeline {
|
checkout(
|
||||||
agent any
|
[$class: 'GitSCM'
|
||||||
post {
|
, branches: [[name: '*/${branch}']]
|
||||||
failure {
|
, doGenerateSubmoduleConfigurations: false
|
||||||
mattermostSend channel: 'notification', color: '#FF0000', message: "Failed to build : [''${env.JOB_NAME}-''${env.BUILD_NUMBER}](''${env.BUILD_URL})"
|
, extensions: [[$class: 'LocalBranch', localBranch: 'master']]
|
||||||
}
|
, submoduleCfg: []
|
||||||
success {
|
, userRemoteConfigs:
|
||||||
mattermostSend channel: 'jenkins', color: '#00FF00', message: "Successfully build : [''${env.JOB_NAME}-''${env.BUILD_NUMBER}](''${env.JOB_URL})"
|
[[ credentialsId: '${credentialsId}'
|
||||||
}
|
, url: '${url}']]
|
||||||
}
|
]
|
||||||
stages{
|
)
|
||||||
stage('Pull') {
|
}
|
||||||
steps {
|
|
||||||
checkout(
|
|
||||||
[$class: 'GitSCM'
|
|
||||||
, branches: [[name: '*/${branch}']]
|
|
||||||
, doGenerateSubmoduleConfigurations: false
|
|
||||||
, extensions: [[$class: 'LocalBranch', localBranch: 'master']]
|
|
||||||
, submoduleCfg: []
|
|
||||||
, userRemoteConfigs:
|
|
||||||
[[ credentialsId: '${credentialsId}'
|
|
||||||
, url: '${url}']]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
${concatStringsSep "\n" stages}
|
||||||
}
|
}
|
||||||
${concatStringsSep "\n" stages}
|
|
||||||
}
|
}
|
||||||
}
|
'';
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -45,92 +45,104 @@ let
|
||||||
backupFile = "${homeBackup}.tar.lzma";
|
backupFile = "${homeBackup}.tar.lzma";
|
||||||
rolloutFile = "${home}.tar.lzma";
|
rolloutFile = "${home}.tar.lzma";
|
||||||
lockFile = "${home}-lock";
|
lockFile = "${home}-lock";
|
||||||
in pkgs.writeShellScriptBin "${name}-clean" # sh
|
in
|
||||||
''
|
pkgs.writeShellScriptBin "${name}-clean" # sh
|
||||||
sudo killall -9 -u ${name}
|
''
|
||||||
sudo rm -f ${lockFile}
|
sudo killall -9 -u ${name}
|
||||||
sudo rm -rf ${home}
|
sudo rm -f ${lockFile}
|
||||||
'';
|
sudo rm -rf ${home}
|
||||||
|
'';
|
||||||
|
|
||||||
createBrowser = name: user: browser: home: homeBackup:
|
createBrowser = name: user: browser: home: homeBackup:
|
||||||
let
|
let
|
||||||
backupFile = "${homeBackup}.tar.lzma";
|
backupFile = "${homeBackup}.tar.lzma";
|
||||||
rolloutFile = "${home}.tar.lzma";
|
rolloutFile = "${home}.tar.lzma";
|
||||||
lockFile = "${home}-lock";
|
lockFile = "${home}-lock";
|
||||||
in pkgs.writeShellScriptBin "${name}" # sh
|
in
|
||||||
''
|
pkgs.writeShellScriptBin "${name}" # sh
|
||||||
# set -x
|
''
|
||||||
if [[ ! -e ${lockFile} ]]
|
# set -x
|
||||||
then
|
if [[ ! -e ${lockFile} ]]
|
||||||
# rollout backup
|
then
|
||||||
if [[ -e ${backupFile} ]]
|
# rollout backup
|
||||||
then
|
if [[ -e ${backupFile} ]]
|
||||||
if [[ ! -d ${home} ]]
|
then
|
||||||
then
|
if [[ ! -d ${home} ]]
|
||||||
# todo : use make user
|
then
|
||||||
sudo mkdir -p ${home}
|
# todo : use make user
|
||||||
sudo chown -R ${user}:users ${home}
|
sudo mkdir -p ${home}
|
||||||
fi
|
sudo chown -R ${user}:users ${home}
|
||||||
cp ${backupFile} ${rolloutFile}
|
fi
|
||||||
sudo -u ${user} ${tarBin} xf ${rolloutFile} --directory ${home}
|
cp ${backupFile} ${rolloutFile}
|
||||||
rm ${rolloutFile}
|
sudo -u ${user} ${tarBin} xf ${rolloutFile} --directory ${home}
|
||||||
touch ${lockFile}
|
rm ${rolloutFile}
|
||||||
fi
|
touch ${lockFile}
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
sudo -u ${user} ${browser}
|
sudo -u ${user} ${browser}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
browserExecutableList = let
|
browserExecutableList =
|
||||||
allBrowser = flip mapAttrsToList cfg.configList (name: config:
|
let
|
||||||
let
|
allBrowser = flip mapAttrsToList cfg.configList (name: config:
|
||||||
browser = if config.browserType == "chrome" then
|
let
|
||||||
''${chromiumBin} "$@"''
|
browser =
|
||||||
else if config.browserType == "google" then
|
if config.browserType == "chrome" then
|
||||||
''${chromeBin} "$@"''
|
''${chromiumBin} "$@"''
|
||||||
else
|
else if config.browserType == "google" then
|
||||||
''${firefoxBin} "$@"'';
|
''${chromeBin} "$@"''
|
||||||
in createBrowser name config.user browser config.home config.homeBackup);
|
else
|
||||||
xclipBrowser = [
|
''${firefoxBin} "$@"'';
|
||||||
(pkgs.writeShellScriptBin "copy-to-xclip" # sh
|
in
|
||||||
''
|
createBrowser name config.user browser config.home config.homeBackup);
|
||||||
echo "$*" | ${pkgs.xclip}/bin/xclip
|
xclipBrowser = [
|
||||||
'')
|
(pkgs.writeShellScriptBin "copy-to-xclip" # sh
|
||||||
];
|
''
|
||||||
in allBrowser ++ xclipBrowser;
|
echo "$*" | ${pkgs.xclip}/bin/xclip
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
in
|
||||||
|
allBrowser ++ xclipBrowser;
|
||||||
|
|
||||||
createBackupScript = name: home: backupHome:
|
createBackupScript = name: home: backupHome:
|
||||||
pkgs.writeShellScriptBin "${name}-backup" # sh
|
pkgs.writeShellScriptBin "${name}-backup" # sh
|
||||||
''
|
''
|
||||||
sudo -u ${name} \
|
sudo -u ${name} \
|
||||||
${tarBin} \
|
${tarBin} \
|
||||||
--exclude=.cache \
|
--exclude=.cache \
|
||||||
--exclude=Downloads \
|
--exclude=Downloads \
|
||||||
--create \
|
--create \
|
||||||
--verbos \
|
--verbos \
|
||||||
--lzma \
|
--lzma \
|
||||||
--file ${home}.tar.lzma \
|
--file ${home}.tar.lzma \
|
||||||
--directory ${home} \
|
--directory ${home} \
|
||||||
.
|
.
|
||||||
|
|
||||||
cp ${home}.tar.lzma ${backupHome}.tar.lzma
|
cp ${home}.tar.lzma ${backupHome}.tar.lzma
|
||||||
'';
|
'';
|
||||||
|
|
||||||
allBackupScripts = let
|
allBackupScripts =
|
||||||
filteredConfigs =
|
let
|
||||||
filterAttrs (name: browserConfig: browserConfig.homeBackup != null)
|
filteredConfigs =
|
||||||
cfg.configList;
|
filterAttrs (name: browserConfig: browserConfig.homeBackup != null)
|
||||||
in mapAttrsToList (name: browserConfig:
|
cfg.configList;
|
||||||
createBackupScript name browserConfig.home browserConfig.homeBackup)
|
in
|
||||||
filteredConfigs;
|
mapAttrsToList
|
||||||
|
(name: browserConfig:
|
||||||
|
createBackupScript name browserConfig.home browserConfig.homeBackup)
|
||||||
|
filteredConfigs;
|
||||||
|
|
||||||
allCleanScripts = let
|
allCleanScripts =
|
||||||
filteredConfigs =
|
let
|
||||||
filterAttrs (name: browserConfig: browserConfig.homeBackup != null)
|
filteredConfigs =
|
||||||
cfg.configList;
|
filterAttrs (name: browserConfig: browserConfig.homeBackup != null)
|
||||||
in mapAttrsToList (name: browserConfig:
|
cfg.configList;
|
||||||
cleanBrowser name name browserConfig.home browserConfig.homeBackup)
|
in
|
||||||
filteredConfigs;
|
mapAttrsToList
|
||||||
|
(name: browserConfig:
|
||||||
|
cleanBrowser name name browserConfig.home browserConfig.homeBackup)
|
||||||
|
filteredConfigs;
|
||||||
|
|
||||||
allKillScripts = mapAttrsToList (name: _: killBrowser name) cfg.configList;
|
allKillScripts = mapAttrsToList (name: _: killBrowser name) cfg.configList;
|
||||||
|
|
||||||
|
@ -153,7 +165,8 @@ let
|
||||||
$BIN "$@"
|
$BIN "$@"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.browser = {
|
options.programs.custom.browser = {
|
||||||
enable = mkEnableOption "enable browsers";
|
enable = mkEnableOption "enable browsers";
|
||||||
|
@ -214,18 +227,22 @@ in {
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
# add sudo rights
|
# add sudo rights
|
||||||
security.sudo.extraConfig = let
|
security.sudo.extraConfig =
|
||||||
extraRules = flip mapAttrsToList cfg.configList (name: values:
|
let
|
||||||
concatStringsSep "" (map (sudoUser: ''
|
extraRules = flip mapAttrsToList cfg.configList (name: values:
|
||||||
# sudo configuration to control browser
|
concatStringsSep "" (map
|
||||||
${sudoUser} ALL=(${values.user}) NOPASSWD: ALL
|
(sudoUser: ''
|
||||||
${sudoUser} ALL=(root) NOPASSWD: /run/current-system/sw/bin/mkdir -p ${values.home}
|
# sudo configuration to control browser
|
||||||
${sudoUser} ALL=(root) NOPASSWD: /run/current-system/sw/bin/chown -R ${values.user}\:users ${values.home}
|
${sudoUser} ALL=(${values.user}) NOPASSWD: ALL
|
||||||
${sudoUser} ALL=(root) NOPASSWD: /run/current-system/sw/bin/killall -9 -u ${name}
|
${sudoUser} ALL=(root) NOPASSWD: /run/current-system/sw/bin/mkdir -p ${values.home}
|
||||||
${sudoUser} ALL=(root) NOPASSWD: /run/current-system/sw/bin/rm -rf ${values.home}
|
${sudoUser} ALL=(root) NOPASSWD: /run/current-system/sw/bin/chown -R ${values.user}\:users ${values.home}
|
||||||
${sudoUser} ALL=(root) NOPASSWD: /run/current-system/sw/bin/rm -f ${values.home}-lock
|
${sudoUser} ALL=(root) NOPASSWD: /run/current-system/sw/bin/killall -9 -u ${name}
|
||||||
'') values.sudoUsers));
|
${sudoUser} ALL=(root) NOPASSWD: /run/current-system/sw/bin/rm -rf ${values.home}
|
||||||
in lib.concatStringsSep "\n" extraRules;
|
${sudoUser} ALL=(root) NOPASSWD: /run/current-system/sw/bin/rm -f ${values.home}-lock
|
||||||
|
'')
|
||||||
|
values.sudoUsers));
|
||||||
|
in
|
||||||
|
lib.concatStringsSep "\n" extraRules;
|
||||||
|
|
||||||
# create users
|
# create users
|
||||||
users.users = flip mapAttrs cfg.configList (name: config: {
|
users.users = flip mapAttrs cfg.configList (name: config: {
|
||||||
|
|
|
@ -19,7 +19,8 @@ let
|
||||||
scriptAxel = citateScript (toString ../../assets/sprueche-axel) "axel";
|
scriptAxel = citateScript (toString ../../assets/sprueche-axel) "axel";
|
||||||
scriptSiw = citateScript (toString ../../assets/sprueche-siw) "siw";
|
scriptSiw = citateScript (toString ../../assets/sprueche-siw) "siw";
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.citate = {
|
options.programs.custom.citate = {
|
||||||
enable = mkEnableOption "enable programs.custom.citate";
|
enable = mkEnableOption "enable programs.custom.citate";
|
||||||
|
|
|
@ -18,7 +18,8 @@ let
|
||||||
|
|
||||||
cfg = config.programs.custom.curlScripts;
|
cfg = config.programs.custom.curlScripts;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.curlScripts.enable =
|
options.programs.custom.curlScripts.enable =
|
||||||
mkEnableOption "enable curl scripts";
|
mkEnableOption "enable curl scripts";
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.programs.custom.easytag;
|
cfg = config.programs.custom.easytag;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.easytag.enable =
|
options.programs.custom.easytag.enable =
|
||||||
mkEnableOption "install easytag with dependencies";
|
mkEnableOption "install easytag with dependencies";
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.programs.custom.elm;
|
cfg = config.programs.custom.elm;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.elm.enable = mkEnableOption "enable elm stack";
|
options.programs.custom.elm.enable = mkEnableOption "enable elm stack";
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,8 @@ let
|
||||||
|
|
||||||
cfg = config.programs.custom.espeak;
|
cfg = config.programs.custom.espeak;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.espeak.enable =
|
options.programs.custom.espeak.enable =
|
||||||
mkEnableOption "enable espeak scripts";
|
mkEnableOption "enable espeak scripts";
|
||||||
|
|
|
@ -5,8 +5,13 @@ let
|
||||||
cfg = config.programs.custom.ffmpeg;
|
cfg = config.programs.custom.ffmpeg;
|
||||||
|
|
||||||
ffmpegTemplate = name:
|
ffmpegTemplate = name:
|
||||||
{ profile, preset, tune ? null, width ? 1280, height ? 720
|
{ profile
|
||||||
, resolution ? "720p" }:
|
, preset
|
||||||
|
, tune ? null
|
||||||
|
, width ? 1280
|
||||||
|
, height ? 720
|
||||||
|
, resolution ? "720p"
|
||||||
|
}:
|
||||||
pkgs.writeShellScriptBin "ffmpeg-${name}" ''
|
pkgs.writeShellScriptBin "ffmpeg-${name}" ''
|
||||||
|
|
||||||
if [ $# -eq 0 ]
|
if [ $# -eq 0 ]
|
||||||
|
@ -99,48 +104,53 @@ let
|
||||||
];
|
];
|
||||||
tunes = [ "film" "animation" "grain" "stillimage" "fastdecode" ];
|
tunes = [ "film" "animation" "grain" "stillimage" "fastdecode" ];
|
||||||
|
|
||||||
ffmpegs = let
|
ffmpegs =
|
||||||
|
let
|
||||||
|
|
||||||
configurations = lib.cartesianProductOfSets {
|
configurations = lib.cartesianProductOfSets {
|
||||||
profile = profiles;
|
profile = profiles;
|
||||||
preset = presets;
|
preset = presets;
|
||||||
};
|
|
||||||
|
|
||||||
p720 = { profile, preset }:
|
|
||||||
ffmpegTemplate "${profile}-${preset}-720p" { inherit profile preset; };
|
|
||||||
|
|
||||||
p1080 = { profile, preset }:
|
|
||||||
ffmpegTemplate "${profile}-${preset}-1080p" {
|
|
||||||
inherit profile preset;
|
|
||||||
height = 1080;
|
|
||||||
width = 1920;
|
|
||||||
resolution = "1080p";
|
|
||||||
};
|
|
||||||
in (map p720 configurations) ++ (map p1080 configurations);
|
|
||||||
|
|
||||||
ffmpegsTune = let
|
|
||||||
configurations = lib.cartesianProductOfSets {
|
|
||||||
profile = profiles;
|
|
||||||
preset = presets;
|
|
||||||
tune = tunes;
|
|
||||||
};
|
|
||||||
|
|
||||||
p720 = { profile, preset, tune }:
|
|
||||||
ffmpegTemplate "${profile}-${preset}-${tune}-720p" {
|
|
||||||
inherit profile preset tune;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
p1080 = { profile, preset, tune }:
|
p720 = { profile, preset }:
|
||||||
ffmpegTemplate "${profile}-${preset}-${tune}-1080p" {
|
ffmpegTemplate "${profile}-${preset}-720p" { inherit profile preset; };
|
||||||
inherit profile preset tune;
|
|
||||||
height = 1080;
|
p1080 = { profile, preset }:
|
||||||
width = 1920;
|
ffmpegTemplate "${profile}-${preset}-1080p" {
|
||||||
resolution = "1080p";
|
inherit profile preset;
|
||||||
|
height = 1080;
|
||||||
|
width = 1920;
|
||||||
|
resolution = "1080p";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
(map p720 configurations) ++ (map p1080 configurations);
|
||||||
|
|
||||||
|
ffmpegsTune =
|
||||||
|
let
|
||||||
|
configurations = lib.cartesianProductOfSets {
|
||||||
|
profile = profiles;
|
||||||
|
preset = presets;
|
||||||
|
tune = tunes;
|
||||||
};
|
};
|
||||||
|
|
||||||
in (map p720 configurations) ++ (map p1080 configurations);
|
p720 = { profile, preset, tune }:
|
||||||
|
ffmpegTemplate "${profile}-${preset}-${tune}-720p" {
|
||||||
|
inherit profile preset tune;
|
||||||
|
};
|
||||||
|
|
||||||
in {
|
p1080 = { profile, preset, tune }:
|
||||||
|
ffmpegTemplate "${profile}-${preset}-${tune}-1080p" {
|
||||||
|
inherit profile preset tune;
|
||||||
|
height = 1080;
|
||||||
|
width = 1920;
|
||||||
|
resolution = "1080p";
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
(map p720 configurations) ++ (map p1080 configurations);
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.ffmpeg = {
|
options.programs.custom.ffmpeg = {
|
||||||
enable = mkEnableOption "enable programs.custom.ffmpeg";
|
enable = mkEnableOption "enable programs.custom.ffmpeg";
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.programs.custom.git;
|
cfg = config.programs.custom.git;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.git.enable =
|
options.programs.custom.git.enable =
|
||||||
mkEnableOption "install git and all its tools";
|
mkEnableOption "install git and all its tools";
|
||||||
|
|
|
@ -29,7 +29,8 @@ let
|
||||||
|
|
||||||
cfg = config.programs.custom.shellTools;
|
cfg = config.programs.custom.shellTools;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.shellTools.enable =
|
options.programs.custom.shellTools.enable =
|
||||||
mkEnableOption "enable shell tools";
|
mkEnableOption "enable shell tools";
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.programs.custom.zsh;
|
cfg = config.programs.custom.zsh;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.zsh = {
|
options.programs.custom.zsh = {
|
||||||
enable = mkEnableOption "enable zsh";
|
enable = mkEnableOption "enable zsh";
|
||||||
|
|
|
@ -14,47 +14,51 @@ let
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
command = "${pkgs.slack}/bin/slack";
|
command = "${pkgs.slack}/bin/slack";
|
||||||
|
|
||||||
desktopFile = let
|
desktopFile =
|
||||||
name = program;
|
let
|
||||||
comment = "Chat Programm";
|
name = program;
|
||||||
in pkgs.writeTextFile {
|
comment = "Chat Programm";
|
||||||
name = "${name}.desktop";
|
in
|
||||||
destination = "/share/applications/${name}.desktop";
|
pkgs.writeTextFile {
|
||||||
text = ''
|
name = "${name}.desktop";
|
||||||
[Desktop Entry]
|
destination = "/share/applications/${name}.desktop";
|
||||||
Categories=Application;Utility;
|
text = ''
|
||||||
Comment=${comment}
|
[Desktop Entry]
|
||||||
Encoding=UTF-8
|
Categories=Application;Utility;
|
||||||
Exec=${bin}/bin/${name}
|
Comment=${comment}
|
||||||
Icon=gnome-lockscreen
|
Encoding=UTF-8
|
||||||
Name=${name}
|
Exec=${bin}/bin/${name}
|
||||||
Terminal=false
|
Icon=gnome-lockscreen
|
||||||
Type=Application
|
Name=${name}
|
||||||
'';
|
Terminal=false
|
||||||
};
|
Type=Application
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
# the script
|
# the script
|
||||||
# ----------
|
# ----------
|
||||||
bin = let
|
bin =
|
||||||
backupFile = "${cfg.homeBackup}.tar.lzma";
|
let
|
||||||
rolloutFile = "${cfg.home}.tar.lzma";
|
backupFile = "${cfg.homeBackup}.tar.lzma";
|
||||||
lockFile = "${cfg.home}-lock";
|
rolloutFile = "${cfg.home}.tar.lzma";
|
||||||
in pkgs.writeShellScriptBin "${program}" ''
|
lockFile = "${cfg.home}-lock";
|
||||||
# set -x
|
in
|
||||||
if [[ ! -e ${lockFile} ]]
|
pkgs.writeShellScriptBin "${program}" ''
|
||||||
then
|
# set -x
|
||||||
# rollout backup
|
if [[ ! -e ${lockFile} ]]
|
||||||
if [[ -e ${backupFile} ]]
|
|
||||||
then
|
then
|
||||||
cp ${backupFile} ${rolloutFile}
|
# rollout backup
|
||||||
sudo -u ${program} ${tarBin} xf ${rolloutFile} --directory ${cfg.home}
|
if [[ -e ${backupFile} ]]
|
||||||
rm ${rolloutFile}
|
then
|
||||||
touch ${lockFile}
|
cp ${backupFile} ${rolloutFile}
|
||||||
|
sudo -u ${program} ${tarBin} xf ${rolloutFile} --directory ${cfg.home}
|
||||||
|
rm ${rolloutFile}
|
||||||
|
touch ${lockFile}
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
sudo -u ${program} ${command}
|
sudo -u ${program} ${command}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
backupScript = pkgs.writeShellScriptBin "${program}-backup" ''
|
backupScript = pkgs.writeShellScriptBin "${program}-backup" ''
|
||||||
sudo -u ${program} \
|
sudo -u ${program} \
|
||||||
|
@ -75,7 +79,8 @@ let
|
||||||
|
|
||||||
cfg = config.programs.custom.slack;
|
cfg = config.programs.custom.slack;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.slack = {
|
options.programs.custom.slack = {
|
||||||
enable = mkEnableOption "install slack";
|
enable = mkEnableOption "install slack";
|
||||||
|
|
|
@ -14,7 +14,8 @@ let
|
||||||
|
|
||||||
cfg = config.programs.custom.steam;
|
cfg = config.programs.custom.steam;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.steam.enable = mkEnableOption "enable steam";
|
options.programs.custom.steam.enable = mkEnableOption "enable steam";
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,8 @@ let
|
||||||
});
|
});
|
||||||
#vit = pkgs.vit;
|
#vit = pkgs.vit;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.taskwarrior.enable =
|
options.programs.custom.taskwarrior.enable =
|
||||||
mkEnableOption "Enable Taskwarrior services";
|
mkEnableOption "Enable Taskwarrior services";
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.programs.custom.urxvt;
|
cfg = config.programs.custom.urxvt;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.urxvt = {
|
options.programs.custom.urxvt = {
|
||||||
|
|
||||||
|
@ -63,24 +64,26 @@ in {
|
||||||
URxvt.fading: 0
|
URxvt.fading: 0
|
||||||
'';
|
'';
|
||||||
|
|
||||||
"X11/Xresource.d/urxvt-font".source = let
|
"X11/Xresource.d/urxvt-font".source =
|
||||||
fontFamily = "terminus";
|
let
|
||||||
normalFont = fontSize:
|
fontFamily = "terminus";
|
||||||
"-*-${fontFamily}-medium-*-*-*-${toString fontSize}-*-*-*-*-*-*-*";
|
normalFont = fontSize:
|
||||||
boldFont = fontSize:
|
"-*-${fontFamily}-medium-*-*-*-${toString fontSize}-*-*-*-*-*-*-*";
|
||||||
"-*-${fontFamily}-bold-*-*-*-${toString fontSize}-*-*-*-*-*-*-*";
|
boldFont = fontSize:
|
||||||
italicFont = normalFont;
|
"-*-${fontFamily}-bold-*-*-*-${toString fontSize}-*-*-*-*-*-*-*";
|
||||||
itallicBoldFont = boldFont;
|
italicFont = normalFont;
|
||||||
backupFont = fontSize:
|
itallicBoldFont = boldFont;
|
||||||
"xft:TerminessTTF Nerd Font:pixelsize=${toString fontSize}";
|
backupFont = fontSize:
|
||||||
|
"xft:TerminessTTF Nerd Font:pixelsize=${toString fontSize}";
|
||||||
|
|
||||||
fontCommand = key: fontSize: ''
|
fontCommand = key: fontSize: ''
|
||||||
URxvt.keysym.M-${key}: command:\033]710;${normalFont fontSize},${
|
URxvt.keysym.M-${key}: command:\033]710;${normalFont fontSize},${
|
||||||
backupFont fontSize
|
backupFont fontSize
|
||||||
}\007\033]711;${boldFont fontSize},${backupFont fontSize}\007
|
}\007\033]711;${boldFont fontSize},${backupFont fontSize}\007
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in pkgs.writeText "Xresource-urxvt-font" ''
|
in
|
||||||
|
pkgs.writeText "Xresource-urxvt-font" ''
|
||||||
|
|
||||||
URxvt.allow_bold: true
|
URxvt.allow_bold: true
|
||||||
URxvt.xftAntialias: true
|
URxvt.xftAntialias: true
|
||||||
|
@ -110,28 +113,31 @@ in {
|
||||||
${fontCommand "F4" (cfg.fontSize + 20)}
|
${fontCommand "F4" (cfg.fontSize + 20)}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
"X11/Xresource.d/urxvt-colors".source = let
|
"X11/Xresource.d/urxvt-colors".source =
|
||||||
colorTheme = if (cfg.colorTheme == "dark") then ''
|
let
|
||||||
#define S_base03 #002b36
|
colorTheme =
|
||||||
#define S_base02 #073642
|
if (cfg.colorTheme == "dark") then ''
|
||||||
#define S_base01 #586e75
|
#define S_base03 #002b36
|
||||||
#define S_base00 #657b83
|
#define S_base02 #073642
|
||||||
#define S_base0 #839496
|
#define S_base01 #586e75
|
||||||
#define S_base1 #93a1a1
|
#define S_base00 #657b83
|
||||||
#define S_base2 #eee8d5
|
#define S_base0 #839496
|
||||||
#define S_base3 #fdf6e3
|
#define S_base1 #93a1a1
|
||||||
'' else ''
|
#define S_base2 #eee8d5
|
||||||
#define S_base03 #fdf6e3
|
#define S_base3 #fdf6e3
|
||||||
#define S_base02 #eee8d5
|
'' else ''
|
||||||
#define S_base01 #93a1a1
|
#define S_base03 #fdf6e3
|
||||||
#define S_base00 #839496
|
#define S_base02 #eee8d5
|
||||||
#define S_base0 #657b83
|
#define S_base01 #93a1a1
|
||||||
#define S_base1 #586e75
|
#define S_base00 #839496
|
||||||
#define S_base2 #073642
|
#define S_base0 #657b83
|
||||||
#define S_base3 #002b36
|
#define S_base1 #586e75
|
||||||
'';
|
#define S_base2 #073642
|
||||||
|
#define S_base3 #002b36
|
||||||
|
'';
|
||||||
|
|
||||||
in pkgs.writeText "Xresource-urxvt-colors" ''
|
in
|
||||||
|
pkgs.writeText "Xresource-urxvt-colors" ''
|
||||||
|
|
||||||
!! Common
|
!! Common
|
||||||
!! ------
|
!! ------
|
||||||
|
|
|
@ -9,24 +9,27 @@ let
|
||||||
# show keyboard input on desktop for screencasts
|
# show keyboard input on desktop for screencasts
|
||||||
screenKey = pkgs.symlinkJoin {
|
screenKey = pkgs.symlinkJoin {
|
||||||
name = "screen-keys";
|
name = "screen-keys";
|
||||||
paths = let
|
paths =
|
||||||
screenKeyScript = { position ? "bottom", size ? "small", ... }:
|
let
|
||||||
pkgs.writeShellScriptBin "screenkeys-${position}-${size}" # sh
|
screenKeyScript = { position ? "bottom", size ? "small", ... }:
|
||||||
''
|
pkgs.writeShellScriptBin "screenkeys-${position}-${size}" # sh
|
||||||
${pkgs.screenkey}/bin/screenkey \
|
''
|
||||||
--no-detach \
|
${pkgs.screenkey}/bin/screenkey \
|
||||||
--bg-color '#fdf6e3' \
|
--no-detach \
|
||||||
--font-color '#073642' \
|
--bg-color '#fdf6e3' \
|
||||||
-p ${position} \
|
--font-color '#073642' \
|
||||||
-s ${size} \
|
-p ${position} \
|
||||||
"$@"
|
-s ${size} \
|
||||||
'';
|
"$@"
|
||||||
in lib.flatten (lib.flip map [ "large" "small" "medium" ] (size:
|
'';
|
||||||
lib.flip map [ "top" "center" "bottom" ]
|
in
|
||||||
(position: screenKeyScript { inherit size position; })));
|
lib.flatten (lib.flip map [ "large" "small" "medium" ] (size:
|
||||||
|
lib.flip map [ "top" "center" "bottom" ]
|
||||||
|
(position: screenKeyScript { inherit size position; })));
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.video.enable = mkEnableOption "enable video tools";
|
options.programs.custom.video.enable = mkEnableOption "enable video tools";
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ let
|
||||||
|
|
||||||
}).env
|
}).env
|
||||||
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
# active plugins
|
# active plugins
|
||||||
|
@ -200,7 +200,8 @@ let
|
||||||
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
# no options
|
# no options
|
||||||
options.programs.custom.vim.enable = lib.mkEnableOption "vim";
|
options.programs.custom.vim.enable = lib.mkEnableOption "vim";
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.programs.custom.xterm;
|
cfg = config.programs.custom.xterm;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.programs.custom.xterm = {
|
options.programs.custom.xterm = {
|
||||||
enable = mkEnableOption "configure and enable urxvt";
|
enable = mkEnableOption "configure and enable urxvt";
|
||||||
|
@ -41,17 +42,19 @@ in {
|
||||||
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
"X11/Xresource.d/xterm-font".source = let
|
"X11/Xresource.d/xterm-font".source =
|
||||||
fontFamily = "terminus";
|
let
|
||||||
normalFont = fontSize:
|
fontFamily = "terminus";
|
||||||
"-*-${fontFamily}-medium-*-*-*-${toString fontSize}-*-*-*-*-*-*-*";
|
normalFont = fontSize:
|
||||||
boldFont = fontSize:
|
"-*-${fontFamily}-medium-*-*-*-${toString fontSize}-*-*-*-*-*-*-*";
|
||||||
"-*-${fontFamily}-bold-*-*-*-${toString fontSize}-*-*-*-*-*-*-*";
|
boldFont = fontSize:
|
||||||
italicFont = normalFont;
|
"-*-${fontFamily}-bold-*-*-*-${toString fontSize}-*-*-*-*-*-*-*";
|
||||||
itallicBoldFont = boldFont;
|
italicFont = normalFont;
|
||||||
backupFont = fontSize:
|
itallicBoldFont = boldFont;
|
||||||
"xft:TerminessTTF Nerd Font:pixelsize=${toString fontSize}";
|
backupFont = fontSize:
|
||||||
in pkgs.writeText "Xresource-xterm-font" ''
|
"xft:TerminessTTF Nerd Font:pixelsize=${toString fontSize}";
|
||||||
|
in
|
||||||
|
pkgs.writeText "Xresource-xterm-font" ''
|
||||||
|
|
||||||
XTerm.allow_bold: true
|
XTerm.allow_bold: true
|
||||||
XTerm.xftAntialias: true
|
XTerm.xftAntialias: true
|
||||||
|
@ -76,29 +79,32 @@ in {
|
||||||
XTerm.*.bolditalicFont: ${itallicBoldFont cfg.fontSize}
|
XTerm.*.bolditalicFont: ${itallicBoldFont cfg.fontSize}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
"X11/Xresource.d/xterm-colors".source = let
|
"X11/Xresource.d/xterm-colors".source =
|
||||||
colorTheme = if (cfg.colorTheme == "dark") then ''
|
let
|
||||||
#define S_base03 #002b36
|
colorTheme =
|
||||||
#define S_base02 #073642
|
if (cfg.colorTheme == "dark") then ''
|
||||||
#define S_base01 #586e75
|
#define S_base03 #002b36
|
||||||
#define S_base00 #657b83
|
#define S_base02 #073642
|
||||||
#define S_base0 #839496
|
#define S_base01 #586e75
|
||||||
#define S_base1 #93a1a1
|
#define S_base00 #657b83
|
||||||
#define S_base2 #eee8d5
|
#define S_base0 #839496
|
||||||
#define S_base3 #fdf6e3
|
#define S_base1 #93a1a1
|
||||||
|
#define S_base2 #eee8d5
|
||||||
|
#define S_base3 #fdf6e3
|
||||||
|
|
||||||
'' else ''
|
'' else ''
|
||||||
#define S_base03 #fdf6e3
|
#define S_base03 #fdf6e3
|
||||||
#define S_base02 #eee8d5
|
#define S_base02 #eee8d5
|
||||||
#define S_base01 #93a1a1
|
#define S_base01 #93a1a1
|
||||||
#define S_base00 #839496
|
#define S_base00 #839496
|
||||||
#define S_base0 #657b83
|
#define S_base0 #657b83
|
||||||
#define S_base1 #586e75
|
#define S_base1 #586e75
|
||||||
#define S_base2 #073642
|
#define S_base2 #073642
|
||||||
#define S_base3 #002b36
|
#define S_base3 #002b36
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in pkgs.writeText "Xresource-xterm-colors" ''
|
in
|
||||||
|
pkgs.writeText "Xresource-xterm-colors" ''
|
||||||
|
|
||||||
!! Color Configuration
|
!! Color Configuration
|
||||||
!! -------------------
|
!! -------------------
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.custom.services.castget;
|
cfg = config.custom.services.castget;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.custom.services.castget = {
|
options.custom.services.castget = {
|
||||||
enable = mkEnableOption "enable custom.services.castget";
|
enable = mkEnableOption "enable custom.services.castget";
|
||||||
|
@ -67,25 +68,33 @@ in {
|
||||||
restartIfChanged = false;
|
restartIfChanged = false;
|
||||||
serviceConfig.User = cfg.user;
|
serviceConfig.User = cfg.user;
|
||||||
|
|
||||||
preStart = let
|
preStart =
|
||||||
mkSpools =
|
let
|
||||||
mapAttrsToList (ignore: value: "mkdir -p ${value.spool}") cfg.feeds;
|
mkSpools =
|
||||||
in concatStringsSep "\n" mkSpools;
|
mapAttrsToList (ignore: value: "mkdir -p ${value.spool}") cfg.feeds;
|
||||||
script = let
|
in
|
||||||
channels = mapAttrsToList (key: ignore: key) cfg.feeds;
|
concatStringsSep "\n" mkSpools;
|
||||||
castget = "${pkgs.castget}/bin/castget";
|
script =
|
||||||
|
let
|
||||||
|
channels = mapAttrsToList (key: ignore: key) cfg.feeds;
|
||||||
|
castget = "${pkgs.castget}/bin/castget";
|
||||||
|
|
||||||
configurationFile = let
|
configurationFile =
|
||||||
configurations = mapAttrsToList (key: value: ''
|
let
|
||||||
[${key}]
|
configurations = mapAttrsToList
|
||||||
url=${value.url}
|
(key: value: ''
|
||||||
spool=${value.spool}
|
[${key}]
|
||||||
'') cfg.feeds;
|
url=${value.url}
|
||||||
in (pkgs.writeText "castget-configuration"
|
spool=${value.spool}
|
||||||
(concatStringsSep "" configurations));
|
'')
|
||||||
in (concatMapStringsSep "\n"
|
cfg.feeds;
|
||||||
(channel: "${castget} --rcfile ${configurationFile} ${channel}")
|
in
|
||||||
channels);
|
(pkgs.writeText "castget-configuration"
|
||||||
|
(concatStringsSep "" configurations));
|
||||||
|
in
|
||||||
|
(concatMapStringsSep "\n"
|
||||||
|
(channel: "${castget} --rcfile ${configurationFile} ${channel}")
|
||||||
|
channels);
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.timers."${cfg.serviceName}" = {
|
systemd.timers."${cfg.serviceName}" = {
|
||||||
|
|
|
@ -11,21 +11,24 @@ let
|
||||||
inherit example description default;
|
inherit example description default;
|
||||||
type = with lib.types;
|
type = with lib.types;
|
||||||
let
|
let
|
||||||
valueType = nullOr (oneOf [
|
valueType = nullOr
|
||||||
bool
|
(oneOf [
|
||||||
int
|
bool
|
||||||
float
|
int
|
||||||
str
|
float
|
||||||
(attrsOf valueType)
|
str
|
||||||
(listOf valueType)
|
(attrsOf valueType)
|
||||||
]) // {
|
(listOf valueType)
|
||||||
|
]) // {
|
||||||
description = "";
|
description = "";
|
||||||
emptyValue.value = { };
|
emptyValue.value = { };
|
||||||
};
|
};
|
||||||
in valueType;
|
in
|
||||||
|
valueType;
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.services.homeAssistantConfig = mkMagicMergeOption {
|
options.services.homeAssistantConfig = mkMagicMergeOption {
|
||||||
description = ''
|
description = ''
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.services.lektor;
|
cfg = config.services.lektor;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.services.lektor = {
|
options.services.lektor = {
|
||||||
enable = mkEnableOption "enable services.lektor";
|
enable = mkEnableOption "enable services.lektor";
|
||||||
|
@ -107,57 +108,59 @@ in {
|
||||||
TimeoutStartSec =
|
TimeoutStartSec =
|
||||||
"infinity"; # it might take some time will this thing is up
|
"infinity"; # it might take some time will this thing is up
|
||||||
|
|
||||||
ExecStartPre = let
|
ExecStartPre =
|
||||||
|
let
|
||||||
|
|
||||||
sshKeyTarget = "/run/keys.lektor/id_rsa";
|
sshKeyTarget = "/run/keys.lektor/id_rsa";
|
||||||
|
|
||||||
sshConfig = pkgs.writeText "sshconfig" ''
|
sshConfig = pkgs.writeText "sshconfig" ''
|
||||||
Host ${cfg.host}
|
Host ${cfg.host}
|
||||||
IdentityFile ${sshKeyTarget}
|
IdentityFile ${sshKeyTarget}
|
||||||
|
|
||||||
Host *
|
Host *
|
||||||
ForwardAgent no
|
ForwardAgent no
|
||||||
Compression no
|
Compression no
|
||||||
ServerAliveInterval 0
|
ServerAliveInterval 0
|
||||||
HashKnownHosts no
|
HashKnownHosts no
|
||||||
UserKnownHostsFile ~/.ssh/known_hosts
|
UserKnownHostsFile ~/.ssh/known_hosts
|
||||||
ControlMaster no
|
ControlMaster no
|
||||||
ControlPath ~/.ssh/master-%r@%n:%p
|
ControlPath ~/.ssh/master-%r@%n:%p
|
||||||
ControlPersist no
|
ControlPersist no
|
||||||
'';
|
|
||||||
|
|
||||||
sshKeyScript = pkgs.writers.writeDash "keyfile-gen" # sh
|
|
||||||
''
|
|
||||||
set -x
|
|
||||||
|
|
||||||
# setup ~/.ssh
|
|
||||||
mkdir -p ${cfg.home}/.ssh
|
|
||||||
chown ${cfg.user} ${cfg.home}/.ssh
|
|
||||||
chmod 700 ${cfg.home}/.ssh
|
|
||||||
|
|
||||||
cp ${sshConfig} ${cfg.home}/.ssh/config
|
|
||||||
chown ${cfg.user} ${cfg.home}/.ssh/config
|
|
||||||
chmod 500 ${cfg.home}/.ssh/config
|
|
||||||
|
|
||||||
mkdir -p ${dirOf sshKeyTarget}
|
|
||||||
chmod 700 ${dirOf sshKeyTarget}
|
|
||||||
chown ${cfg.user} ${dirOf sshKeyTarget}
|
|
||||||
cp ${toString cfg.sshKey} ${sshKeyTarget}
|
|
||||||
chown ${cfg.user} ${sshKeyTarget}
|
|
||||||
chmod 500 ${sshKeyTarget}
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
cloneScript = pkgs.writers.writeDash "clone" # sh
|
sshKeyScript = pkgs.writers.writeDash "keyfile-gen" # sh
|
||||||
''
|
''
|
||||||
set -x
|
set -x
|
||||||
if [[ `ls ~/${cfg.user} | wc -l` == 0 ]]
|
|
||||||
then
|
|
||||||
rm ~/${cfg.user}
|
|
||||||
fi
|
|
||||||
${pkgs.git}/bin/git clone ${cfg.repository} ~/${cfg.user}
|
|
||||||
'';
|
|
||||||
|
|
||||||
in [ "+${sshKeyScript}" "-${cloneScript}" ];
|
# setup ~/.ssh
|
||||||
|
mkdir -p ${cfg.home}/.ssh
|
||||||
|
chown ${cfg.user} ${cfg.home}/.ssh
|
||||||
|
chmod 700 ${cfg.home}/.ssh
|
||||||
|
|
||||||
|
cp ${sshConfig} ${cfg.home}/.ssh/config
|
||||||
|
chown ${cfg.user} ${cfg.home}/.ssh/config
|
||||||
|
chmod 500 ${cfg.home}/.ssh/config
|
||||||
|
|
||||||
|
mkdir -p ${dirOf sshKeyTarget}
|
||||||
|
chmod 700 ${dirOf sshKeyTarget}
|
||||||
|
chown ${cfg.user} ${dirOf sshKeyTarget}
|
||||||
|
cp ${toString cfg.sshKey} ${sshKeyTarget}
|
||||||
|
chown ${cfg.user} ${sshKeyTarget}
|
||||||
|
chmod 500 ${sshKeyTarget}
|
||||||
|
'';
|
||||||
|
|
||||||
|
cloneScript = pkgs.writers.writeDash "clone" # sh
|
||||||
|
''
|
||||||
|
set -x
|
||||||
|
if [[ `ls ~/${cfg.user} | wc -l` == 0 ]]
|
||||||
|
then
|
||||||
|
rm ~/${cfg.user}
|
||||||
|
fi
|
||||||
|
${pkgs.git}/bin/git clone ${cfg.repository} ~/${cfg.user}
|
||||||
|
'';
|
||||||
|
|
||||||
|
in
|
||||||
|
[ "+${sshKeyScript}" "-${cloneScript}" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
# todo : add restart ruling
|
# todo : add restart ruling
|
||||||
|
|
|
@ -11,24 +11,27 @@ let
|
||||||
inherit example description default;
|
inherit example description default;
|
||||||
type = with lib.types;
|
type = with lib.types;
|
||||||
let
|
let
|
||||||
valueType = nullOr (oneOf [
|
valueType = nullOr
|
||||||
bool
|
(oneOf [
|
||||||
int
|
bool
|
||||||
float
|
int
|
||||||
str
|
float
|
||||||
(attrsOf valueType)
|
str
|
||||||
(listOf valueType)
|
(attrsOf valueType)
|
||||||
]) // {
|
(listOf valueType)
|
||||||
|
]) // {
|
||||||
description = "";
|
description = "";
|
||||||
emptyValue.value = { };
|
emptyValue.value = { };
|
||||||
};
|
};
|
||||||
in valueType;
|
in
|
||||||
|
valueType;
|
||||||
};
|
};
|
||||||
|
|
||||||
lightControlConfig =
|
lightControlConfig =
|
||||||
pkgs.writeText "light-control.json" (builtins.toJSON cfg.config);
|
pkgs.writeText "light-control.json" (builtins.toJSON cfg.config);
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.services.mqtt.light-control = {
|
options.services.mqtt.light-control = {
|
||||||
enable = mkEnableOption "enable mqtt.light-control";
|
enable = mkEnableOption "enable mqtt.light-control";
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.custom.samba-share;
|
cfg = config.custom.samba-share;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.custom.samba-share = {
|
options.custom.samba-share = {
|
||||||
enable = mkEnableOption "enable custom.samba-share";
|
enable = mkEnableOption "enable custom.samba-share";
|
||||||
|
@ -61,27 +62,31 @@ in {
|
||||||
disable spoolss = yes
|
disable spoolss = yes
|
||||||
'';
|
'';
|
||||||
|
|
||||||
shares = mapAttrs' (name: path: {
|
shares = mapAttrs'
|
||||||
name = name;
|
(name: path: {
|
||||||
value = {
|
|
||||||
browsable = "yes";
|
|
||||||
comment = "read only share ${name}";
|
|
||||||
path = path;
|
|
||||||
"read only" = "yes";
|
|
||||||
"guest ok" = "yes";
|
|
||||||
};
|
|
||||||
}) cfg.folders // (mapAttrs' (name:
|
|
||||||
{ users, folder, ... }: {
|
|
||||||
name = name;
|
name = name;
|
||||||
value = {
|
value = {
|
||||||
browsable = "yes";
|
browsable = "yes";
|
||||||
comment = "read only share ${name}";
|
comment = "read only share ${name}";
|
||||||
path = folder;
|
path = path;
|
||||||
"read only" = "no";
|
"read only" = "yes";
|
||||||
"valid users" = users;
|
"guest ok" = "yes";
|
||||||
"guest ok" = "false";
|
|
||||||
};
|
};
|
||||||
}) cfg.private);
|
})
|
||||||
|
cfg.folders // (mapAttrs'
|
||||||
|
(name:
|
||||||
|
{ users, folder, ... }: {
|
||||||
|
name = name;
|
||||||
|
value = {
|
||||||
|
browsable = "yes";
|
||||||
|
comment = "read only share ${name}";
|
||||||
|
path = folder;
|
||||||
|
"read only" = "no";
|
||||||
|
"valid users" = users;
|
||||||
|
"guest ok" = "false";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
cfg.private);
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users.smbguest = {
|
users.users.smbguest = {
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.services.custom.ssh;
|
cfg = config.services.custom.ssh;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.services.custom.ssh = {
|
options.services.custom.ssh = {
|
||||||
tools.enable = mkEnableOption "Add ssh tools";
|
tools.enable = mkEnableOption "Add ssh tools";
|
||||||
|
@ -44,14 +45,16 @@ in {
|
||||||
Banner /etc/sshd/banner-line
|
Banner /etc/sshd/banner-line
|
||||||
'';
|
'';
|
||||||
|
|
||||||
environment.etc."sshd/banner-line".text = let
|
environment.etc."sshd/banner-line".text =
|
||||||
text = config.networking.hostName;
|
let
|
||||||
size = 80 - (lib.stringLength text);
|
text = config.networking.hostName;
|
||||||
space = lib.fixedWidthString size " " "";
|
size = 80 - (lib.stringLength text);
|
||||||
in ''
|
space = lib.fixedWidthString size " " "";
|
||||||
────────────────────────────────────────────────────────────────────────────────
|
in
|
||||||
${space}${text}
|
''
|
||||||
'';
|
────────────────────────────────────────────────────────────────────────────────
|
||||||
|
${space}${text}
|
||||||
|
'';
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ in
|
||||||
default = "4:00:00";
|
default = "4:00:00";
|
||||||
};
|
};
|
||||||
recurrence = mkOption {
|
recurrence = mkOption {
|
||||||
type = enum["on" "off"];
|
type = enum [ "on" "off" ];
|
||||||
default = "off";
|
default = "off";
|
||||||
};
|
};
|
||||||
pushoverApiTokenFile = mkOption {
|
pushoverApiTokenFile = mkOption {
|
||||||
|
@ -37,7 +37,7 @@ in
|
||||||
certificateFile = mkOption {
|
certificateFile = mkOption {
|
||||||
type = path;
|
type = path;
|
||||||
};
|
};
|
||||||
credentials= mkOption {
|
credentials = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
};
|
};
|
||||||
keyFile = mkOption {
|
keyFile = mkOption {
|
||||||
|
@ -55,43 +55,44 @@ in
|
||||||
DynamicUser = true;
|
DynamicUser = true;
|
||||||
StateDirectory = name;
|
StateDirectory = name;
|
||||||
};
|
};
|
||||||
script = let
|
script =
|
||||||
taskwarriorCommand = pkgs.writers.writeDash "taskwarrior-push" ''
|
let
|
||||||
${pkgs.taskwarrior}/bin/task \
|
taskwarriorCommand = pkgs.writers.writeDash "taskwarrior-push" ''
|
||||||
rc.recurrence=${cfg.recurrence} \
|
${pkgs.taskwarrior}/bin/task \
|
||||||
rc:/var/lib/${name}/.taskrc \
|
rc.recurrence=${cfg.recurrence} \
|
||||||
rc.data.location=/var/lib/${name}/${cfg.dataDir} \
|
rc:/var/lib/${name}/.taskrc \
|
||||||
rc.taskd.ca=${cfg.caFile} \
|
rc.data.location=/var/lib/${name}/${cfg.dataDir} \
|
||||||
rc.taskd.certificate=${cfg.certificateFile} \
|
rc.taskd.ca=${cfg.caFile} \
|
||||||
rc.taskd.credentials="${cfg.credentials}" \
|
rc.taskd.certificate=${cfg.certificateFile} \
|
||||||
rc.taskd.key=${cfg.keyFile} \
|
rc.taskd.credentials="${cfg.credentials}" \
|
||||||
rc.taskd.server=${cfg.server} \
|
rc.taskd.key=${cfg.keyFile} \
|
||||||
"$@"
|
rc.taskd.server=${cfg.server} \
|
||||||
'';
|
"$@"
|
||||||
in
|
'';
|
||||||
|
in
|
||||||
''
|
''
|
||||||
if [ -d /var/lib/${name}/${cfg.dataDir} ]
|
if [ -d /var/lib/${name}/${cfg.dataDir} ]
|
||||||
then
|
then
|
||||||
echo "synchronize {cfg.dataDir}"
|
echo "synchronize {cfg.dataDir}"
|
||||||
${taskwarriorCommand} sync
|
${taskwarriorCommand} sync
|
||||||
else
|
else
|
||||||
echo "initialize ${cfg.dataDir}"
|
echo "initialize ${cfg.dataDir}"
|
||||||
${pkgs.coreutils}/bin/yes | ${taskwarriorCommand} sync init
|
${pkgs.coreutils}/bin/yes | ${taskwarriorCommand} sync init
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${taskwarriorCommand} '${cfg.query}' export \
|
${taskwarriorCommand} '${cfg.query}' export \
|
||||||
| ${pkgs.jq}/bin/jq -r '.[] | @base64' | while read entry
|
| ${pkgs.jq}/bin/jq -r '.[] | @base64' | while read entry
|
||||||
do
|
do
|
||||||
echo $entry | base64 --decode | \
|
echo $entry | base64 --decode | \
|
||||||
${pkgs.jq}/bin/jq '{
|
${pkgs.jq}/bin/jq '{
|
||||||
"token": "'`cat ${cfg.pushoverApiTokenFile}`'",
|
"token": "'`cat ${cfg.pushoverApiTokenFile}`'",
|
||||||
"user": "'`cat ${cfg.pushoverUserKeyFile}`'",
|
"user": "'`cat ${cfg.pushoverUserKeyFile}`'",
|
||||||
"titel": "taskwarrior",
|
"titel": "taskwarrior",
|
||||||
message: .description
|
message: .description
|
||||||
}' \
|
}' \
|
||||||
| ${pkgs.curl}/bin/curl -sS -X POST -H 'Content-Type: application/json' -d @- \
|
| ${pkgs.curl}/bin/curl -sS -X POST -H 'Content-Type: application/json' -d @- \
|
||||||
"https://api.pushover.net/1/messages.json"
|
"https://api.pushover.net/1/messages.json"
|
||||||
done
|
done
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
systemd.timers.taskwarrior-pushover = {
|
systemd.timers.taskwarrior-pushover = {
|
||||||
|
|
|
@ -30,7 +30,8 @@ let
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.service.videoencoder = {
|
options.service.videoencoder = {
|
||||||
enable = mkEnableOption "enable service.videoencoder";
|
enable = mkEnableOption "enable service.videoencoder";
|
||||||
|
@ -91,14 +92,17 @@ in {
|
||||||
systemd.services."videoEncoding" = {
|
systemd.services."videoEncoding" = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
enable = true;
|
enable = true;
|
||||||
script = let
|
script =
|
||||||
myList = map (value:
|
let
|
||||||
createEncoder "/tmp/videoencoder" value.inputFile value.outputFile)
|
myList = map
|
||||||
cfg.fileConfig;
|
(value:
|
||||||
in ''
|
createEncoder "/tmp/videoencoder" value.inputFile value.outputFile)
|
||||||
set -x
|
cfg.fileConfig;
|
||||||
${concatStringsSep "\n" myList}
|
in
|
||||||
'';
|
''
|
||||||
|
set -x
|
||||||
|
${concatStringsSep "\n" myList}
|
||||||
|
'';
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,8 @@ let
|
||||||
|
|
||||||
cfg = config.system.custom.audio;
|
cfg = config.system.custom.audio;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.system.custom.audio = {
|
options.system.custom.audio = {
|
||||||
enable = mkEnableOption "use PluseAudio";
|
enable = mkEnableOption "use PluseAudio";
|
||||||
|
|
|
@ -4,7 +4,8 @@ let
|
||||||
|
|
||||||
cfg = config.system.custom.bluetooth;
|
cfg = config.system.custom.bluetooth;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.system.custom.bluetooth.enable =
|
options.system.custom.bluetooth.enable =
|
||||||
lib.mkEnableOption "enable bluetooth support";
|
lib.mkEnableOption "enable bluetooth support";
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.system.custom.fonts;
|
cfg = config.system.custom.fonts;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.system.custom.fonts = {
|
options.system.custom.fonts = {
|
||||||
enable = mkEnableOption "enable fonts";
|
enable = mkEnableOption "enable fonts";
|
||||||
|
|
|
@ -9,12 +9,14 @@ let
|
||||||
dockerGroup =
|
dockerGroup =
|
||||||
if (config.virtualisation.docker.enable) then [ "docker" ] else [ ];
|
if (config.virtualisation.docker.enable) then [ "docker" ] else [ ];
|
||||||
|
|
||||||
vboxGroup = if (config.virtualisation.virtualbox.host.enable) then
|
vboxGroup =
|
||||||
[ "vboxusers" ]
|
if (config.virtualisation.virtualbox.host.enable) then
|
||||||
else
|
[ "vboxusers" ]
|
||||||
[ ];
|
else
|
||||||
|
[ ];
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.system.custom.mainUser = {
|
options.system.custom.mainUser = {
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,8 @@ let
|
||||||
${cfg.url}
|
${cfg.url}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.on-failure = api;
|
options.on-failure = api;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
cfg = config.system.permown;
|
cfg = config.system.permown;
|
||||||
nameGenerator = path: "permown.${replaceStrings [ "/" ] [ "_" ] path}";
|
nameGenerator = path: "permown.${replaceStrings [ "/" ] [ "_" ] path}";
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.system.permown = mkOption {
|
options.system.permown = mkOption {
|
||||||
default = { };
|
default = { };
|
||||||
|
@ -45,51 +46,54 @@ in {
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
config = let plans = lib.attrValues cfg;
|
config =
|
||||||
|
let plans = lib.attrValues cfg;
|
||||||
|
|
||||||
in mkIf (plans != [ ]) {
|
in mkIf (plans != [ ]) {
|
||||||
|
|
||||||
system.activationScripts.permown = let
|
system.activationScripts.permown =
|
||||||
mkdir = { path, ... }: ''
|
let
|
||||||
${pkgs.coreutils}/bin/mkdir -p ${path}
|
mkdir = { path, ... }: ''
|
||||||
'';
|
${pkgs.coreutils}/bin/mkdir -p ${path}
|
||||||
in concatMapStrings mkdir plans;
|
'';
|
||||||
|
in
|
||||||
|
concatMapStrings mkdir plans;
|
||||||
|
|
||||||
systemd.services = listToAttrs (flip map plans
|
systemd.services = listToAttrs (flip map plans
|
||||||
({ path, directory-mode, file-mode, owner, group, umask, ... }: {
|
({ path, directory-mode, file-mode, owner, group, umask, ... }: {
|
||||||
|
name = nameGenerator path;
|
||||||
|
value = {
|
||||||
|
environment = {
|
||||||
|
DIR_MODE = directory-mode;
|
||||||
|
FILE_MODE = file-mode;
|
||||||
|
OWNER_GROUP = "${owner}:${group}";
|
||||||
|
ROOT_PATH = path;
|
||||||
|
};
|
||||||
|
path = [ pkgs.coreutils pkgs.findutils pkgs.inotifyTools ];
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = pkgs.writers.writeDash "permown" ''
|
||||||
|
set -efu
|
||||||
|
find "$ROOT_PATH" -exec chown -h "$OWNER_GROUP" {} +
|
||||||
|
find "$ROOT_PATH" -type d -exec chmod "$DIR_MODE" {} +
|
||||||
|
find "$ROOT_PATH" -type f -exec chmod "$FILE_MODE" {} +
|
||||||
|
'';
|
||||||
|
PrivateTmp = true;
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = 10;
|
||||||
|
UMask = umask;
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
|
||||||
|
systemd.timers = listToAttrs (flip map plans ({ path, timer, ... }: {
|
||||||
name = nameGenerator path;
|
name = nameGenerator path;
|
||||||
value = {
|
value = {
|
||||||
environment = {
|
|
||||||
DIR_MODE = directory-mode;
|
|
||||||
FILE_MODE = file-mode;
|
|
||||||
OWNER_GROUP = "${owner}:${group}";
|
|
||||||
ROOT_PATH = path;
|
|
||||||
};
|
|
||||||
path = [ pkgs.coreutils pkgs.findutils pkgs.inotifyTools ];
|
|
||||||
serviceConfig = {
|
|
||||||
ExecStart = pkgs.writers.writeDash "permown" ''
|
|
||||||
set -efu
|
|
||||||
find "$ROOT_PATH" -exec chown -h "$OWNER_GROUP" {} +
|
|
||||||
find "$ROOT_PATH" -type d -exec chmod "$DIR_MODE" {} +
|
|
||||||
find "$ROOT_PATH" -type f -exec chmod "$FILE_MODE" {} +
|
|
||||||
'';
|
|
||||||
PrivateTmp = true;
|
|
||||||
Restart = "always";
|
|
||||||
RestartSec = 10;
|
|
||||||
UMask = umask;
|
|
||||||
};
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
timerConfig.OnCalendar = timer;
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
systemd.timers = listToAttrs (flip map plans ({ path, timer, ... }: {
|
};
|
||||||
name = nameGenerator path;
|
|
||||||
value = {
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
timerConfig.OnCalendar = timer;
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.system.custom.wifi;
|
cfg = config.system.custom.wifi;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.system.custom.wifi = {
|
options.system.custom.wifi = {
|
||||||
enable = mkEnableOption "enable wifi";
|
enable = mkEnableOption "enable wifi";
|
||||||
|
|
|
@ -6,7 +6,8 @@ let
|
||||||
|
|
||||||
cfg = config.system.custom.x11;
|
cfg = config.system.custom.x11;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
options.system.custom.x11 = {
|
options.system.custom.x11 = {
|
||||||
enable = mkEnableOption "enable x11";
|
enable = mkEnableOption "enable x11";
|
||||||
|
|
|
@ -12,7 +12,8 @@ let
|
||||||
|
|
||||||
# function call
|
# function call
|
||||||
# -------------
|
# -------------
|
||||||
in (pkgs.buildFHSUserEnv {
|
in
|
||||||
|
(pkgs.buildFHSUserEnv {
|
||||||
|
|
||||||
# name of the programm
|
# name of the programm
|
||||||
# --------------------
|
# --------------------
|
||||||
|
|
|
@ -1,6 +1,27 @@
|
||||||
{ stdenv, fetchurl, alsaLib, bzip2, cairo, dpkg, freetype, gdk_pixbuf, glib
|
{ stdenv
|
||||||
, gtk2, harfbuzz, jdk, lib, xorg, libbsd, libjack2, libpng, libxkbcommon
|
, fetchurl
|
||||||
, makeWrapper, pixman, xdg_utils, zenity, zlib }:
|
, alsaLib
|
||||||
|
, bzip2
|
||||||
|
, cairo
|
||||||
|
, dpkg
|
||||||
|
, freetype
|
||||||
|
, gdk_pixbuf
|
||||||
|
, glib
|
||||||
|
, gtk2
|
||||||
|
, harfbuzz
|
||||||
|
, jdk
|
||||||
|
, lib
|
||||||
|
, xorg
|
||||||
|
, libbsd
|
||||||
|
, libjack2
|
||||||
|
, libpng
|
||||||
|
, libxkbcommon
|
||||||
|
, makeWrapper
|
||||||
|
, pixman
|
||||||
|
, xdg_utils
|
||||||
|
, zenity
|
||||||
|
, zlib
|
||||||
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
name = "bitwig-studio-${version}";
|
name = "bitwig-studio-${version}";
|
||||||
|
|
|
@ -40,9 +40,10 @@ let
|
||||||
Yᵒᵘ Oᶰˡʸ Lᶤᵛᵉ Oᶰᶜᵉ | yolo
|
Yᵒᵘ Oᶰˡʸ Lᶤᵛᵉ Oᶰᶜᵉ | yolo
|
||||||
⊹╰(⌣ʟ⌣)╯⊹ | zen
|
⊹╰(⌣ʟ⌣)╯⊹ | zen
|
||||||
@}-,-`- | rose
|
@}-,-`- | rose
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in writeShellScriptBin "emoticons" ''
|
in
|
||||||
|
writeShellScriptBin "emoticons" ''
|
||||||
set -efu
|
set -efu
|
||||||
|
|
||||||
data=$(${coreutils}/bin/cat ${emoticons})
|
data=$(${coreutils}/bin/cat ${emoticons})
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
{ pkgs, lib, ... }:
|
{ pkgs, lib, ... }:
|
||||||
|
|
||||||
pkgs.writers.writePython3Bin "gitlog2json" {
|
pkgs.writers.writePython3Bin "gitlog2json"
|
||||||
|
{
|
||||||
libraries = [
|
libraries = [
|
||||||
pkgs.python3Packages.GitPython
|
pkgs.python3Packages.GitPython
|
||||||
pkgs.python3Packages.click
|
pkgs.python3Packages.click
|
||||||
pkgs.python3Packages.elasticsearch
|
pkgs.python3Packages.elasticsearch
|
||||||
];
|
];
|
||||||
} (lib.fileContents ./gitlog2json.py)
|
}
|
||||||
|
(lib.fileContents ./gitlog2json.py)
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
{ lib, writeTextFile, jsonConfig ? { }, title ? "Landing Page"
|
{ lib
|
||||||
, destination ? "/index.html", ... }:
|
, writeTextFile
|
||||||
|
, jsonConfig ? { }
|
||||||
|
, title ? "Landing Page"
|
||||||
|
, destination ? "/index.html"
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
{ lib, symlinkJoin, rofi, gnused, pass-otp, writeTextFile, writeShellScriptBin
|
{ lib
|
||||||
, xdotool }:
|
, symlinkJoin
|
||||||
|
, rofi
|
||||||
|
, gnused
|
||||||
|
, pass-otp
|
||||||
|
, writeTextFile
|
||||||
|
, writeShellScriptBin
|
||||||
|
, xdotool
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|
||||||
|
@ -36,7 +43,8 @@ let
|
||||||
printf %s "$otp" | ${xdotool}/bin/xdotool type -f -
|
printf %s "$otp" | ${xdotool}/bin/xdotool type -f -
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in symlinkJoin rec {
|
in
|
||||||
|
symlinkJoin rec {
|
||||||
version = "1.0.0";
|
version = "1.0.0";
|
||||||
name = "otpMenu-${version}";
|
name = "otpMenu-${version}";
|
||||||
paths = [ bin desktopFile ];
|
paths = [ bin desktopFile ];
|
||||||
|
|
|
@ -1,82 +1,93 @@
|
||||||
{ pkgs, lib
|
{ pkgs
|
||||||
# tzselect is your frind do find timezones
|
, lib
|
||||||
, timeZones ? [ ], timeColor ? 9, timeZoneColor ? 10, calBackgroundColor ? 10
|
# tzselect is your frind do find timezones
|
||||||
, calWeekColor ? 13, calDayColor ? 9, enableIntelBacklight ? true
|
, timeZones ? [ ]
|
||||||
, userHighlight ? [ "palo" ], enableBattery ? true, ... }:
|
, timeColor ? 9
|
||||||
|
, timeZoneColor ? 10
|
||||||
|
, calBackgroundColor ? 10
|
||||||
|
, calWeekColor ? 13
|
||||||
|
, calDayColor ? 9
|
||||||
|
, enableIntelBacklight ? true
|
||||||
|
, userHighlight ? [ "palo" ]
|
||||||
|
, enableBattery ? true
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|
||||||
hrule = "${pkgs.terminal-tools}/bin/hrule";
|
hrule = "${pkgs.terminal-tools}/bin/hrule";
|
||||||
|
|
||||||
q-cal = let
|
q-cal =
|
||||||
|
let
|
||||||
|
|
||||||
# Maximum width of cal's output.
|
# Maximum width of cal's output.
|
||||||
calwidth = 23;
|
calwidth = 23;
|
||||||
|
|
||||||
# Number of space characters between two calendars.
|
# Number of space characters between two calendars.
|
||||||
hspace = 2;
|
hspace = 2;
|
||||||
|
|
||||||
# Return number of columns required to print n calenders side by side.
|
# Return number of columns required to print n calenders side by side.
|
||||||
need_width = n: assert n >= 1; n * calwidth + (n - 1) * hspace;
|
need_width = n: assert n >= 1; n * calwidth + (n - 1) * hspace;
|
||||||
|
|
||||||
lpad = n: c: s: if lib.stringLength s < n then lpad n c (c + s) else s;
|
lpad = n: c: s: if lib.stringLength s < n then lpad n c (c + s) else s;
|
||||||
|
|
||||||
pad = ''
|
pad = ''
|
||||||
{
|
{
|
||||||
${pkgs.gnused}/bin/sed '
|
${pkgs.gnused}/bin/sed '
|
||||||
# rtrim
|
# rtrim
|
||||||
s/ *$//
|
s/ *$//
|
||||||
|
|
||||||
# delete last empty line
|
# delete last empty line
|
||||||
''${/^$/d}
|
''${/^$/d}
|
||||||
|
' \
|
||||||
|
| ${pkgs.gawk}/bin/awk '{printf "%-${
|
||||||
|
toString calwidth
|
||||||
|
}s\n", $0}' \
|
||||||
|
| ${pkgs.gnused}/bin/sed "
|
||||||
|
# colorize header
|
||||||
|
1,2s/.*/[38;5;${toString calBackgroundColor}m&[39;22m/
|
||||||
|
|
||||||
|
# highlight current week
|
||||||
|
s/^$(${pkgs.coreutils}/bin/date +%W)/[38;5;${
|
||||||
|
toString calWeekColor
|
||||||
|
}m&[39;22m/
|
||||||
|
|
||||||
|
# colorize week number
|
||||||
|
s/^[ 1-9][0-9]/[38;5;${
|
||||||
|
toString calBackgroundColor
|
||||||
|
}m&[39;22m/
|
||||||
|
"
|
||||||
|
}'';
|
||||||
|
in
|
||||||
|
''
|
||||||
|
cols=$(${pkgs.ncurses}/bin/tput cols)
|
||||||
|
${pkgs.coreutils}/bin/paste \
|
||||||
|
<(if test $cols -ge ${toString (need_width 3)}; then
|
||||||
|
${pkgs.utillinux}/bin/cal -mw \
|
||||||
|
$(${pkgs.coreutils}/bin/date +'%m %Y' -d 'last month') \
|
||||||
|
| ${pad}
|
||||||
|
fi) \
|
||||||
|
<(if test $cols -ge ${toString (need_width 1)}; then
|
||||||
|
${pkgs.utillinux}/bin/cal -mw \
|
||||||
|
| ${pkgs.gnused}/bin/sed '
|
||||||
|
# colorize day of month
|
||||||
|
s/\(^\| \)'"$(${pkgs.coreutils}/bin/date +%e)"'\>/[38;5;${
|
||||||
|
toString calDayColor
|
||||||
|
}m&[39;22m/
|
||||||
' \
|
' \
|
||||||
| ${pkgs.gawk}/bin/awk '{printf "%-${
|
| ${pad}
|
||||||
toString calwidth
|
fi) \
|
||||||
}s\n", $0}' \
|
<(if test $cols -ge ${toString (need_width 2)}; then
|
||||||
| ${pkgs.gnused}/bin/sed "
|
${pkgs.utillinux}/bin/cal -mw \
|
||||||
# colorize header
|
$(${pkgs.coreutils}/bin/date +'%m %Y' -d 'next month') \
|
||||||
1,2s/.*/[38;5;${toString calBackgroundColor}m&[39;22m/
|
| ${pad}
|
||||||
|
fi) \
|
||||||
# highlight current week
|
| ${pkgs.gnused}/bin/sed '
|
||||||
s/^$(${pkgs.coreutils}/bin/date +%W)/[38;5;${
|
s/^\t//
|
||||||
toString calWeekColor
|
s/\t$//
|
||||||
}m&[39;22m/
|
s/\t/${lpad hspace " " ""}/g
|
||||||
|
'
|
||||||
# colorize week number
|
'';
|
||||||
s/^[ 1-9][0-9]/[38;5;${
|
|
||||||
toString calBackgroundColor
|
|
||||||
}m&[39;22m/
|
|
||||||
"
|
|
||||||
}'';
|
|
||||||
in ''
|
|
||||||
cols=$(${pkgs.ncurses}/bin/tput cols)
|
|
||||||
${pkgs.coreutils}/bin/paste \
|
|
||||||
<(if test $cols -ge ${toString (need_width 3)}; then
|
|
||||||
${pkgs.utillinux}/bin/cal -mw \
|
|
||||||
$(${pkgs.coreutils}/bin/date +'%m %Y' -d 'last month') \
|
|
||||||
| ${pad}
|
|
||||||
fi) \
|
|
||||||
<(if test $cols -ge ${toString (need_width 1)}; then
|
|
||||||
${pkgs.utillinux}/bin/cal -mw \
|
|
||||||
| ${pkgs.gnused}/bin/sed '
|
|
||||||
# colorize day of month
|
|
||||||
s/\(^\| \)'"$(${pkgs.coreutils}/bin/date +%e)"'\>/[38;5;${
|
|
||||||
toString calDayColor
|
|
||||||
}m&[39;22m/
|
|
||||||
' \
|
|
||||||
| ${pad}
|
|
||||||
fi) \
|
|
||||||
<(if test $cols -ge ${toString (need_width 2)}; then
|
|
||||||
${pkgs.utillinux}/bin/cal -mw \
|
|
||||||
$(${pkgs.coreutils}/bin/date +'%m %Y' -d 'next month') \
|
|
||||||
| ${pad}
|
|
||||||
fi) \
|
|
||||||
| ${pkgs.gnused}/bin/sed '
|
|
||||||
s/^\t//
|
|
||||||
s/\t$//
|
|
||||||
s/\t/${lpad hspace " " ""}/g
|
|
||||||
'
|
|
||||||
'';
|
|
||||||
|
|
||||||
q-timeZoneDate = size: zone:
|
q-timeZoneDate = size: zone:
|
||||||
let
|
let
|
||||||
|
@ -88,17 +99,19 @@ let
|
||||||
comment = lib.optionalString (zone != null)
|
comment = lib.optionalString (zone != null)
|
||||||
" : ${lib.fixedWidthString size " " zone}";
|
" : ${lib.fixedWidthString size " " zone}";
|
||||||
# sh
|
# sh
|
||||||
in ''
|
in
|
||||||
|
''
|
||||||
${timeZoneVariable} ${pkgs.coreutils}/bin/date ${
|
${timeZoneVariable} ${pkgs.coreutils}/bin/date ${
|
||||||
dateString comment
|
dateString comment
|
||||||
} | ${pkgs.terminal-tools}/bin/center
|
} | ${pkgs.terminal-tools}/bin/center
|
||||||
'';
|
'';
|
||||||
|
|
||||||
q-timeZoneDates = if timeZones == [ ] then
|
q-timeZoneDates =
|
||||||
q-timeZoneDate 0 null
|
if timeZones == [ ] then
|
||||||
else
|
q-timeZoneDate 0 null
|
||||||
let size = lib.foldr lib.max 0 (map builtins.stringLength timeZones);
|
else
|
||||||
in lib.concatMapStringsSep "\n" (q-timeZoneDate size) timeZones;
|
let size = lib.foldr lib.max 0 (map builtins.stringLength timeZones);
|
||||||
|
in lib.concatMapStringsSep "\n" (q-timeZoneDate size) timeZones;
|
||||||
|
|
||||||
q-intel_backlight = ''
|
q-intel_backlight = ''
|
||||||
cd /sys/class/backlight/intel_backlight
|
cd /sys/class/backlight/intel_backlight
|
||||||
|
@ -116,144 +129,146 @@ let
|
||||||
'
|
'
|
||||||
'';
|
'';
|
||||||
|
|
||||||
q-power_supply = let
|
q-power_supply =
|
||||||
power_supply = pkgs.writers.writeBash "power_supply" ''
|
let
|
||||||
set -efu
|
power_supply = pkgs.writers.writeBash "power_supply" ''
|
||||||
uevent=$1
|
set -efu
|
||||||
eval "$(${pkgs.gnused}/bin/sed -n '
|
uevent=$1
|
||||||
s/^\([A-Z_]\+=[0-9A-Za-z_-]*\)$/export \1/p
|
eval "$(${pkgs.gnused}/bin/sed -n '
|
||||||
' $uevent)"
|
s/^\([A-Z_]\+=[0-9A-Za-z_-]*\)$/export \1/p
|
||||||
case $POWER_SUPPLY_NAME in
|
' $uevent)"
|
||||||
AC)
|
case $POWER_SUPPLY_NAME in
|
||||||
exit # not battery
|
AC)
|
||||||
;;
|
exit # not battery
|
||||||
esac
|
;;
|
||||||
exec </dev/null
|
esac
|
||||||
exec ${pkgs.gawk}/bin/awk '
|
exec </dev/null
|
||||||
function die(s) {
|
exec ${pkgs.gawk}/bin/awk '
|
||||||
printf "%20s │ %s\n", name, s
|
function die(s) {
|
||||||
exit 1
|
printf "%20s │ %s\n", name, s
|
||||||
}
|
exit 1
|
||||||
|
|
||||||
function print_hm(h, m) {
|
|
||||||
m = (h - int(h)) * 60
|
|
||||||
return sprintf("%dh%dm", h, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_bar(bar_size, charge, full_bars, empty_bars, full_color) {
|
|
||||||
full_bars = int(charge * bar_size)
|
|
||||||
empty_bars = bar_size - full_bars
|
|
||||||
|
|
||||||
if (charge >= .42) full_color = "2"
|
|
||||||
else if (charge >= .23) full_color = "3"
|
|
||||||
else full_color = "1"
|
|
||||||
|
|
||||||
left_arrow = 1
|
|
||||||
middle_arrow = 1
|
|
||||||
right_arrow = 1
|
|
||||||
if (full_bars == 0) {
|
|
||||||
left_arrow = 0
|
|
||||||
middle_arrow = 0
|
|
||||||
}
|
|
||||||
if (empty_bars == 0) {
|
|
||||||
middle_arrow = 0
|
|
||||||
right_arrow = 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
empty_color = "0";
|
function print_hm(h, m) {
|
||||||
return sgr("38;5;" 8) sgr("48;5;" full_color) strdup("",left_arrow) strdup(" ", full_bars) sgr("48;5;" empty_color) sgr("38;5;" full_color) strdup("",middle_arrow) strdup(" ", empty_bars) sgr() sgr("38;5;" empty_color) strdup("",right_arrow) sgr()
|
m = (h - int(h)) * 60
|
||||||
}
|
return sprintf("%dh%dm", h, m)
|
||||||
|
|
||||||
function sgr(p) {
|
|
||||||
return "\x1b[" p "m"
|
|
||||||
}
|
|
||||||
|
|
||||||
function strdup(s,n,t) {
|
|
||||||
t = sprintf("%"n"s","")
|
|
||||||
gsub(/ /,s,t)
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
END {
|
|
||||||
name = ENVIRON["POWER_SUPPLY_NAME"]
|
|
||||||
|
|
||||||
charge_unit = "Ah"
|
|
||||||
charge_now = ENVIRON["POWER_SUPPLY_CHARGE_NOW"] / 10^6
|
|
||||||
charge_full = ENVIRON["POWER_SUPPLY_CHARGE_FULL"] / 10^6
|
|
||||||
|
|
||||||
current_unit = "A"
|
|
||||||
current_now = ENVIRON["POWER_SUPPLY_CURRENT_NOW"] / 10^6
|
|
||||||
|
|
||||||
energy_unit = "Wh"
|
|
||||||
energy_now = ENVIRON["POWER_SUPPLY_ENERGY_NOW"] / 10^6
|
|
||||||
energy_full = ENVIRON["POWER_SUPPLY_ENERGY_FULL"] / 10^6
|
|
||||||
|
|
||||||
power_unit = "W"
|
|
||||||
power_now = ENVIRON["POWER_SUPPLY_POWER_NOW"] / 10^6
|
|
||||||
|
|
||||||
voltage_unit = "V"
|
|
||||||
voltage_now = ENVIRON["POWER_SUPPLY_VOLTAGE_NOW"] / 10^6
|
|
||||||
voltage_min_design = ENVIRON["POWER_SUPPLY_VOLTAGE_MIN_DESIGN"] / 10^6
|
|
||||||
|
|
||||||
#printf "charge_now: %s\n", charge_now
|
|
||||||
#printf "charge_full: %s\n", charge_full
|
|
||||||
#printf "current_now: %s\n", current_now
|
|
||||||
#printf "energy_now: %s\n", energy_now
|
|
||||||
#printf "energy_full: %s\n", energy_full
|
|
||||||
#printf "energy_full: %s\n", ENVIRON["POWER_SUPPLY_ENERGY_FULL"]
|
|
||||||
#printf "energy_full: %s\n", ENVIRON["POWER_SUPPLY_ENERGY_FULL"] / 10^6
|
|
||||||
#printf "power_now: %s\n", power_now
|
|
||||||
#printf "voltage_now: %s\n", voltage_now
|
|
||||||
|
|
||||||
if (current_now == 0 && voltage_now != 0) {
|
|
||||||
current_now = power_now / voltage_now
|
|
||||||
}
|
|
||||||
if (power_now == 0) {
|
|
||||||
power_now = current_now * voltage_now
|
|
||||||
}
|
|
||||||
if (charge_now == 0 && voltage_min_design != 0) {
|
|
||||||
charge_now = energy_now / voltage_min_design
|
|
||||||
}
|
|
||||||
if (energy_now == 0) {
|
|
||||||
energy_now = charge_now * voltage_min_design
|
|
||||||
}
|
|
||||||
if (charge_full == 0 && voltage_min_design != 0) {
|
|
||||||
charge_full = energy_full / voltage_min_design
|
|
||||||
}
|
|
||||||
if (energy_full == 0) {
|
|
||||||
energy_full = charge_full * voltage_min_design
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (charge_now == 0 || charge_full == 0) {
|
function print_bar(bar_size, charge, full_bars, empty_bars, full_color) {
|
||||||
die("unknown charge")
|
full_bars = int(charge * bar_size)
|
||||||
|
empty_bars = bar_size - full_bars
|
||||||
|
|
||||||
|
if (charge >= .42) full_color = "2"
|
||||||
|
else if (charge >= .23) full_color = "3"
|
||||||
|
else full_color = "1"
|
||||||
|
|
||||||
|
left_arrow = 1
|
||||||
|
middle_arrow = 1
|
||||||
|
right_arrow = 1
|
||||||
|
if (full_bars == 0) {
|
||||||
|
left_arrow = 0
|
||||||
|
middle_arrow = 0
|
||||||
|
}
|
||||||
|
if (empty_bars == 0) {
|
||||||
|
middle_arrow = 0
|
||||||
|
right_arrow = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
empty_color = "0";
|
||||||
|
return sgr("38;5;" 8) sgr("48;5;" full_color) strdup("",left_arrow) strdup(" ", full_bars) sgr("48;5;" empty_color) sgr("38;5;" full_color) strdup("",middle_arrow) strdup(" ", empty_bars) sgr() sgr("38;5;" empty_color) strdup("",right_arrow) sgr()
|
||||||
}
|
}
|
||||||
|
|
||||||
charge_ratio = charge_now / charge_full
|
function sgr(p) {
|
||||||
|
return "\x1b[" p "m"
|
||||||
out = out sprintf("%20s │", name)
|
|
||||||
out = out sprintf(" %s", print_bar(10, charge_ratio))
|
|
||||||
out = out sprintf(" %d%", charge_ratio * 100)
|
|
||||||
out = out sprintf(" %.2f%s", charge_now, charge_unit)
|
|
||||||
if (current_now != 0) {
|
|
||||||
out = out sprintf("/%.1f%s", current_now, current_unit)
|
|
||||||
}
|
|
||||||
out = out sprintf(" %d%s", energy_full, energy_unit)
|
|
||||||
if (power_now != 0) {
|
|
||||||
out = out sprintf("/%.1f%s", power_now, power_unit)
|
|
||||||
}
|
|
||||||
if (current_now != 0) {
|
|
||||||
out = out sprintf(" %s", print_hm(charge_now / current_now))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print out
|
function strdup(s,n,t) {
|
||||||
}
|
t = sprintf("%"n"s","")
|
||||||
'
|
gsub(/ /,s,t)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
name = ENVIRON["POWER_SUPPLY_NAME"]
|
||||||
|
|
||||||
|
charge_unit = "Ah"
|
||||||
|
charge_now = ENVIRON["POWER_SUPPLY_CHARGE_NOW"] / 10^6
|
||||||
|
charge_full = ENVIRON["POWER_SUPPLY_CHARGE_FULL"] / 10^6
|
||||||
|
|
||||||
|
current_unit = "A"
|
||||||
|
current_now = ENVIRON["POWER_SUPPLY_CURRENT_NOW"] / 10^6
|
||||||
|
|
||||||
|
energy_unit = "Wh"
|
||||||
|
energy_now = ENVIRON["POWER_SUPPLY_ENERGY_NOW"] / 10^6
|
||||||
|
energy_full = ENVIRON["POWER_SUPPLY_ENERGY_FULL"] / 10^6
|
||||||
|
|
||||||
|
power_unit = "W"
|
||||||
|
power_now = ENVIRON["POWER_SUPPLY_POWER_NOW"] / 10^6
|
||||||
|
|
||||||
|
voltage_unit = "V"
|
||||||
|
voltage_now = ENVIRON["POWER_SUPPLY_VOLTAGE_NOW"] / 10^6
|
||||||
|
voltage_min_design = ENVIRON["POWER_SUPPLY_VOLTAGE_MIN_DESIGN"] / 10^6
|
||||||
|
|
||||||
|
#printf "charge_now: %s\n", charge_now
|
||||||
|
#printf "charge_full: %s\n", charge_full
|
||||||
|
#printf "current_now: %s\n", current_now
|
||||||
|
#printf "energy_now: %s\n", energy_now
|
||||||
|
#printf "energy_full: %s\n", energy_full
|
||||||
|
#printf "energy_full: %s\n", ENVIRON["POWER_SUPPLY_ENERGY_FULL"]
|
||||||
|
#printf "energy_full: %s\n", ENVIRON["POWER_SUPPLY_ENERGY_FULL"] / 10^6
|
||||||
|
#printf "power_now: %s\n", power_now
|
||||||
|
#printf "voltage_now: %s\n", voltage_now
|
||||||
|
|
||||||
|
if (current_now == 0 && voltage_now != 0) {
|
||||||
|
current_now = power_now / voltage_now
|
||||||
|
}
|
||||||
|
if (power_now == 0) {
|
||||||
|
power_now = current_now * voltage_now
|
||||||
|
}
|
||||||
|
if (charge_now == 0 && voltage_min_design != 0) {
|
||||||
|
charge_now = energy_now / voltage_min_design
|
||||||
|
}
|
||||||
|
if (energy_now == 0) {
|
||||||
|
energy_now = charge_now * voltage_min_design
|
||||||
|
}
|
||||||
|
if (charge_full == 0 && voltage_min_design != 0) {
|
||||||
|
charge_full = energy_full / voltage_min_design
|
||||||
|
}
|
||||||
|
if (energy_full == 0) {
|
||||||
|
energy_full = charge_full * voltage_min_design
|
||||||
|
}
|
||||||
|
|
||||||
|
if (charge_now == 0 || charge_full == 0) {
|
||||||
|
die("unknown charge")
|
||||||
|
}
|
||||||
|
|
||||||
|
charge_ratio = charge_now / charge_full
|
||||||
|
|
||||||
|
out = out sprintf("%20s │", name)
|
||||||
|
out = out sprintf(" %s", print_bar(10, charge_ratio))
|
||||||
|
out = out sprintf(" %d%", charge_ratio * 100)
|
||||||
|
out = out sprintf(" %.2f%s", charge_now, charge_unit)
|
||||||
|
if (current_now != 0) {
|
||||||
|
out = out sprintf("/%.1f%s", current_now, current_unit)
|
||||||
|
}
|
||||||
|
out = out sprintf(" %d%s", energy_full, energy_unit)
|
||||||
|
if (power_now != 0) {
|
||||||
|
out = out sprintf("/%.1f%s", power_now, power_unit)
|
||||||
|
}
|
||||||
|
if (current_now != 0) {
|
||||||
|
out = out sprintf(" %s", print_hm(charge_now / current_now))
|
||||||
|
}
|
||||||
|
|
||||||
|
print out
|
||||||
|
}
|
||||||
|
'
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
''
|
||||||
|
for uevent in /sys/class/power_supply/*/uevent; do
|
||||||
|
${power_supply} "$uevent" || :
|
||||||
|
done
|
||||||
'';
|
'';
|
||||||
in ''
|
|
||||||
for uevent in /sys/class/power_supply/*/uevent; do
|
|
||||||
${power_supply} "$uevent" || :
|
|
||||||
done
|
|
||||||
'';
|
|
||||||
|
|
||||||
q-virtualization = ''
|
q-virtualization = ''
|
||||||
printf '%20s │ %s\n' "VT" \
|
printf '%20s │ %s\n' "VT" \
|
||||||
|
@ -323,7 +338,8 @@ let
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# bash needed for <(...)
|
# bash needed for <(...)
|
||||||
in pkgs.writers.writeBashBin "q" ''
|
in
|
||||||
|
pkgs.writers.writeBashBin "q" ''
|
||||||
set -eu
|
set -eu
|
||||||
export PATH=/var/empty
|
export PATH=/var/empty
|
||||||
${hrule}
|
${hrule}
|
||||||
|
|
|
@ -32,7 +32,8 @@ let
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
in (pkgs.buildFHSUserEnv {
|
in
|
||||||
|
(pkgs.buildFHSUserEnv {
|
||||||
|
|
||||||
# name it
|
# name it
|
||||||
# -------
|
# -------
|
||||||
|
|
|
@ -32,7 +32,8 @@ let
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
in (pkgs.buildFHSUserEnv {
|
in
|
||||||
|
(pkgs.buildFHSUserEnv {
|
||||||
|
|
||||||
# name it
|
# name it
|
||||||
# -------
|
# -------
|
||||||
|
|
|
@ -20,58 +20,62 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = let
|
config =
|
||||||
|
let
|
||||||
|
|
||||||
servers = [
|
servers = [
|
||||||
{
|
{
|
||||||
name = "workhorse";
|
name = "workhorse";
|
||||||
host = "workhorse.private";
|
host = "workhorse.private";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "pepe";
|
name = "pepe";
|
||||||
host = "pepe.private";
|
host = "pepe.private";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
dirs = config.backup.dirs;
|
dirs = config.backup.dirs;
|
||||||
|
|
||||||
myHostname = config.networking.hostName;
|
myHostname = config.networking.hostName;
|
||||||
|
|
||||||
|
setup = server: {
|
||||||
|
paths = config.backup.dirs;
|
||||||
|
exclude = config.backup.exclude;
|
||||||
|
doInit = true;
|
||||||
|
repo = "borg@${server}:./${myHostname}";
|
||||||
|
encryption = {
|
||||||
|
mode = "repokey-blake2";
|
||||||
|
passCommand =
|
||||||
|
"cat ${config.sops.secrets.backup_repository_passphrase.path}";
|
||||||
|
};
|
||||||
|
environment.BORG_RSH =
|
||||||
|
"ssh -i ${toString config.sops.secrets.backup_ssh_rsa_private.path}";
|
||||||
|
compression = "auto,lzma";
|
||||||
|
startAt = "daily";
|
||||||
|
prune.keep = {
|
||||||
|
within = "10d"; # Keep all backups in the last 10 days.
|
||||||
|
weekly = 8; # Keep 8 additional end of week archives.
|
||||||
|
monthly = -1; # Keep end of month archive for every month
|
||||||
|
};
|
||||||
|
|
||||||
setup = server: {
|
|
||||||
paths = config.backup.dirs;
|
|
||||||
exclude = config.backup.exclude;
|
|
||||||
doInit = true;
|
|
||||||
repo = "borg@${server}:./${myHostname}";
|
|
||||||
encryption = {
|
|
||||||
mode = "repokey-blake2";
|
|
||||||
passCommand =
|
|
||||||
"cat ${config.sops.secrets.backup_repository_passphrase.path}";
|
|
||||||
};
|
|
||||||
environment.BORG_RSH =
|
|
||||||
"ssh -i ${toString config.sops.secrets.backup_ssh_rsa_private.path}";
|
|
||||||
compression = "auto,lzma";
|
|
||||||
startAt = "daily";
|
|
||||||
prune.keep = {
|
|
||||||
within = "10d"; # Keep all backups in the last 10 days.
|
|
||||||
weekly = 8; # Keep 8 additional end of week archives.
|
|
||||||
monthly = -1; # Keep end of month archive for every month
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
sops.secrets.backup_repository_passphrase = { };
|
||||||
|
sops.secrets.backup_ssh_rsa_private = { };
|
||||||
|
|
||||||
|
services.borgbackup.jobs =
|
||||||
|
let
|
||||||
|
setups = map ({ name, host }: { "${name}" = setup host; }) servers;
|
||||||
|
setupAttrs = lib.zipAttrsWith (_: vals: lib.head vals) setups;
|
||||||
|
nonEmptySetups =
|
||||||
|
lib.filterAttrs (_: { paths, ... }: builtins.length paths != 0)
|
||||||
|
setupAttrs;
|
||||||
|
in
|
||||||
|
nonEmptySetups;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
sops.secrets.backup_repository_passphrase = { };
|
|
||||||
sops.secrets.backup_ssh_rsa_private = { };
|
|
||||||
|
|
||||||
services.borgbackup.jobs = let
|
|
||||||
setups = map ({ name, host }: { "${name}" = setup host; }) servers;
|
|
||||||
setupAttrs = lib.zipAttrsWith (_: vals: lib.head vals) setups;
|
|
||||||
nonEmptySetups =
|
|
||||||
lib.filterAttrs (_: { paths, ... }: builtins.length paths != 0)
|
|
||||||
setupAttrs;
|
|
||||||
in nonEmptySetups;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
{ pkgs, lib, ... }: {
|
{ pkgs, lib, ... }: {
|
||||||
|
|
||||||
environment.systemPackages = let
|
environment.systemPackages =
|
||||||
createScript = command: host: repository:
|
let
|
||||||
pkgs.writers.writeBashBin
|
createScript = command: host: repository:
|
||||||
"borg-${command}-on-${host}-for-${repository}" ''
|
pkgs.writers.writeBashBin
|
||||||
${pkgs.borgbackup}/bin/borg \
|
"borg-${command}-on-${host}-for-${repository}" ''
|
||||||
${command} \
|
${pkgs.borgbackup}/bin/borg \
|
||||||
--rsh='ssh -i ~/.ssh/card_rsa.pub' borg@${host}.private:${repository}/. \
|
${command} \
|
||||||
"$@"
|
--rsh='ssh -i ~/.ssh/card_rsa.pub' borg@${host}.private:${repository}/. \
|
||||||
'';
|
"$@"
|
||||||
hosts = [ "workhorse" "pepe" ];
|
'';
|
||||||
repositories = [ "workhorse" "pepe" "sterni" "workout" ];
|
hosts = [ "workhorse" "pepe" ];
|
||||||
commands = [ "list" ];
|
repositories = [ "workhorse" "pepe" "sterni" "workout" ];
|
||||||
in lib.flatten (map (command:
|
commands = [ "list" ];
|
||||||
map
|
in
|
||||||
(host: map (repository: createScript command host repository) repositories)
|
lib.flatten (map
|
||||||
hosts) commands);
|
(command:
|
||||||
|
map
|
||||||
|
(host: map (repository: createScript command host repository) repositories)
|
||||||
|
hosts)
|
||||||
|
commands);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ let
|
||||||
rev = "fe27cbc99e994d50bb4269a9388e3f7d60492ffa";
|
rev = "fe27cbc99e994d50bb4269a9388e3f7d60492ffa";
|
||||||
sha256 = "1z8zc4k2mh8d56ipql8vfljvdjczrrna5ckgzjsdyrndfkwv8ghw";
|
sha256 = "1z8zc4k2mh8d56ipql8vfljvdjczrrna5ckgzjsdyrndfkwv8ghw";
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
boot.loader.grub.extraConfig = ''
|
boot.loader.grub.extraConfig = ''
|
||||||
set theme=($drive1)//themes/fallout-grub-theme/theme.txt
|
set theme=($drive1)//themes/fallout-grub-theme/theme.txt
|
||||||
|
|
|
@ -26,28 +26,30 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = let
|
config =
|
||||||
kbits = number:
|
let
|
||||||
import (pkgs.runCommand "round-${toString number}" { }
|
kbits = number:
|
||||||
''awk 'BEGIN{printf "\"%ikbit\"", ${toString number}}' > $out'');
|
import (pkgs.runCommand "round-${toString number}" { }
|
||||||
|
''awk 'BEGIN{printf "\"%ikbit\"", ${toString number}}' > $out'');
|
||||||
|
|
||||||
interface = config.configuration.fireqos.interface;
|
interface = config.configuration.fireqos.interface;
|
||||||
input = "${toString config.configuration.fireqos.input}kbit";
|
input = "${toString config.configuration.fireqos.input}kbit";
|
||||||
output = "${toString config.configuration.fireqos.output}kbit";
|
output = "${toString config.configuration.fireqos.output}kbit";
|
||||||
tincInput = kbits (config.configuration.fireqos.input * 0.7);
|
tincInput = kbits (config.configuration.fireqos.input * 0.7);
|
||||||
tincOutput = kbits (config.configuration.fireqos.output * 0.7);
|
tincOutput = kbits (config.configuration.fireqos.output * 0.7);
|
||||||
useBalancedForExperimenting = false;
|
useBalancedForExperimenting = false;
|
||||||
|
|
||||||
tincPorts =
|
tincPorts =
|
||||||
lib.mapAttrsToList (name: configuration: toString configuration.port)
|
lib.mapAttrsToList (name: configuration: toString configuration.port)
|
||||||
config.module.cluster.services.tinc;
|
config.module.cluster.services.tinc;
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
# https://firehol.org/tutorial/fireqos-new-user/
|
# https://firehol.org/tutorial/fireqos-new-user/
|
||||||
services.fireqos.enable = config.configuration.fireqos.enable;
|
services.fireqos.enable = config.configuration.fireqos.enable;
|
||||||
systemd.services.fireqos.wantedBy = [ "multi-user.target" ];
|
systemd.services.fireqos.wantedBy = [ "multi-user.target" ];
|
||||||
services.fireqos.config = ''
|
services.fireqos.config = ''
|
||||||
|
|
||||||
# ------------------- world
|
# ------------------- world
|
||||||
|
|
||||||
|
@ -121,6 +123,6 @@
|
||||||
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,28 +228,32 @@
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
text = "Syncthings";
|
text = "Syncthings";
|
||||||
items = map ({ name, host ? "${name}.private", ... }: {
|
items = map
|
||||||
label = name;
|
({ name, host ? "${name}.private", ... }: {
|
||||||
href = "http://${host}:8384/";
|
label = name;
|
||||||
image =
|
href = "http://${host}:8384/";
|
||||||
"https://media.giphy.com/media/JoyU4vuzwj6ZA7Ging/giphy.gif";
|
image =
|
||||||
}) (map (name: { inherit name; }) (lib.attrNames
|
"https://media.giphy.com/media/JoyU4vuzwj6ZA7Ging/giphy.gif";
|
||||||
config.module.cluster.services.tinc."private".hosts));
|
})
|
||||||
|
(map (name: { inherit name; }) (lib.attrNames
|
||||||
|
config.module.cluster.services.tinc."private".hosts));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
text = "netdata";
|
text = "netdata";
|
||||||
items = map ({ name, host ? "${name}.private", ... }: {
|
items = map
|
||||||
label = name;
|
({ name, host ? "${name}.private", ... }: {
|
||||||
href = "http://${host}:19999/";
|
label = name;
|
||||||
image = "https://media.giphy.com/media/BkjdN6MQCDPaw/giphy.gif";
|
href = "http://${host}:19999/";
|
||||||
}) (map (name: { inherit name; }) [
|
image = "https://media.giphy.com/media/BkjdN6MQCDPaw/giphy.gif";
|
||||||
"workhorse"
|
})
|
||||||
"porani"
|
(map (name: { inherit name; }) [
|
||||||
"pepe"
|
"workhorse"
|
||||||
"sputnik"
|
"porani"
|
||||||
]
|
"pepe"
|
||||||
#(lib.attrNames config.module.cluster.services.tinc."private".hosts)
|
"sputnik"
|
||||||
);
|
]
|
||||||
|
#(lib.attrNames config.module.cluster.services.tinc."private".hosts)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
let
|
let
|
||||||
access_log_sink = "workhorse.private:12304";
|
access_log_sink = "workhorse.private:12304";
|
||||||
error_log_sink = "workhorse.private:12305";
|
error_log_sink = "workhorse.private:12305";
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
security.acme.email = "contact@ingolf-wagner.de";
|
security.acme.email = "contact@ingolf-wagner.de";
|
||||||
security.acme.acceptTerms = true;
|
security.acme.acceptTerms = true;
|
||||||
|
|
|
@ -29,14 +29,17 @@ let
|
||||||
EOF
|
EOF
|
||||||
'';
|
'';
|
||||||
|
|
||||||
storepath = let
|
storepath =
|
||||||
dirname = "${pkgs.coreutils-full}/bin/dirname";
|
let
|
||||||
readlink = "${pkgs.coreutils-full}/bin/readlink";
|
dirname = "${pkgs.coreutils-full}/bin/dirname";
|
||||||
in pkgs.writers.writeBashBin "storepath" ''
|
readlink = "${pkgs.coreutils-full}/bin/readlink";
|
||||||
${dirname} $( ${readlink} $( type -p "$1" ) )
|
in
|
||||||
'';
|
pkgs.writers.writeBashBin "storepath" ''
|
||||||
|
${dirname} $( ${readlink} $( type -p "$1" ) )
|
||||||
|
'';
|
||||||
|
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
#imports = [ ./packages/llvm-config-dummy.nix ];
|
#imports = [ ./packages/llvm-config-dummy.nix ];
|
||||||
|
|
||||||
|
|
|
@ -1,41 +1,43 @@
|
||||||
{ pkgs, config, lib, ... }:
|
{ pkgs, config, lib, ... }:
|
||||||
with pkgs.lib; {
|
with pkgs.lib; {
|
||||||
environment.systemPackages = let
|
environment.systemPackages =
|
||||||
llvm = pkgs.llvm;
|
let
|
||||||
llvm-config = pkgs.writers.writeBashBin "llvm-config" ''
|
llvm = pkgs.llvm;
|
||||||
while [[ $# -gt 0 ]]; do
|
llvm-config = pkgs.writers.writeBashBin "llvm-config" ''
|
||||||
arg="$1"
|
while [[ $# -gt 0 ]]; do
|
||||||
case $arg in
|
arg="$1"
|
||||||
--assertion-mode)
|
case $arg in
|
||||||
echo "OFF"
|
--assertion-mode)
|
||||||
;;
|
echo "OFF"
|
||||||
--bindir)
|
;;
|
||||||
echo "${getBin llvm}/bin"
|
--bindir)
|
||||||
;;
|
echo "${getBin llvm}/bin"
|
||||||
--libdir)
|
;;
|
||||||
echo "${getLib llvm}/lib"
|
--libdir)
|
||||||
;;
|
echo "${getLib llvm}/lib"
|
||||||
--includedir)
|
;;
|
||||||
echo "${getDev llvm}/include"
|
--includedir)
|
||||||
;;
|
echo "${getDev llvm}/include"
|
||||||
--prefix)
|
;;
|
||||||
echo "${llvm.out}"
|
--prefix)
|
||||||
;;
|
echo "${llvm.out}"
|
||||||
--src-root)
|
;;
|
||||||
echo "/build/llvm";
|
--src-root)
|
||||||
;;
|
echo "/build/llvm";
|
||||||
--obj-root)
|
;;
|
||||||
echo "/build/llvm/build";
|
--obj-root)
|
||||||
;;
|
echo "/build/llvm/build";
|
||||||
--cmakedir)
|
;;
|
||||||
echo "${getDev llvm}/lib/cmake/llvm"
|
--cmakedir)
|
||||||
;;
|
echo "${getDev llvm}/lib/cmake/llvm"
|
||||||
*)
|
;;
|
||||||
echo "Unhandled argument '$arg' passed to dummy llvm-config!"
|
*)
|
||||||
exit 1
|
echo "Unhandled argument '$arg' passed to dummy llvm-config!"
|
||||||
esac
|
exit 1
|
||||||
shift
|
esac
|
||||||
done
|
shift
|
||||||
'';
|
done
|
||||||
in [ llvm-config ];
|
'';
|
||||||
|
in
|
||||||
|
[ llvm-config ];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,2 @@
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
{
|
{ }
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue