Merge branch 'feature/flakes'
This commit is contained in:
commit
6dc18d06e1
298 changed files with 5865 additions and 4682 deletions
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"url": "https://github.com/NixOS/nixpkgs.git",
|
|
||||||
"rev": "6bfe71f2a4e2e425dee26b25d2309f341ff1600d",
|
|
||||||
"date": "2021-09-02T17:55:10+02:00",
|
|
||||||
"path": "/nix/store/wmg7a97b7ql8kj413wkvh2pmvl5m4nkd-nixpkgs",
|
|
||||||
"sha256": "1mpf700fqlzyj6vsy2c329zlgbk9g6giwiyb2g0yhc0a78h72g8l",
|
|
||||||
"fetchSubmodules": false,
|
|
||||||
"deepClone": false,
|
|
||||||
"leaveDotGit": false
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"url": "https://github.com/NixOS/nixpkgs.git",
|
|
||||||
"rev": "a51aa6523bd8ee985bc70987909eff235900197a",
|
|
||||||
"date": "2021-09-04T10:19:48-03:00",
|
|
||||||
"path": "/nix/store/qylkdn96ah6r3mhh5m0p3yv236nxdbsa-nixpkgs",
|
|
||||||
"sha256": "1rpikl60v179gsshqfrr4xwz42db5g87scm2v2hk3v3jys9dqrgc",
|
|
||||||
"fetchSubmodules": false,
|
|
||||||
"deepClone": false,
|
|
||||||
"leaveDotGit": false
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"url": "https://git.ingolf-wagner.de/krebs/krops.git",
|
|
||||||
"rev": "2e93a93ac264a480b427acc2684993476732539d",
|
|
||||||
"date": "2018-09-19T19:57:26+02:00",
|
|
||||||
"sha256": "1s6b2cs60xa270ynhr32qj1rcy3prvf9pidap0qbbvgg008iafxk",
|
|
||||||
"fetchSubmodules": false
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"url": "https://cgit.krebsco.de/nix-writers/",
|
|
||||||
"rev": "fc8a3802a0777a5f43a9a2fe0f5848ecaeb555a1",
|
|
||||||
"date": "2018-10-27T14:45:48+02:00",
|
|
||||||
"path": "/nix/store/81f2li00frwb29kzk7wjw7b87l65s8bg-nix-writers",
|
|
||||||
"sha256": "1iy207rcbz9nv9bf64025ypy38x8mwzl6snbmbrq347h6vvs0ksc",
|
|
||||||
"fetchSubmodules": false,
|
|
||||||
"deepClone": false,
|
|
||||||
"leaveDotGit": false
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"url": "https://github.com/nix-community/nixos-generators.git",
|
|
||||||
"rev": "ef1e4480cf8af45cfdeac597b2f1b1af33923e93",
|
|
||||||
"date": "2019-01-18T10:41:01+01:00",
|
|
||||||
"path": "/nix/store/61wmz4fvlyxnxhw9smkl897rhavj06ry-nixos-generators-ef1e448",
|
|
||||||
"sha256": "0ymzp4pmpkjjjg5h8d45gv8avy4wh1dj0v238i2cz3jp3j489ik9",
|
|
||||||
"fetchSubmodules": false,
|
|
||||||
"deepClone": false,
|
|
||||||
"leaveDotGit": false
|
|
||||||
}
|
|
|
@ -1,228 +0,0 @@
|
||||||
{ pkgs, lib, config, ... }: {
|
|
||||||
|
|
||||||
services.mqtt.light-control.enable = true;
|
|
||||||
services.mqtt.light-control.loglevel = "debug";
|
|
||||||
services.mqtt.light-control.config = {
|
|
||||||
credentials = {
|
|
||||||
host = "tcp://localhost:1883";
|
|
||||||
user = "homeassistant";
|
|
||||||
password = "hallo";
|
|
||||||
};
|
|
||||||
scenes = [
|
|
||||||
{
|
|
||||||
name = "up-dark";
|
|
||||||
ignored_sensors = [
|
|
||||||
"zigbee2mqtt/door_sensor_1"
|
|
||||||
"zigbee2mqtt/door_sensor_4"
|
|
||||||
"zigbee2mqtt/door_sensor_5"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "half";
|
|
||||||
ignored_sensors = [
|
|
||||||
"zigbee2mqtt/door_sensor_1"
|
|
||||||
"zigbee2mqtt/door_sensor_4"
|
|
||||||
"zigbee2mqtt/door_sensor_5"
|
|
||||||
];
|
|
||||||
disabled_switches = [
|
|
||||||
"zigbee2mqtt/led_1"
|
|
||||||
"zigbee2mqtt/led_2"
|
|
||||||
"zigbee2mqtt/light_2"
|
|
||||||
"zigbee2mqtt/light_4"
|
|
||||||
"zigbee2mqtt/light_5"
|
|
||||||
"zigbee2mqtt/light_7"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "down";
|
|
||||||
ignored_sensors = [
|
|
||||||
"zigbee2mqtt/door_sensor_1"
|
|
||||||
"zigbee2mqtt/door_sensor_4"
|
|
||||||
"zigbee2mqtt/door_sensor_5"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "up-bright";
|
|
||||||
disabled_switches = [
|
|
||||||
"zigbee2mqtt/led_1"
|
|
||||||
"zigbee2mqtt/led_2"
|
|
||||||
"zigbee2mqtt/light_2"
|
|
||||||
"zigbee2mqtt/light_4"
|
|
||||||
"zigbee2mqtt/light_5"
|
|
||||||
"zigbee2mqtt/light_7"
|
|
||||||
];
|
|
||||||
ignored_sensors = [ "zigbee2mqtt/door_sensor_4" ];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "outside";
|
|
||||||
room_tracking_enabled = false;
|
|
||||||
ignored_sensors = [ "zigbee2mqtt/door_sensor_4" ];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "night";
|
|
||||||
room_tracking_enabled = false;
|
|
||||||
brightness = 25;
|
|
||||||
ignored_sensors =
|
|
||||||
[ "zigbee2mqtt/motion_sensor_7" "zigbee2mqtt/door_sensor_4" ];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
sensors = let
|
|
||||||
door = { topic, room }: {
|
|
||||||
topic = topic;
|
|
||||||
key = "contact";
|
|
||||||
room = room;
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
light = { topic, rooms, delay ? 0 }: {
|
|
||||||
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 {
|
|
||||||
topic = "zigbee2mqtt/light_2";
|
|
||||||
rooms = [ "office_room" ];
|
|
||||||
})
|
|
||||||
(light {
|
|
||||||
topic = "zigbee2mqtt/light_4";
|
|
||||||
rooms = [ "office_room" ];
|
|
||||||
})
|
|
||||||
(light {
|
|
||||||
topic = "zigbee2mqtt/light_5";
|
|
||||||
rooms = [ "storage_room" ];
|
|
||||||
})
|
|
||||||
(light {
|
|
||||||
topic = "zigbee2mqtt/light_7";
|
|
||||||
rooms = [ "sleeping_room" ];
|
|
||||||
})
|
|
||||||
(led {
|
|
||||||
topic = "zigbee2mqtt/led_1";
|
|
||||||
rooms = [ "office_room" ];
|
|
||||||
})
|
|
||||||
(led {
|
|
||||||
topic = "zigbee2mqtt/led_2";
|
|
||||||
rooms = [ "kitchen" ];
|
|
||||||
})
|
|
||||||
|
|
||||||
#(sonoff {
|
|
||||||
# id = "PAL01";
|
|
||||||
# rooms = [ "bed_room" ];
|
|
||||||
#})
|
|
||||||
#(sonoff {
|
|
||||||
# id = "PAL03";
|
|
||||||
# rooms = [ "living_room" ];
|
|
||||||
#})
|
|
||||||
#(sonoff {
|
|
||||||
# id = "PAL04";
|
|
||||||
# rooms = [ "bed_room" ];
|
|
||||||
#})
|
|
||||||
#(sonoff {
|
|
||||||
# id = "PAL06";
|
|
||||||
# rooms = [ "kitchen" ];
|
|
||||||
#})
|
|
||||||
## monitor and speakers
|
|
||||||
#(sonoff {
|
|
||||||
# id = "PAL07";
|
|
||||||
# rooms = [ "bed_room" ];
|
|
||||||
# delay = 180;
|
|
||||||
#})
|
|
||||||
#(sonoff {
|
|
||||||
# id = "PAL08";
|
|
||||||
# rooms = [ "bed_room" ];
|
|
||||||
# delay = 180;
|
|
||||||
#})
|
|
||||||
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,173 +0,0 @@
|
||||||
{ lib, config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
folderPath = config.services.home-assistant.configDir;
|
|
||||||
|
|
||||||
# find symbols with
|
|
||||||
# https://www.alphavantage.co/query?function=SYMBOL_SEARCH&keywords=<keywords>&apikey=<api_key>
|
|
||||||
# as described here : https://www.alphavantage.co/documentation/#symbolsearch
|
|
||||||
#
|
|
||||||
# example:
|
|
||||||
# --------
|
|
||||||
# stocks = [
|
|
||||||
# {
|
|
||||||
# symbol = "GOOGL";
|
|
||||||
# name = "google";
|
|
||||||
# friendly_name = "Google";
|
|
||||||
# currency = "$";
|
|
||||||
# # I own 50 and bought at a price of 1000
|
|
||||||
# own = {
|
|
||||||
# pieces = 50;
|
|
||||||
# price = 1000;
|
|
||||||
# };
|
|
||||||
# }
|
|
||||||
# ];
|
|
||||||
stocks = import <secrets/home-assistant/stocks>;
|
|
||||||
filePath = name: "${folderPath}/stock_${name}.json";
|
|
||||||
|
|
||||||
cleanup_list = list: lib.filter (entry: entry != { }) (lib.flatten list);
|
|
||||||
|
|
||||||
in {
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
sensor = cleanup_list (map ({ name, currency, own ? { }, ... }: [
|
|
||||||
{
|
|
||||||
platform = "file";
|
|
||||||
name = "stock_${name}";
|
|
||||||
file_path = filePath name;
|
|
||||||
value_template = "{{ value_json.price}} ${currency}";
|
|
||||||
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "file";
|
|
||||||
name = "stock_${name}_change";
|
|
||||||
file_path = filePath name;
|
|
||||||
value_template = "{{ value_json.change}} ${currency}";
|
|
||||||
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "file";
|
|
||||||
name = "stock_${name}_change_percent";
|
|
||||||
file_path = filePath name;
|
|
||||||
value_template = "{{ value_json.change_percent}} %";
|
|
||||||
}
|
|
||||||
(lib.optionalAttrs (own != { }) {
|
|
||||||
platform = "file";
|
|
||||||
name = "stock_${name}_profit";
|
|
||||||
file_path = filePath name;
|
|
||||||
value_template = ''
|
|
||||||
{{ "{:,.2f}".format( value_json.price * ${toString own.pieces} - ${
|
|
||||||
toString (own.pieces * own.price)
|
|
||||||
} ) }} ${currency}'';
|
|
||||||
})
|
|
||||||
]) stocks);
|
|
||||||
|
|
||||||
homeassistant = {
|
|
||||||
whitelist_external_dirs = [ folderPath ];
|
|
||||||
customize = builtins.listToAttrs (cleanup_list (map
|
|
||||||
({ name, own ? { }, ... }: [
|
|
||||||
{
|
|
||||||
name = "sensor.stock_${name}";
|
|
||||||
value = {
|
|
||||||
icon = "mdi:cash-usd-outline";
|
|
||||||
friendly_name = "Price";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "sensor.stock_${name}_change";
|
|
||||||
value = {
|
|
||||||
icon = "mdi:radar";
|
|
||||||
friendly_name = "Difference";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "sensor.stock_${name}_change_percent";
|
|
||||||
value = {
|
|
||||||
icon = "mdi:radar";
|
|
||||||
friendly_name = "Percent";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
(lib.optionalAttrs (own != { }) {
|
|
||||||
name = "sensor.stock_${name}_profit";
|
|
||||||
value = {
|
|
||||||
icon = "mdi:radar";
|
|
||||||
friendly_name = "Profit";
|
|
||||||
};
|
|
||||||
})
|
|
||||||
]) stocks));
|
|
||||||
};
|
|
||||||
|
|
||||||
group = (builtins.listToAttrs (map
|
|
||||||
({ name, friendly_name, own ? { }, ... }: {
|
|
||||||
name = "stock_${name}";
|
|
||||||
value = {
|
|
||||||
name = "${friendly_name} Aktie";
|
|
||||||
entities = [
|
|
||||||
"sensor.stock_${name}"
|
|
||||||
"sensor.stock_${name}_change"
|
|
||||||
"sensor.stock_${name}_change_percent"
|
|
||||||
] ++ (lib.optional (own != { }) "sensor.stock_${name}_profit");
|
|
||||||
};
|
|
||||||
}) stocks));
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services = let
|
|
||||||
pullService = { name, symbol, currency, ... }: {
|
|
||||||
name = "pull_stock_${name}";
|
|
||||||
value = {
|
|
||||||
enable = true;
|
|
||||||
before = [ "home-assistant.service" ];
|
|
||||||
wantedBy = [ "home-assistant.service" ];
|
|
||||||
serviceConfig = {
|
|
||||||
User = "hass";
|
|
||||||
Type = "oneshot";
|
|
||||||
};
|
|
||||||
description = "pull stock_${name} for homeassistant";
|
|
||||||
script = ''
|
|
||||||
SYMBOL="${symbol}"
|
|
||||||
CURRENCY="${currency}"
|
|
||||||
APIKEY=${
|
|
||||||
lib.fileContents <secrets/home-assistant/alphavantage/apikey>
|
|
||||||
}
|
|
||||||
|
|
||||||
${pkgs.curl}/bin/curl --location --silent \
|
|
||||||
"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=$SYMBOL&apikey=$APIKEY" \
|
|
||||||
| ${pkgs.jq}/bin/jq --compact-output \
|
|
||||||
'.["Global Quote"] |
|
|
||||||
{
|
|
||||||
price: .["05. price"] | tonumber,
|
|
||||||
currency: "'$CURRENCY'",
|
|
||||||
change_percent: .["10. change percent"] | .[0:-1] | tonumber,
|
|
||||||
change: .["09. change"] | tonumber,
|
|
||||||
last_date: .["07. latest trading day"],
|
|
||||||
}' \
|
|
||||||
>> ${filePath name}
|
|
||||||
|
|
||||||
# old and stupid
|
|
||||||
#${pkgs.curl}/bin/curl --location --silent \
|
|
||||||
#"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=$SYMBOL&interval=5min&apikey=$APIKEY" \
|
|
||||||
#| ${pkgs.jq}/bin/jq --compact-output \
|
|
||||||
# '.["Time Series (5min)"] | to_entries | [ .[]
|
|
||||||
# | { date : .key , value : .value["4. close"], currency: "'$CURRENCY'" } ]
|
|
||||||
# | 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 builtins.listToAttrs (map pullTimer stocks);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,226 +0,0 @@
|
||||||
{ pkgs, lib, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
# we create 3 input_boolean which get toggled by the 3 types of buttons pressed.
|
|
||||||
# input_boolean.single_${name} : single click
|
|
||||||
# input_boolean.double_${name} : double click
|
|
||||||
# input_boolean.hold_${name} : hold
|
|
||||||
# if you override these input (via states) you have to create the input yourself
|
|
||||||
|
|
||||||
# https://www.zigbee2mqtt.io/devices/WXKG12LM.html
|
|
||||||
allDevices = {
|
|
||||||
"button_a1" = {
|
|
||||||
id = "0x00158d0002b04f65";
|
|
||||||
#groups = [ "living_room" ];
|
|
||||||
states.single = "input_boolean.situation_toggle";
|
|
||||||
states.hold = "input_boolean.printer_toggle";
|
|
||||||
states.double = "input_boolean.windows_up";
|
|
||||||
};
|
|
||||||
"button_a2" = {
|
|
||||||
id = "0x00158d0002b04f09";
|
|
||||||
#groups = [ "bed_room" ];
|
|
||||||
states.single = "input_boolean.situation_toggle";
|
|
||||||
states.hold = "input_boolean.printer_toggle";
|
|
||||||
states.double = "input_boolean.windows_up";
|
|
||||||
};
|
|
||||||
"button_a3" = {
|
|
||||||
id = "0x00158d0002b00e04";
|
|
||||||
#groups = [ "bed_room" ];
|
|
||||||
states.single = "input_boolean.situation_toggle";
|
|
||||||
states.hold = "input_boolean.printer_toggle";
|
|
||||||
states.double = "input_boolean.windows_up";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
|
||||||
{ id, ... }: {
|
|
||||||
name = id;
|
|
||||||
value = {
|
|
||||||
retain = false;
|
|
||||||
friendly_name = name;
|
|
||||||
};
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
# define input_boolean
|
|
||||||
# --------------------
|
|
||||||
# which get toggled by the buttons
|
|
||||||
input_boolean = let stripEmpty = lib.filter (a: a != { });
|
|
||||||
in builtins.listToAttrs (stripEmpty (lib.flatten (lib.mapAttrsToList (name:
|
|
||||||
{ states ? { }, ... }: [
|
|
||||||
(lib.optionalAttrs (!lib.hasAttr "single" states) {
|
|
||||||
name = "single_${name}";
|
|
||||||
value = { icon = "mdi:toggle-switch"; };
|
|
||||||
})
|
|
||||||
(lib.optionalAttrs (!lib.hasAttr "double" states) {
|
|
||||||
name = "double_${name}";
|
|
||||||
value = { icon = "mdi:toggle-switch"; };
|
|
||||||
})
|
|
||||||
(lib.optionalAttrs (!lib.hasAttr "hold" states) {
|
|
||||||
name = "hold_${name}";
|
|
||||||
value = { icon = "mdi:toggle-switch"; };
|
|
||||||
})
|
|
||||||
]) allDevices)));
|
|
||||||
|
|
||||||
# define meta information sensors
|
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
|
||||||
{ ... }: [
|
|
||||||
{
|
|
||||||
platform = "mqtt";
|
|
||||||
name = name;
|
|
||||||
icon = "mdi:toggle-switch";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
value_template = "{{ value_json.click }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "battery_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "%";
|
|
||||||
icon = "mdi:battery-10";
|
|
||||||
value_template = "{{ value_json.battery }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "link_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
icon = "mdi:signal";
|
|
||||||
unit_of_measurement = "lqi";
|
|
||||||
value_template = "{{ value_json.linkquality }}";
|
|
||||||
}
|
|
||||||
]) allDevices);
|
|
||||||
|
|
||||||
binary_sensor = lib.mapAttrsToList (name:
|
|
||||||
{ ... }: {
|
|
||||||
name = name;
|
|
||||||
platform = "mqtt";
|
|
||||||
device_class = "motion";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
payload_on = true;
|
|
||||||
payload_off = false;
|
|
||||||
value_template = "{{ value_json.occupancy }}";
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
# create groups
|
|
||||||
# -------------
|
|
||||||
#group = let
|
|
||||||
# # to have nice panels for every device
|
|
||||||
# sensorGroups = lib.mapAttrs (name:
|
|
||||||
# { states ? { }, ... }:
|
|
||||||
# let
|
|
||||||
# entityIds = { single ? "input_boolean.single_${name}"
|
|
||||||
# , double ? "input_boolean.double_${name}"
|
|
||||||
# , hold ? "input_boolean.hold_${name}", ... }: [
|
|
||||||
# single
|
|
||||||
# double
|
|
||||||
# hold
|
|
||||||
# ];
|
|
||||||
# in {
|
|
||||||
# entities = [ "sensor.${name}" ] ++ (entityIds states)
|
|
||||||
# ++ [ "sensor.battery_${name}" "sensor.link_${name}" ];
|
|
||||||
# }) allDevices;
|
|
||||||
# # sort lights into given groups.
|
|
||||||
# sortedInGroups = let
|
|
||||||
# groupEntries = lib.zipAttrs (lib.flatten (lib.mapAttrsToList (name:
|
|
||||||
# { groups ? [ ], states ? { }, ... }:
|
|
||||||
# map (groupName: {
|
|
||||||
# "${groupName}" = if (lib.hasAttr "single" states) then
|
|
||||||
# states.single
|
|
||||||
# else
|
|
||||||
# "input_boolean.single_${name}";
|
|
||||||
# }) groups) allDevices));
|
|
||||||
# in lib.mapAttrs (name: entities: { inherit entities; }) groupEntries;
|
|
||||||
#in sortedInGroups // sensorGroups // {
|
|
||||||
# all_sensors.entities =
|
|
||||||
# lib.mapAttrsToList (name: { ... }: "binary_sensor.${name}") allDevices;
|
|
||||||
#};
|
|
||||||
|
|
||||||
# create automation
|
|
||||||
# -----------------
|
|
||||||
automation = let
|
|
||||||
|
|
||||||
# single click
|
|
||||||
toggle_single_button_input = lib.mapAttrsToList (name:
|
|
||||||
{ states ? { }, ... }:
|
|
||||||
let
|
|
||||||
entityId = if (lib.hasAttr "single" states) then
|
|
||||||
states.single
|
|
||||||
else
|
|
||||||
"input_boolean.single_${name}";
|
|
||||||
in {
|
|
||||||
alias = "toggle single click ${name}";
|
|
||||||
trigger = {
|
|
||||||
platform = "mqtt";
|
|
||||||
topic = "zigbee2mqtt/${name}";
|
|
||||||
};
|
|
||||||
condition = {
|
|
||||||
condition = "template";
|
|
||||||
value_template = ''{{ "single" == trigger.payload_json.click}}'';
|
|
||||||
};
|
|
||||||
action = {
|
|
||||||
service = "input_boolean.toggle";
|
|
||||||
data.entity_id = entityId;
|
|
||||||
};
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
# double click
|
|
||||||
toggle_double_button_input = lib.mapAttrsToList (name:
|
|
||||||
{ states ? { }, ... }:
|
|
||||||
let
|
|
||||||
entityId = if (lib.hasAttr "double" states) then
|
|
||||||
states.double
|
|
||||||
else
|
|
||||||
"input_boolean.double_${name}";
|
|
||||||
in {
|
|
||||||
alias = "toggle double click ${name}";
|
|
||||||
trigger = {
|
|
||||||
platform = "mqtt";
|
|
||||||
topic = "zigbee2mqtt/${name}";
|
|
||||||
};
|
|
||||||
condition = {
|
|
||||||
condition = "template";
|
|
||||||
value_template = ''{{ "double" == trigger.payload_json.click}}'';
|
|
||||||
};
|
|
||||||
action = {
|
|
||||||
service = "input_boolean.toggle";
|
|
||||||
data.entity_id = entityId;
|
|
||||||
};
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
# hold
|
|
||||||
toggle_hold_button_input = lib.mapAttrsToList (name:
|
|
||||||
{ states ? { }, ... }:
|
|
||||||
let
|
|
||||||
entityId = if (lib.hasAttr "hold" states) then
|
|
||||||
states.hold
|
|
||||||
else
|
|
||||||
"input_boolean.hold_${name}";
|
|
||||||
in {
|
|
||||||
alias = "toggle hold ${name}";
|
|
||||||
trigger = {
|
|
||||||
platform = "mqtt";
|
|
||||||
topic = "zigbee2mqtt/${name}";
|
|
||||||
};
|
|
||||||
condition = {
|
|
||||||
condition = "template";
|
|
||||||
value_template = ''{{ "hold" == trigger.payload_json.action}}'';
|
|
||||||
};
|
|
||||||
action = {
|
|
||||||
service = "input_boolean.toggle";
|
|
||||||
data.entity_id = entityId;
|
|
||||||
};
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
in lib.flatten (toggle_single_button_input ++ toggle_double_button_input
|
|
||||||
++ toggle_hold_button_input);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
{ pkgs, lib, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
# https://www.zigbee2mqtt.io/devices/MCCGQ11LM.html
|
|
||||||
allDevices = {
|
|
||||||
"door_sensor_1" = { id = "0x00158d000312dc52"; };
|
|
||||||
"door_sensor_2" = { id = "0x00158d000316d5bf"; };
|
|
||||||
"door_sensor_3" = { id = "0x00158d0002f9516f"; };
|
|
||||||
"door_sensor_4" = { id = "0x00158d00031383b9"; };
|
|
||||||
"door_sensor_5" = { id = "0x00158d0003120d3e"; };
|
|
||||||
};
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
|
||||||
{ id, ... }: {
|
|
||||||
name = id;
|
|
||||||
value = {
|
|
||||||
retain = false;
|
|
||||||
friendly_name = name;
|
|
||||||
};
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
# define meta information sensors
|
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
|
||||||
{ ... }: [
|
|
||||||
{
|
|
||||||
name = "battery_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "%";
|
|
||||||
icon = "mdi:battery-10";
|
|
||||||
value_template = "{{ value_json.battery }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "link_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
icon = "mdi:signal";
|
|
||||||
unit_of_measurement = "lqi";
|
|
||||||
value_template = "{{ value_json.linkquality }}";
|
|
||||||
}
|
|
||||||
]) allDevices);
|
|
||||||
|
|
||||||
binary_sensor = lib.mapAttrsToList (name:
|
|
||||||
{ ... }: {
|
|
||||||
name = name;
|
|
||||||
platform = "mqtt";
|
|
||||||
device_class = "door";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
payload_on = false;
|
|
||||||
payload_off = true;
|
|
||||||
value_template = "{{ value_json.contact}}";
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
# create groups
|
|
||||||
# -------------
|
|
||||||
group = let
|
|
||||||
# to have nice panels for every device
|
|
||||||
sensorGroups = lib.mapAttrs (name:
|
|
||||||
{ ... }: {
|
|
||||||
entities = [
|
|
||||||
"binary_sensor.${name}"
|
|
||||||
"sensor.battery_${name}"
|
|
||||||
"sensor.link_${name}"
|
|
||||||
];
|
|
||||||
}) allDevices;
|
|
||||||
# sort lights into given groups.
|
|
||||||
sortedInGroups = let
|
|
||||||
groupEntries = lib.zipAttrs (lib.flatten (lib.mapAttrsToList (name:
|
|
||||||
{ groups ? [ ], ... }:
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
{ pkgs, lib, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
# https://www.zigbee2mqtt.io/devices/E1757.html
|
|
||||||
allDevices = {
|
|
||||||
"office_fyrtur_1" = { id = "0x680ae2fffe64fa40"; };
|
|
||||||
"office_fyrtur_2" = { id = "0x680ae2fffe91d234"; };
|
|
||||||
"bedroom_fyrtur_1" = { id = "0x680ae2fffe6e9f41"; };
|
|
||||||
"broken_fyrtur_1" = { id = "0x680ae2fffe8f6411"; };
|
|
||||||
};
|
|
||||||
|
|
||||||
# -t "zigbee2mqtt/fyrtur1/set" -m '{"position":100}'
|
|
||||||
# -t "zigbee2mqtt/fyrtur1/set" -m '{"position":15}'
|
|
||||||
in {
|
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
|
||||||
{ id, ... }: {
|
|
||||||
name = id;
|
|
||||||
value = {
|
|
||||||
retain = false;
|
|
||||||
friendly_name = name;
|
|
||||||
transition = 0.1;
|
|
||||||
};
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
|
||||||
{ ... }: [
|
|
||||||
{
|
|
||||||
name = "battery_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "%";
|
|
||||||
icon = "mdi:battery-10";
|
|
||||||
value_template = "{{ value_json.battery }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "link_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
icon = "mdi:signal";
|
|
||||||
unit_of_measurement = "lqi";
|
|
||||||
value_template = "{{ value_json.linkquality }}";
|
|
||||||
}
|
|
||||||
]) allDevices);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
{ pkgs, lib, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
# https://www.zigbee2mqtt.io/devices/SPZB0001.html
|
|
||||||
allDevices = {
|
|
||||||
"office_heater_1" = { id = "0x00158d00032f5ee4"; }; # office
|
|
||||||
"office_heater_2" = { id = "0x00158d00032f5f9f"; }; # office (kitchen)
|
|
||||||
"bedroom_heater_1" = { id = "0x00158d00032f6d1e"; }; # bed room
|
|
||||||
"storage_heater_1" = { id = "0x00158d00032f604d"; }; # abstell raum
|
|
||||||
};
|
|
||||||
|
|
||||||
# -t "zigbee2mqtt/heater3/set" -m '{"system_mode":"auto","current_heating_setpoint":23}'
|
|
||||||
# -t "zigbee2mqtt/heater3/set" -m '{"system_mode":"off"}'
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
|
||||||
{ id, ... }: {
|
|
||||||
name = id;
|
|
||||||
value = {
|
|
||||||
legacy = false;
|
|
||||||
retain = false;
|
|
||||||
friendly_name = name;
|
|
||||||
transition = 1;
|
|
||||||
debounce = 0.5;
|
|
||||||
filtered_attributes = [
|
|
||||||
"battery_low"
|
|
||||||
"eurotronic_host_flags"
|
|
||||||
"eurotronic_system_mode"
|
|
||||||
#"occupied_heating_setpoint"
|
|
||||||
#"pi_heating_demand"
|
|
||||||
#"unoccupied_heating_setpoint"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
|
||||||
{ ... }: [
|
|
||||||
{
|
|
||||||
name = "battery_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "%";
|
|
||||||
icon = "mdi:battery-10";
|
|
||||||
value_template = "{{ value_json.battery }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "link_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
icon = "mdi:signal";
|
|
||||||
unit_of_measurement = "lqi";
|
|
||||||
value_template = "{{ value_json.linkquality }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "mqtt";
|
|
||||||
name = "temperature_${name}";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "°C";
|
|
||||||
device_class = "temperature";
|
|
||||||
value_template = "{{ value_json.local_temperature }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "mqtt";
|
|
||||||
name = "pi_heating_demand_${name}";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "%";
|
|
||||||
value_template = "{{ value_json.pi_heating_demand }}";
|
|
||||||
}
|
|
||||||
]) allDevices);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
{ pkgs, lib, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
# https://www.zigbee2mqtt.io/devices/GL-C-007-1ID.html
|
|
||||||
allDevices = {
|
|
||||||
"led_1" = { id = "0x00124b001f7a5be9"; };
|
|
||||||
"led_2" = { id = "0x00124b001ee958b3"; };
|
|
||||||
};
|
|
||||||
|
|
||||||
# -t "zigbee2mqtt/led_1/set" -m '{"state":"ON","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":"OFF"}'
|
|
||||||
in {
|
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
|
||||||
{ id, ... }: {
|
|
||||||
name = id;
|
|
||||||
value = {
|
|
||||||
retain = false;
|
|
||||||
friendly_name = name;
|
|
||||||
transition = 1;
|
|
||||||
};
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
light = lib.mapAttrsToList (name:
|
|
||||||
{ ... }: {
|
|
||||||
platform = "mqtt";
|
|
||||||
name = name;
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
command_topic = "zigbee2mqtt/${name}/set";
|
|
||||||
value_template = "{{ value_json.click }}";
|
|
||||||
brightness = true;
|
|
||||||
color_temp = true;
|
|
||||||
schema = "json";
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
{ pkgs, lib, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
# https://www.zigbee2mqtt.io/devices/RTCGQ01LM.html
|
|
||||||
allDevices = {
|
|
||||||
|
|
||||||
"motion_sensor_1" = { id = "0x00158d0002fbd451"; };
|
|
||||||
"motion_sensor_2" = { id = "0x00158d0002f9a6b8"; };
|
|
||||||
"motion_sensor_3" = { id = "0x00158d0002f04522"; };
|
|
||||||
"motion_sensor_4" = { id = "0x00158d0002f9a558"; };
|
|
||||||
"motion_sensor_5" = { id = "0x00158d0002f9a56f"; };
|
|
||||||
"motion_sensor_6" = { id = "0x00158d0002f9a5cb"; };
|
|
||||||
"motion_sensor_7" = { id = "0x00158d0002f9a6aa"; };
|
|
||||||
"motion_sensor_8" = { id = "0x00158d0002f04637"; };
|
|
||||||
};
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
|
||||||
{ id, timeout ? 65, ... }: {
|
|
||||||
name = id;
|
|
||||||
value = {
|
|
||||||
retain = false;
|
|
||||||
friendly_name = name;
|
|
||||||
# should not be set below 60 seconds
|
|
||||||
occupancy_timeout = timeout;
|
|
||||||
};
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
# define meta information sensors
|
|
||||||
binary_sensor = lib.flatten (lib.mapAttrsToList (name:
|
|
||||||
{ ... }: [{
|
|
||||||
name = "${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
value_template = "{{ value_json.occupancy }}";
|
|
||||||
#icon = "mdi:battery-10";
|
|
||||||
payload_on = true;
|
|
||||||
payload_off = false;
|
|
||||||
device_class = "motion";
|
|
||||||
}]) allDevices);
|
|
||||||
|
|
||||||
# define meta information sensors
|
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
|
||||||
{ ... }: [
|
|
||||||
{
|
|
||||||
name = "battery_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "%";
|
|
||||||
icon = "mdi:battery-10";
|
|
||||||
value_template = "{{ value_json.battery }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "link_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
icon = "mdi:signal";
|
|
||||||
unit_of_measurement = "lqi";
|
|
||||||
value_template = "{{ value_json.linkquality }}";
|
|
||||||
}
|
|
||||||
]) allDevices);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
{ pkgs, lib, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
# https://www.zigbee2mqtt.io/devices/WSDCGQ11LM.html
|
|
||||||
allDevices = {
|
|
||||||
"temperature_sensor_1" = {
|
|
||||||
id = "0x00158d0002d79220";
|
|
||||||
groups = [ "living_room" ];
|
|
||||||
};
|
|
||||||
"temperature_sensor_2" = {
|
|
||||||
id = "0x00158d0002d7913d";
|
|
||||||
groups = [ "living_room" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
services.zigbee2mqttConfiguration = lib.mapAttrs' (name:
|
|
||||||
{ id, ... }: {
|
|
||||||
name = id;
|
|
||||||
value = {
|
|
||||||
retain = false;
|
|
||||||
friendly_name = name;
|
|
||||||
};
|
|
||||||
}) allDevices;
|
|
||||||
|
|
||||||
services.homeAssistantConfig = {
|
|
||||||
|
|
||||||
# define meta information sensors
|
|
||||||
sensor = lib.flatten (lib.mapAttrsToList (name:
|
|
||||||
{ ... }: [
|
|
||||||
{
|
|
||||||
platform = "mqtt";
|
|
||||||
name = name;
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "°C";
|
|
||||||
device_class = "temperature";
|
|
||||||
value_template = "{{ value_json.temperature }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "mqtt";
|
|
||||||
name = "humidity_${name}";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "%";
|
|
||||||
device_class = "humidity";
|
|
||||||
value_template = "{{ value_json.humidity }}";
|
|
||||||
}
|
|
||||||
#{
|
|
||||||
# platform = "mqtt";
|
|
||||||
# name = "pressure_${name}";
|
|
||||||
# state_topic = "zigbee2mqtt/${name}";
|
|
||||||
# availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
# unit_of_measurement = "hPa";
|
|
||||||
# device_class = "pressure";
|
|
||||||
# value_template = "{{ value_json.pressure }}";
|
|
||||||
#}
|
|
||||||
{
|
|
||||||
name = "battery_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
unit_of_measurement = "%";
|
|
||||||
icon = "mdi:battery-10";
|
|
||||||
value_template = "{{ value_json.battery }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "link_${name}";
|
|
||||||
platform = "mqtt";
|
|
||||||
state_topic = "zigbee2mqtt/${name}";
|
|
||||||
availability_topic = "zigbee2mqtt/bridge/state";
|
|
||||||
icon = "mdi:signal";
|
|
||||||
unit_of_measurement = "lqi";
|
|
||||||
value_template = "{{ value_json.linkquality }}";
|
|
||||||
}
|
|
||||||
]) allDevices);
|
|
||||||
|
|
||||||
# create groups
|
|
||||||
# -------------
|
|
||||||
#group = let
|
|
||||||
# # to have nice panels for every device
|
|
||||||
# sensorGroups = lib.mapAttrs (name:
|
|
||||||
# { ... }: {
|
|
||||||
# entities = [
|
|
||||||
# "sensor.${name}"
|
|
||||||
# "sensor.humidity_${name}"
|
|
||||||
# #"sensor.pressure_${name}"
|
|
||||||
# "sensor.battery_${name}"
|
|
||||||
# "sensor.link_${name}"
|
|
||||||
# ];
|
|
||||||
# }) allDevices;
|
|
||||||
# # sort lights into given groups.
|
|
||||||
# sortedInGroups = let
|
|
||||||
# groupEntries = lib.zipAttrs (lib.flatten (lib.mapAttrsToList (name:
|
|
||||||
# { groups ? [ ], ... }:
|
|
||||||
# map (groupName: { "${groupName}" = "sensor.${name}"; }) groups)
|
|
||||||
# allDevices));
|
|
||||||
# in lib.mapAttrs (name: entities: { inherit entities; }) groupEntries;
|
|
||||||
#in sortedInGroups // sensorGroups // {
|
|
||||||
# all_sensors.entities =
|
|
||||||
# lib.mapAttrsToList (name: { ... }: "sensor.${name}") allDevices;
|
|
||||||
#};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
{ config, pkgs, lib, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
let port = 8000;
|
|
||||||
in {
|
|
||||||
|
|
||||||
# configure nginx
|
|
||||||
services.nginx = {
|
|
||||||
enable = true;
|
|
||||||
virtualHosts = {
|
|
||||||
"paste.workhorse.private" = {
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://localhost:${toString port}";
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_set_header Host $host:$server_port;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_read_timeout 90;
|
|
||||||
proxy_redirect http://localhost:${
|
|
||||||
toString port
|
|
||||||
} https://paste.workhorse.private/;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
krops.userKeys."bepasty" = {
|
|
||||||
user = "bepasty";
|
|
||||||
source = toString <secrets/bepasty-secret-key>;
|
|
||||||
requiredBy = [ "bepasty-server-ingolf-wagner.de-gunicorn.service" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.bepasty = {
|
|
||||||
enable = true;
|
|
||||||
servers."ingolf-wagner.de" = {
|
|
||||||
bind = "0.0.0.0:${toString port}";
|
|
||||||
secretKeyFile = config.krops.userKeys."bepasty".target;
|
|
||||||
extraConfig = ''
|
|
||||||
PERMISSIONS = {
|
|
||||||
'${
|
|
||||||
lib.fileContents <common_secrets/bepasty/admin-password>
|
|
||||||
}': 'admin,list,create,read,delete',
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,199 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
|
|
||||||
library = import <library> { inherit pkgs lib; };
|
|
||||||
|
|
||||||
sync-repo = library.jenkins.syncJob;
|
|
||||||
job = library.jenkins.job;
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.cabal-install ];
|
|
||||||
|
|
||||||
services.nginx = {
|
|
||||||
enable = true;
|
|
||||||
virtualHosts = {
|
|
||||||
"jenkins.${config.networking.hostName}.private" = {
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass =
|
|
||||||
"http://localhost:${toString config.services.jenkins.port}";
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_set_header Host $host:$server_port;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
proxy_read_timeout 90;
|
|
||||||
proxy_redirect http://localhost:${
|
|
||||||
toString config.services.jenkins.port
|
|
||||||
} https://jenkins.${config.networking.hostName}.private/;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
krops.userKeys."accessToken" = {
|
|
||||||
user = "jenkins";
|
|
||||||
source = toString <secrets/jenkins/accessToken>;
|
|
||||||
requiredBy = [ "jenkins-job-builder.service" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.jenkins = {
|
|
||||||
enable = true;
|
|
||||||
home = "/home/jenkins";
|
|
||||||
port = 10420;
|
|
||||||
|
|
||||||
# Plugins to Install:
|
|
||||||
# - all the plugins recommended at the setup
|
|
||||||
# - Build pipeline
|
|
||||||
# - SSH Agent
|
|
||||||
# - mattermost plugin
|
|
||||||
jobBuilder = {
|
|
||||||
enable = true;
|
|
||||||
|
|
||||||
# create an access token in the admin users panel
|
|
||||||
accessTokenFile = config.krops.userKeys."accessToken".target;
|
|
||||||
accessUser = "admin";
|
|
||||||
|
|
||||||
# https://docs.openstack.org/infra/jenkins-job-builder/definition.html#modules
|
|
||||||
nixJobs = let
|
|
||||||
# ssh username + key
|
|
||||||
gogs-id = "bc584c99-0fb7-43fb-af75-4076d64c51b2";
|
|
||||||
# ssh username + key
|
|
||||||
github-id = "bc584c99-0fb7-43fb-af75-4076d64c51b2";
|
|
||||||
# ssh username + key
|
|
||||||
sshSputnik = "d91eb57c-5bff-434c-b317-68aad46848d7";
|
|
||||||
|
|
||||||
sync-to-github = name: source: target:
|
|
||||||
sync-repo name {
|
|
||||||
url = source;
|
|
||||||
credentialsId = gogs-id;
|
|
||||||
} {
|
|
||||||
url = target;
|
|
||||||
credentialsId = github-id;
|
|
||||||
};
|
|
||||||
|
|
||||||
in [
|
|
||||||
|
|
||||||
(job "sync-retiolum" {
|
|
||||||
url = "git@github.com:krebs/retiolum.git";
|
|
||||||
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" {
|
|
||||||
url = "ssh://gogs@workhorse.private:2222/palo/taskninja.git";
|
|
||||||
credentialsId = gogs-id;
|
|
||||||
} [
|
|
||||||
{
|
|
||||||
"Create Shell" = [
|
|
||||||
''
|
|
||||||
nix-shell -p cabal2nix --run "cabal2nix --shell file://. > jenkins.nix"''
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{ Update = [ ''nix-shell ./jenkins.nix --run "cabal update"'' ]; }
|
|
||||||
{
|
|
||||||
Configure = [
|
|
||||||
''nix-shell ./jenkins.nix --run "cabal configure --enable-tests"''
|
|
||||||
''
|
|
||||||
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"'' ]; }
|
|
||||||
])
|
|
||||||
|
|
||||||
# sync to github
|
|
||||||
# --------------
|
|
||||||
(sync-to-github "sync-radiodj"
|
|
||||||
"ssh://gogs@workhorse.private:2222/crashburn_radio/radio-dj2.git"
|
|
||||||
"git@github.com:crashburn-radio/radio-dj.git")
|
|
||||||
(sync-to-github "sync-radiodj-tracks"
|
|
||||||
"ssh://gogs@workhorse.private:2222/crashburn_radio/radio-dj-tracks.git"
|
|
||||||
"git@github.com:crashburn-radio/radio-dj-tracks.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-krops-module"
|
|
||||||
"ssh://gogs@workhorse.private:2222/nix-modules/krops.git"
|
|
||||||
"git@github.com:mrVanDalo/module.krops.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-cluster-module"
|
|
||||||
"ssh://gogs@workhorse.private:2222/nix-modules/cluster.git"
|
|
||||||
"git@github.com:mrVanDalo/module.cluster.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-backup-module"
|
|
||||||
"ssh://gogs@workhorse.private:2222/nix-modules/backup.git"
|
|
||||||
"git@github.com:mrVanDalo/module.backup.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-module-tinc"
|
|
||||||
"ssh://gogs@workhorse.private:2222/palo/nixos-tinc.git"
|
|
||||||
"git@github.com:mrVanDalo/nixos-tinc.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-memo"
|
|
||||||
"ssh://gogs@workhorse.private:2222/palo/memo.git"
|
|
||||||
"git@github.com:mrVanDalo/memo.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-diagrams-template"
|
|
||||||
"ssh://gogs@workhorse.private:2222/palo/diagrams-template.git"
|
|
||||||
"git@github.com:mrVanDalo/diagrams.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-plops"
|
|
||||||
"ssh://gogs@workhorse.private:2222/palo/plops.git"
|
|
||||||
"git@github.com:mrVanDalo/plops.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-image-generator"
|
|
||||||
"ssh://gogs@workhorse.private:2222/palo/image-generator2.git"
|
|
||||||
"git@github.com:mrVanDalo/image-generator.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-image-generator-lib"
|
|
||||||
"ssh://gogs@workhorse.private:2222/palo/image-generator-lib.git"
|
|
||||||
"git@github.com:mrVanDalo/image-generator-examples.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-tech.ingolf-wagner.de"
|
|
||||||
"ssh://gogs@workhorse.private:2222/palo/tech.ingolf-wagner.de.git"
|
|
||||||
"git@github.com:mrVanDalo/tech.ingolf-wagner.de.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-LineageOS-build"
|
|
||||||
"ssh://gogs@git.ingolf-wagner.de:443/palo/LineagoOS-build.git"
|
|
||||||
"git@github.com:mrVanDalo/LineagoOS-build.git")
|
|
||||||
|
|
||||||
(sync-to-github "sync-http-errors"
|
|
||||||
"ssh://gogs@git.ingolf-wagner.de:443/palo/http-errors.git"
|
|
||||||
"git@github.com:mrVanDalo/http-errors.git")
|
|
||||||
(sync-to-github "sync-light-control"
|
|
||||||
"ssh://gogs@git.ingolf-wagner.de:443/palo/light-control.git"
|
|
||||||
"git@github.com:mrVanDalo/light-control.git")
|
|
||||||
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,135 +0,0 @@
|
||||||
{ pkgs, lib, ... }:
|
|
||||||
let
|
|
||||||
|
|
||||||
hostAddress = "192.168.100.20";
|
|
||||||
containerAddress = "192.168.100.21";
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
# backup mattermost
|
|
||||||
backup.dirs = [ "/home/mattermost" ];
|
|
||||||
|
|
||||||
containers.mattermost = {
|
|
||||||
|
|
||||||
# mount host folders
|
|
||||||
bindMounts = {
|
|
||||||
home = {
|
|
||||||
# make sure this folder exist on the host
|
|
||||||
hostPath = toString "/home/mattermost/home";
|
|
||||||
mountPoint = "/var/lib/mattermost";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
db = {
|
|
||||||
# make sure this folder exist on the host
|
|
||||||
hostPath = toString "/home/mattermost/db";
|
|
||||||
mountPoint = "/var/lib/postgresql";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# container network setup
|
|
||||||
# see also nating on host system.
|
|
||||||
privateNetwork = true;
|
|
||||||
hostAddress = hostAddress;
|
|
||||||
localAddress = containerAddress;
|
|
||||||
|
|
||||||
autoStart = true;
|
|
||||||
|
|
||||||
config = { config, pkgs, lib, ... }: {
|
|
||||||
|
|
||||||
imports = [ <modules> <krops-lib> ];
|
|
||||||
|
|
||||||
services.nginx = {
|
|
||||||
|
|
||||||
# Use recommended settings
|
|
||||||
recommendedGzipSettings = lib.mkDefault true;
|
|
||||||
recommendedOptimisation = lib.mkDefault true;
|
|
||||||
recommendedProxySettings = lib.mkDefault true;
|
|
||||||
recommendedTlsSettings = lib.mkDefault true;
|
|
||||||
|
|
||||||
# for graylog logging
|
|
||||||
commonHttpConfig = let
|
|
||||||
access_log_sink = "${hostAddress}:12304";
|
|
||||||
error_log_sink = "${hostAddress}:12305";
|
|
||||||
in ''
|
|
||||||
log_format graylog2_json escape=json '{ "timestamp": "$time_iso8601", '
|
|
||||||
'"facility": "nginx", '
|
|
||||||
'"src_addr": "$remote_addr", '
|
|
||||||
'"body_bytes_sent": $body_bytes_sent, '
|
|
||||||
'"request_time": $request_time, '
|
|
||||||
'"response_status": $status, '
|
|
||||||
'"request": "$request", '
|
|
||||||
'"request_method": "$request_method", '
|
|
||||||
'"host": "$host",'
|
|
||||||
'"upstream_cache_status": "$upstream_cache_status",'
|
|
||||||
'"upstream_addr": "$upstream_addr",'
|
|
||||||
'"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;
|
|
||||||
error_log syslog:server=${error_log_sink};
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ 8065 6667 ];
|
|
||||||
networking.firewall.allowedUDPPorts = [ 8065 ];
|
|
||||||
|
|
||||||
# setup matter most
|
|
||||||
services.mattermost = {
|
|
||||||
enable = true;
|
|
||||||
siteUrl = "https://chat.ingolf-wagner.de";
|
|
||||||
localDatabaseName = "chat";
|
|
||||||
localDatabaseUser = "chatty";
|
|
||||||
listenAddress = ":8065";
|
|
||||||
|
|
||||||
matterircd = {
|
|
||||||
enable = true;
|
|
||||||
parameters = [
|
|
||||||
"-mmserver chat.ingolf-wagner.de"
|
|
||||||
"-restrict chat.ingolf-wagner.de"
|
|
||||||
"-bind [::]:6667"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# send log to host systems graylog (use tinc or wireguard if host is not graylog)
|
|
||||||
services.SystemdJournal2Gelf.enable = true;
|
|
||||||
services.SystemdJournal2Gelf.graylogServer = "${hostAddress}:11201";
|
|
||||||
|
|
||||||
services.journald.extraConfig = "SystemMaxUse=1G";
|
|
||||||
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# give containers internet access
|
|
||||||
networking.nat.enable = true;
|
|
||||||
networking.nat.internalInterfaces = [ "ve-mattermost" ];
|
|
||||||
networking.nat.externalInterface = "enp2s0f1";
|
|
||||||
|
|
||||||
# don't let networkmanager manger container network
|
|
||||||
networking.networkmanager.unmanaged = [ "interface-name:ve-*" ];
|
|
||||||
|
|
||||||
# open ports for logging
|
|
||||||
networking.firewall.interfaces."ve-mattermost".allowedTCPPorts =
|
|
||||||
[ 11201 12304 12305 ];
|
|
||||||
networking.firewall.interfaces."ve-mattermost".allowedUDPPorts =
|
|
||||||
[ 11201 12304 12305 ];
|
|
||||||
|
|
||||||
# host nginx setup
|
|
||||||
services.nginx = {
|
|
||||||
enable = true;
|
|
||||||
recommendedProxySettings = true;
|
|
||||||
virtualHosts = {
|
|
||||||
"chat.workhorse.private" = {
|
|
||||||
serverAliases = [ "chat.ingolf-wagner.de" ];
|
|
||||||
locations."/" = {
|
|
||||||
proxyWebsockets = true;
|
|
||||||
proxyPass = "http://${containerAddress}:8065";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
{ config, pkgs, ... }:
|
|
||||||
let unstable = import <nixpkgs-unstable> { };
|
|
||||||
in { environment.systemPackages = with pkgs; [ ]; }
|
|
77
flake.lock
Normal file
77
flake.lock
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1597053966,
|
||||||
|
"narHash": "sha256-f9lbPS/GJ1His8fsDqM6gfa8kSqREU4eKiMCS5hrKg4=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "ec20f52e2ff61e9c36c2b894b62fc1b4bd04c71b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"krops": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1632420452,
|
||||||
|
"narHash": "sha256-ncK6vABW/Ku9XI0kqj1otarUfblryoQzSaOCnaZ0oSs=",
|
||||||
|
"owner": "Mic92",
|
||||||
|
"repo": "krops",
|
||||||
|
"rev": "0388970c568905fedcbf429e5745aacd4f7a6633",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "Mic92",
|
||||||
|
"repo": "krops",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1635070614,
|
||||||
|
"narHash": "sha256-eRup9WsvSIhsRrSlNugPcQ7gfGOsbk3d4izufwVlz1Q=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "3b1789322fcbcb5cf51228d732752714f1bf77da",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-21.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"krops": "krops",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"secrets": "secrets"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"secrets": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"narHash": "sha256-tsXsKNsa6/AqhXV6YxsSweX++YlwzQuWt0KeaV3SMgQ=",
|
||||||
|
"path": "/home/palo/dev/secrets",
|
||||||
|
"type": "path"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"path": "/home/palo/dev/secrets",
|
||||||
|
"type": "path"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
31
flake.nix
Normal file
31
flake.nix
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
|
||||||
|
description = "my krops file";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
secrets = {
|
||||||
|
url = "path:/home/palo/dev/secrets";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-21.05";
|
||||||
|
krops = {
|
||||||
|
url = "github:Mic92/krops";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, krops, secrets, ... }:
|
||||||
|
let
|
||||||
|
system = "x86_64-linux";
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
writeCommand = krops.packages.${system}.writeCommand;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# deploy like this:
|
||||||
|
# nix run ".#deploy.sterni"
|
||||||
|
apps.${system}.deploy = pkgs.callPackage ./nixos/krops.nix {
|
||||||
|
inherit writeCommand secrets;
|
||||||
|
lib = krops.lib;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,150 +0,0 @@
|
||||||
{ lib, ... }:
|
|
||||||
|
|
||||||
with builtins;
|
|
||||||
|
|
||||||
# https://jenkinsci.github.io/job-dsl-plugin/
|
|
||||||
|
|
||||||
{
|
|
||||||
# source container url and credentialsId
|
|
||||||
job = name:
|
|
||||||
{ url, credentialsId, branch ? "master",
|
|
||||||
# https://docs.openstack.org/infra/jenkins-job-builder/triggers.html
|
|
||||||
triggers ? [{
|
|
||||||
pollscm = {
|
|
||||||
cron = "H/30 * * * *";
|
|
||||||
ignore-post-commit-hooks = true;
|
|
||||||
};
|
|
||||||
}], ... }:
|
|
||||||
config: {
|
|
||||||
job = {
|
|
||||||
inherit name triggers;
|
|
||||||
sandbox = true;
|
|
||||||
project-type = "pipeline";
|
|
||||||
dsl = let
|
|
||||||
stage = elem:
|
|
||||||
let
|
|
||||||
stageName = head (attrNames elem);
|
|
||||||
stateScripts = map (stage:
|
|
||||||
lib.getAttr (typeOf stage) {
|
|
||||||
string = ''
|
|
||||||
withEnv(['PATH=/run/current-system/sw/bin/','NIX_PATH=/var/src/']) {
|
|
||||||
sh '${toString stage}'
|
|
||||||
}'';
|
|
||||||
set = let
|
|
||||||
script = ''
|
|
||||||
withEnv(['PATH=/run/current-system/sw/bin/','NIX_PATH=/var/src/']) {
|
|
||||||
sh '${toString stage.script}'
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
in if (stage.credentialsId != null) then ''
|
|
||||||
sshagent(['${stage.credentialsId}']) { ${script} }
|
|
||||||
'' else
|
|
||||||
script;
|
|
||||||
}) (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{
|
|
||||||
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}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# creates a sync job
|
|
||||||
# source and target container url and credentialsId
|
|
||||||
syncJob = name: source: target: {
|
|
||||||
job = {
|
|
||||||
name = name;
|
|
||||||
sandbox = true;
|
|
||||||
project-type = "pipeline";
|
|
||||||
triggers = [{
|
|
||||||
pollscm = {
|
|
||||||
cron = "H/30 * * * *";
|
|
||||||
ignore-post-commit-hooks = true;
|
|
||||||
};
|
|
||||||
}];
|
|
||||||
dsl = ''
|
|
||||||
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{
|
|
||||||
stage('Pull') {
|
|
||||||
steps {
|
|
||||||
checkout(
|
|
||||||
[$class: 'GitSCM'
|
|
||||||
, branches: [[name: '*/master']]
|
|
||||||
, doGenerateSubmoduleConfigurations: false
|
|
||||||
, extensions: [[$class: 'LocalBranch', localBranch: 'master']]
|
|
||||||
, submoduleCfg: []
|
|
||||||
, userRemoteConfigs:
|
|
||||||
[[ credentialsId: '${source.credentialsId}'
|
|
||||||
, url: '${source.url}']]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Push') {
|
|
||||||
steps {
|
|
||||||
sshagent(['${target.credentialsId}']) {
|
|
||||||
withEnv(['PATH=/run/current-system/sw/bin/','NIX_PATH=/var/src/']) {
|
|
||||||
sh "git push -f ${target.url}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Push Tags') {
|
|
||||||
steps {
|
|
||||||
sshagent(['${target.credentialsId}']) {
|
|
||||||
withEnv(['PATH=/run/current-system/sw/bin/']) {
|
|
||||||
sh "git push -f ${target.url} --tags"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
{ config, pkgs, lib, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
|
|
||||||
cfg = config.programs.custom.video;
|
|
||||||
|
|
||||||
# show keyboard input on desktop for screencasts
|
|
||||||
screenKey = pkgs.symlinkJoin {
|
|
||||||
name = "screen-keys";
|
|
||||||
paths = let
|
|
||||||
screenKeyScript = { position ? "bottom", size ? "small", ... }:
|
|
||||||
pkgs.writeShellScriptBin "screenkeys-${position}-${size}" # sh
|
|
||||||
''
|
|
||||||
${pkgs.screenkey}/bin/screenkey \
|
|
||||||
--no-detach \
|
|
||||||
--bg-color '#fdf6e3' \
|
|
||||||
--font-color '#073642' \
|
|
||||||
-p ${position} \
|
|
||||||
-s ${size} \
|
|
||||||
"$@"
|
|
||||||
'';
|
|
||||||
in lib.flatten (lib.flip map [ "large" "small" "medium" ] (size:
|
|
||||||
lib.flip map [ "top" "center" "bottom" ]
|
|
||||||
(position: screenKeyScript { inherit size position; })));
|
|
||||||
};
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
options.programs.custom.video.enable = mkEnableOption "enable video tools";
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
youtube-dl
|
|
||||||
mplayer
|
|
||||||
mpv
|
|
||||||
|
|
||||||
# to record your screen
|
|
||||||
# ---------------------
|
|
||||||
simplescreenrecorder
|
|
||||||
screenKey
|
|
||||||
|
|
||||||
# to transcode video material
|
|
||||||
# ---------------------------
|
|
||||||
handbrake
|
|
||||||
ffmpeg-full
|
|
||||||
|
|
||||||
# video editing
|
|
||||||
# -------------
|
|
||||||
openshot-qt
|
|
||||||
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,399 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
|
|
||||||
cfg = config.programs.custom.vim;
|
|
||||||
|
|
||||||
nix-xptemplates = pkgs.writeTextFile {
|
|
||||||
name = "nix-xptemplates";
|
|
||||||
destination = "/ftplugin/nix/nix.xpt.vim";
|
|
||||||
text = # vim
|
|
||||||
''
|
|
||||||
XPTemplate priority=personal
|
|
||||||
|
|
||||||
XPT option " tips
|
|
||||||
`name^ = mkOption {
|
|
||||||
type = with types; `type^;
|
|
||||||
description = ${"''"}
|
|
||||||
`cursor^
|
|
||||||
${"''"};
|
|
||||||
};
|
|
||||||
|
|
||||||
XPT package " tips
|
|
||||||
{ config, lib, ... }:
|
|
||||||
{
|
|
||||||
`cursor^
|
|
||||||
}
|
|
||||||
|
|
||||||
XPT terranix" tips
|
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
cfg = config.`name^;
|
|
||||||
in {
|
|
||||||
|
|
||||||
options.`name^ = mkOption {
|
|
||||||
default = {};
|
|
||||||
type = with types; attrsOf (submodule ({ name, ... }:{
|
|
||||||
options = {
|
|
||||||
enable = mkEnableOption "`name^.name";
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
config =
|
|
||||||
let
|
|
||||||
allConfigs = cfg
|
|
||||||
in
|
|
||||||
mkIf (cfg != {} ){
|
|
||||||
`cursor^
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
XPT module " tips
|
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
|
|
||||||
cfg = config.`name^;
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
options.`name^ = {
|
|
||||||
enable = mkEnableOption "enable `name^";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
`cursor^
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
XPT shell " tips
|
|
||||||
{ pkgs ? import <nixpkgs> {} }:
|
|
||||||
pkgs.mkShell {
|
|
||||||
|
|
||||||
# needed pkgs
|
|
||||||
# -----------
|
|
||||||
buildInputs = with pkgs; [
|
|
||||||
`name^
|
|
||||||
];
|
|
||||||
|
|
||||||
# run this on start
|
|
||||||
# -----------------
|
|
||||||
shellHook = ${"''"}
|
|
||||||
HISTFILE=${"$"}{toString ./.}/.history
|
|
||||||
${"''"};
|
|
||||||
}
|
|
||||||
|
|
||||||
XPT fhsUser " tips
|
|
||||||
{ pkgs ? import <nixpkgs> {} }:
|
|
||||||
(pkgs.buildFHSUserEnv {
|
|
||||||
name = "fhs-user-env";
|
|
||||||
|
|
||||||
targetPkgs = pkgs: with pkgs; [
|
|
||||||
# core stuff
|
|
||||||
# ----------
|
|
||||||
vim silver-searcher curl coreutils git tig
|
|
||||||
|
|
||||||
# common X dependencies
|
|
||||||
# ---------------------
|
|
||||||
atk cairo dbus eudev expat fontconfig freetype gdk_pixbuf glib gnome3.GConf gtk2-x11
|
|
||||||
mesa_glu nspr nss pango xlibs.libXScrnSaver xlibs.libXcomposite xlibs.libXcursor
|
|
||||||
xlibs.libXdamage xlibs.libXfixes xlibs.libXi xlibs.libXrender xlibs.libXtst xorg.libX11
|
|
||||||
xorg.libXext xorg.libXinerama xorg.libxcb
|
|
||||||
liblo zlib fftw minixml libcxx alsaLib glibc
|
|
||||||
|
|
||||||
# new stuff
|
|
||||||
# ---------
|
|
||||||
`cursor^
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
# multilib packages
|
|
||||||
# -----------------
|
|
||||||
# these are packages compiled 32bit and 64bit
|
|
||||||
multiPkgs = pkgs: with pkgs; [
|
|
||||||
];
|
|
||||||
|
|
||||||
# environment variables
|
|
||||||
# ---------------------
|
|
||||||
profile = ${"''"}
|
|
||||||
export TERM="xterm"
|
|
||||||
${"''"};
|
|
||||||
|
|
||||||
}).env
|
|
||||||
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
vim-tv-plugin = with lib;
|
|
||||||
((rtp: rtp // { inherit rtp; }) (pkgs.write "vim-tv" {
|
|
||||||
"/syntax/haskell.vim".text = # vim
|
|
||||||
''
|
|
||||||
syn region String start=+\[[[:alnum:]]*|+ end=+|]+
|
|
||||||
|
|
||||||
hi link ConId Identifier
|
|
||||||
hi link VarId Identifier
|
|
||||||
hi link hsDelimiter Delimiter
|
|
||||||
'';
|
|
||||||
"/syntax/nix.vim".text = # vim
|
|
||||||
''
|
|
||||||
"" Quit when a (custom) syntax file was already loaded
|
|
||||||
"if exists("b:current_syntax")
|
|
||||||
" finish
|
|
||||||
"endif
|
|
||||||
|
|
||||||
"setf nix
|
|
||||||
|
|
||||||
" Ref <nix/src/libexpr/lexer.l>
|
|
||||||
syn match NixID /[a-zA-Z\_][a-zA-Z0-9\_\'\-]*/
|
|
||||||
syn match NixINT /\<[0-9]\+\>/
|
|
||||||
syn match NixPATH /[a-zA-Z0-9\.\_\-\+]*\(\/[a-zA-Z0-9\.\_\-\+]\+\)\+/
|
|
||||||
syn match NixHPATH /\~\(\/[a-zA-Z0-9\.\_\-\+]\+\)\+/
|
|
||||||
syn match NixSPATH /<[a-zA-Z0-9\.\_\-\+]\+\(\/[a-zA-Z0-9\.\_\-\+]\+\)*>/
|
|
||||||
syn match NixURI /[a-zA-Z][a-zA-Z0-9\+\-\.]*:[a-zA-Z0-9\%\/\?\:\@\&\=\+\$\,\-\_\.\!\~\*\']\+/
|
|
||||||
syn region NixSTRING
|
|
||||||
\ matchgroup=NixSTRING
|
|
||||||
\ start='"'
|
|
||||||
\ skip='\\"'
|
|
||||||
\ end='"'
|
|
||||||
syn region NixIND_STRING
|
|
||||||
\ matchgroup=NixIND_STRING
|
|
||||||
\ start="'''"
|
|
||||||
\ skip="'''\('\|[$]\|\\[nrt]\)"
|
|
||||||
\ end="'''"
|
|
||||||
|
|
||||||
syn match NixOther /[-!+&<>|():/;=.,?\[\]*@]/
|
|
||||||
|
|
||||||
syn match NixCommentMatch /\(^\|\s\)#.*/
|
|
||||||
syn region NixCommentRegion start="/\*" end="\*/"
|
|
||||||
|
|
||||||
hi link NixCode Statement
|
|
||||||
hi link NixData Constant
|
|
||||||
hi link NixComment Comment
|
|
||||||
|
|
||||||
hi link NixCommentMatch NixComment
|
|
||||||
hi link NixCommentRegion NixComment
|
|
||||||
hi link NixID NixCode
|
|
||||||
hi link NixINT NixData
|
|
||||||
hi link NixPATH NixData
|
|
||||||
hi link NixHPATH NixData
|
|
||||||
hi link NixSPATH NixData
|
|
||||||
hi link NixURI NixData
|
|
||||||
hi link NixSTRING NixData
|
|
||||||
hi link NixIND_STRING NixData
|
|
||||||
|
|
||||||
hi link NixEnter NixCode
|
|
||||||
hi link NixOther NixCode
|
|
||||||
hi link NixQuote NixData
|
|
||||||
|
|
||||||
syn cluster nix_has_dollar_curly contains=@nix_ind_strings,@nix_strings
|
|
||||||
syn cluster nix_ind_strings contains=NixIND_STRING
|
|
||||||
syn cluster nix_strings contains=NixSTRING
|
|
||||||
|
|
||||||
${concatStringsSep "\n" (mapAttrsToList (name:
|
|
||||||
{ extraStart ? null, lang ? name }:
|
|
||||||
let
|
|
||||||
startAlts = filter isString [ "/\\* ${name} \\*/" extraStart ];
|
|
||||||
sigil = "\\(${concatStringsSep "\\|" startAlts}\\)[ \\t\\r\\n]*";
|
|
||||||
# vim
|
|
||||||
in ''
|
|
||||||
syn include @nix_${lang}_syntax syntax/${lang}.vim
|
|
||||||
if exists("b:current_syntax")
|
|
||||||
unlet b:current_syntax
|
|
||||||
endif
|
|
||||||
|
|
||||||
syn match nix_${lang}_sigil
|
|
||||||
\ X${replaceStrings [ "X" ] [ "\\X" ] sigil}\ze\('''\|"\)X
|
|
||||||
\ nextgroup=nix_${lang}_region_IND_STRING,nix_${lang}_region_STRING
|
|
||||||
\ transparent
|
|
||||||
|
|
||||||
syn region nix_${lang}_region_STRING
|
|
||||||
\ matchgroup=NixSTRING
|
|
||||||
\ start='"'
|
|
||||||
\ skip='\\"'
|
|
||||||
\ end='"'
|
|
||||||
\ contained
|
|
||||||
\ contains=@nix_${lang}_syntax
|
|
||||||
\ transparent
|
|
||||||
|
|
||||||
syn region nix_${lang}_region_IND_STRING
|
|
||||||
\ matchgroup=NixIND_STRING
|
|
||||||
\ start="'''"
|
|
||||||
\ skip="'''\('\|[$]\|\\[nrt]\)"
|
|
||||||
\ end="'''"
|
|
||||||
\ contained
|
|
||||||
\ contains=@nix_${lang}_syntax
|
|
||||||
\ transparent
|
|
||||||
|
|
||||||
syn cluster nix_ind_strings
|
|
||||||
\ add=nix_${lang}_region_IND_STRING
|
|
||||||
|
|
||||||
syn cluster nix_strings
|
|
||||||
\ add=nix_${lang}_region_STRING
|
|
||||||
|
|
||||||
" This is required because containedin isn't transitive.
|
|
||||||
syn cluster nix_has_dollar_curly
|
|
||||||
\ add=@nix_${lang}_syntax
|
|
||||||
'') {
|
|
||||||
c = { };
|
|
||||||
cabal = { };
|
|
||||||
diff = { };
|
|
||||||
haskell = { };
|
|
||||||
python = { };
|
|
||||||
lua = { };
|
|
||||||
sed.extraStart = ''writeSed[^ \t\r\n]*[ \t\r\n]*"[^"]*"'';
|
|
||||||
sh.extraStart = concatStringsSep "\\|" [
|
|
||||||
''
|
|
||||||
write\(A\|Ba\|Da\)sh[^ \t\r\n]*[ \t\r\n]*\("[^"]*"\|[a-z]\+\)''
|
|
||||||
"[a-z]*Phase[ \\t\\r\\n]*="
|
|
||||||
];
|
|
||||||
yaml = { };
|
|
||||||
vim.extraStart = ''
|
|
||||||
write[^ \t\r\n]*[ \t\r\n]*"\(\([^"]*\.\)\?vimrc\|[^"]*\.vim\)"'';
|
|
||||||
xdefaults = { };
|
|
||||||
})}
|
|
||||||
|
|
||||||
" Clear syntax that interferes with nixINSIDE_DOLLAR_CURLY.
|
|
||||||
syn clear shVarAssign
|
|
||||||
|
|
||||||
syn region nixINSIDE_DOLLAR_CURLY
|
|
||||||
\ matchgroup=NixEnter
|
|
||||||
\ start="[$]{"
|
|
||||||
\ end="}"
|
|
||||||
\ contains=TOP
|
|
||||||
\ containedin=@nix_has_dollar_curly
|
|
||||||
\ transparent
|
|
||||||
|
|
||||||
syn region nix_inside_curly
|
|
||||||
\ matchgroup=NixEnter
|
|
||||||
\ start="{"
|
|
||||||
\ end="}"
|
|
||||||
\ contains=TOP
|
|
||||||
\ containedin=nixINSIDE_DOLLAR_CURLY,nix_inside_curly
|
|
||||||
\ transparent
|
|
||||||
|
|
||||||
syn match NixQuote /'''\($\|\\.\)/he=s+2
|
|
||||||
\ containedin=@nix_ind_strings
|
|
||||||
\ contained
|
|
||||||
|
|
||||||
syn match NixQuote /'''\('\|\\.\)/he=s+1
|
|
||||||
\ containedin=@nix_ind_strings
|
|
||||||
\ contained
|
|
||||||
|
|
||||||
syn match NixQuote /\\./he=s+1
|
|
||||||
\ containedin=@nix_strings
|
|
||||||
\ contained
|
|
||||||
|
|
||||||
syn sync fromstart
|
|
||||||
|
|
||||||
let b:current_syntax = "nix"
|
|
||||||
|
|
||||||
set isk=@,48-57,_,192-255,-,'
|
|
||||||
'';
|
|
||||||
"/syntax/sed.vim".text = # vim
|
|
||||||
''
|
|
||||||
syn region sedBranch
|
|
||||||
\ matchgroup=sedFunction start="T"
|
|
||||||
\ matchgroup=sedSemicolon end=";\|$"
|
|
||||||
\ contains=sedWhitespace
|
|
||||||
'';
|
|
||||||
}));
|
|
||||||
|
|
||||||
# active plugins
|
|
||||||
# --------------
|
|
||||||
extra-runtimepath = with pkgs;
|
|
||||||
lib.concatMapStringsSep "," (pkg: "${pkg.rtp}") [
|
|
||||||
vimPlugins.Syntastic
|
|
||||||
vimPlugins.ack-vim
|
|
||||||
vimPlugins.airline
|
|
||||||
vimPlugins.vim-nix
|
|
||||||
vimPlugins.xptemplate
|
|
||||||
vim-tv-plugin
|
|
||||||
];
|
|
||||||
|
|
||||||
# the vimrc
|
|
||||||
# ---------
|
|
||||||
vimrc = pkgs.writeText "vimrc" ''
|
|
||||||
|
|
||||||
" turn on linenumbers
|
|
||||||
" to turn of :set nonumber
|
|
||||||
:set number
|
|
||||||
|
|
||||||
" show Trailing Whitespaces
|
|
||||||
:set list listchars=tab:»·,trail:¶
|
|
||||||
|
|
||||||
" Map leader is the key for shortcuts
|
|
||||||
nnoremap <SPACE> <Nop>
|
|
||||||
let mapleader = "\<Space>"
|
|
||||||
|
|
||||||
" move blocks of text in visual mode
|
|
||||||
" does not work correctly
|
|
||||||
vmap <up> xkP`[V`]
|
|
||||||
vmap <down> xp`[V`]
|
|
||||||
|
|
||||||
" search/grep case insensitive
|
|
||||||
:set ignorecase
|
|
||||||
|
|
||||||
" tabs should always be 2 spaces
|
|
||||||
set et ts=2 sts=2 sw=2
|
|
||||||
|
|
||||||
" installed vim-plugins
|
|
||||||
set runtimepath=${extra-runtimepath},$VIMRUNTIME,$HOME/.vim,${nix-xptemplates}
|
|
||||||
|
|
||||||
" syntax highlighting on
|
|
||||||
syntax on
|
|
||||||
|
|
||||||
" xptemplates
|
|
||||||
" -----------
|
|
||||||
" a plugin to insert snippets on demand
|
|
||||||
set nocompatible
|
|
||||||
filetype plugin on
|
|
||||||
|
|
||||||
" enable cursor cross
|
|
||||||
" -------------------
|
|
||||||
":hi CursorLine cterm=NONE ctermbg=darkred ctermfg=white guibg=darkred guifg=white
|
|
||||||
":hi CursorColumn cterm=NONE ctermbg=darkred ctermfg=white guibg=darkred guifg=white
|
|
||||||
:hi CursorLine cterm=NONE ctermbg=0 guibg=#073642
|
|
||||||
:hi CursorColumn cterm=NONE ctermbg=0 guibg=#073642
|
|
||||||
set cursorline
|
|
||||||
set cursorcolumn
|
|
||||||
|
|
||||||
" save view
|
|
||||||
" ---------
|
|
||||||
augroup AutoSaveFolds
|
|
||||||
autocmd!
|
|
||||||
autocmd BufWinLeave * mkview
|
|
||||||
autocmd BufWinEnter * silent loadview
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
" some language stuff
|
|
||||||
" -------------------
|
|
||||||
:map <leader>s :setlocal spell spelllang=en
|
|
||||||
|
|
||||||
'';
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
# no options
|
|
||||||
options.programs.custom.vim.enable = lib.mkEnableOption "vim";
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
# create vimrc
|
|
||||||
# ------------
|
|
||||||
# and load it as config for vim
|
|
||||||
environment.variables.VIMINIT = ":so /etc/vimrc";
|
|
||||||
environment.etc.vimrc.source = vimrc;
|
|
||||||
|
|
||||||
# set vim to the default editor
|
|
||||||
# -----------------------------
|
|
||||||
programs.vim.defaultEditor = true;
|
|
||||||
|
|
||||||
# install vim
|
|
||||||
# -----------
|
|
||||||
environment.systemPackages = [ pkgs.vim ];
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
{ config, pkgs, lib, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.system.permown;
|
|
||||||
nameGenerator = path: "permown.${replaceStrings [ "/" ] [ "_" ] path}";
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
options.system.permown = mkOption {
|
|
||||||
default = { };
|
|
||||||
type = with types;
|
|
||||||
attrsOf (submodule ({ config, ... }: {
|
|
||||||
options = {
|
|
||||||
directory-mode = mkOption {
|
|
||||||
default = "=rwx";
|
|
||||||
type = types.str;
|
|
||||||
};
|
|
||||||
file-mode = mkOption {
|
|
||||||
default = "=rw";
|
|
||||||
type = types.str;
|
|
||||||
};
|
|
||||||
group = mkOption {
|
|
||||||
apply = x: if x == null then "" else x;
|
|
||||||
default = null;
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
};
|
|
||||||
owner = mkOption { type = types.str; };
|
|
||||||
path = mkOption {
|
|
||||||
default = config._module.args.name;
|
|
||||||
type = types.path;
|
|
||||||
};
|
|
||||||
umask = mkOption {
|
|
||||||
default = "0027";
|
|
||||||
type = types.str;
|
|
||||||
};
|
|
||||||
timer = mkOption {
|
|
||||||
default = "hourly";
|
|
||||||
type = types.str;
|
|
||||||
description =
|
|
||||||
"OnCalendar string on how frequent should this command run";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
config = let plans = lib.attrValues cfg;
|
|
||||||
|
|
||||||
in mkIf (plans != [ ]) {
|
|
||||||
|
|
||||||
system.activationScripts.permown = let
|
|
||||||
mkdir = { path, ... }: ''
|
|
||||||
${pkgs.coreutils}/bin/mkdir -p ${path}
|
|
||||||
'';
|
|
||||||
in concatMapStrings mkdir plans;
|
|
||||||
|
|
||||||
systemd.services = listToAttrs (flip map plans
|
|
||||||
({ 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;
|
|
||||||
value = {
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
timerConfig.OnCalendar = timer;
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
1
nixos/assets/ssh/borg_access.pub
Normal file
1
nixos/assets/ssh/borg_access.pub
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC/WCoJ9zSL85R1mNJHUGRofyigeg2+g4+bwWVysHxWroPMIpP2hJrMRPoP13SAOaLOjl6X112jjoQ2wpJ/qptjtojrsF8bpFgoMqCQFsQDD4zuG4V/AaIt0nAF4B5tDBGFN3Hj6vpbwVAidv+8Kr41r5JOG/8Z/UiJDGrIMab3kDwyOklrMPLWr7IBYC0O8Jwyz3lAl18ukMSEZvoPaJhPJyyqRhSagX59U7AQiNrnq18kzi7Pszy3e1d7x3vWSXemJGZaUJ+cFbl1LrvFHwUa55sSUVUVBRxgABc906YoiUcr31aw98zUX4W+2+AqDzIIquV5frIc/+nnfsmDrsnMl81cLglxuRxqib0AuSYqkNQimWrR61M7TaLvGZomMk8Vheew/QlxvHvhbHwnu7/tgNll2i+Zi1T7VZ5Hcy4quYDZQA7NDrvu0dEm+dTlOfuJJZdMLWws20ao8xtv8IxxCN31CBCbCSETpsSuvT7joHKGpJoOf3eilLLqOKjrbo5E6s6S1w1WRoZ6LuXQo2l5uvMVSzUZ+4CG+FX+Q73bpQ5SWUvz2o5HovX8RbcneuG7mfZMe80F5IyaqSmi0r+kFOqK4NKz/InHhSJjrFYJWl2PP+30MfsHx5NMOVhfKdRZje5oTds6L2o9+3vhiE7CmgZVR+RqMHMUtRrERODwPQ==
|
1
nixos/assets/ssh/jenkins.pub
Normal file
1
nixos/assets/ssh/jenkins.pub
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDIZ8ezpjX1nI/Im+krulJNaVd1DZeFvcgX3x197DIbBgCsBjAW8WuV2tzmcrWSjWJ6lfmLlzplOLzhTNG763sbNQ5amfhglYTmQhruGcSXNkdsjOyoxK8SX3wH6Kv/Q0CpoyAYOB9fiJnUyWB9BXSI8VYMMRFj6+cPiZc6NhnnlxU+6uH3VvzV5hsAaT4mpXJJEidMqE9DpGFguOekOUO7HCVcZeQQjazl1u+NhbqRI3CsJjXBqiqAFSMzKOXhTk36xd2WLEmCaPnWuWf7imvR+T3JVPFTNGec3wMbT5nnMiK0/hbowyDQCbtnUVWja9ftVsOH55tLRSY16GnXngUzw+trxWOvX0wOFOhfSZ2k1WtjTlNtOEhne/V0a3bocel/7JuXBX3RvWAEVl1sWS5R9MG8aDB8S2fx8qZirbg0NZticAxcHtg0RyJRzH6DYrkINE6cUgK7qsrUtaY1W6Qj6Jp33Li8KHY2JElDvJLhAx8v7l6BaZkog/Z0raR8RSRefiDQZJ8qiqPXUJG1pQm4Mp8IGL5PAmi0AZg6QL2pkXC0pyg1xE4TdRjOeuV/vdVDX15xCsgOJjK7PGNoNm2JpYA8vaWMHG8Ujk4UBHolooKeuL3g0CcgzfyRMp/Dxlk1BhgRQ17VxWBDuKt3bWuTJIvmrvDuPB3vd+WYNNqskQ==
|
|
@ -7,8 +7,8 @@
|
||||||
allowSubRepos = true;
|
allowSubRepos = true;
|
||||||
authorizedKeys = [
|
authorizedKeys = [
|
||||||
# todo rename
|
# todo rename
|
||||||
(lib.fileContents <common_secrets/backup/ssh_rsa.pub>)
|
(lib.fileContents ../../assets/ssh/borg_access.pub)
|
||||||
(lib.fileContents <assets/ssh/card_rsa.pub>)
|
(lib.fileContents ../../assets/ssh/card_rsa.pub)
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
|
|
||||||
<system/server>
|
../../system/server
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
|
|
||||||
#./home-assistant.nix
|
#./home-assistant.nix
|
||||||
|
@ -13,10 +13,14 @@
|
||||||
#./lan.nix
|
#./lan.nix
|
||||||
./dms.nix
|
./dms.nix
|
||||||
./borg.nix
|
./borg.nix
|
||||||
|
./mpd.nix
|
||||||
|
./grocy.nix
|
||||||
|
./taskwarrior-pushover.nix
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
nixpkgs.config.permittedInsecurePackages = [ "homeassistant-0.114.4" ];
|
sops.defaultSopsFile = ../../secrets/pepe.yaml;
|
||||||
|
|
||||||
|
|
||||||
networking.hostName = "pepe";
|
networking.hostName = "pepe";
|
||||||
|
|
|
@ -11,7 +11,8 @@ let
|
||||||
rev = "2f5c44f017bdfd8abfe908d419ef26bac300f809";
|
rev = "2f5c44f017bdfd8abfe908d419ef26bac300f809";
|
||||||
sha256 = "0dxhk1ah6wwbsxyk4hd32rz7886w7r5gfy16485gjbvky1qsi8gd";
|
sha256 = "0dxhk1ah6wwbsxyk4hd32rz7886w7r5gfy16485gjbvky1qsi8gd";
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
# setup ftp
|
# setup ftp
|
||||||
services.vsftpd = {
|
services.vsftpd = {
|
||||||
|
@ -39,9 +40,11 @@ in {
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
sops.secrets.ftp_password = { };
|
||||||
|
|
||||||
# create user
|
# create user
|
||||||
users.users.ftp-upload = {
|
users.users.ftp-upload = {
|
||||||
passwordFile = toString <secrets/ftp/password>;
|
passwordFile = config.sops.secrets.ftp_password.path;
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
};
|
};
|
||||||
|
|
16
nixos/configs/pepe/grocy.nix
Normal file
16
nixos/configs/pepe/grocy.nix
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.grocy = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
culture = "de";
|
||||||
|
currency = "EUR";
|
||||||
|
};
|
||||||
|
hostName = "grocy.pepe.private";
|
||||||
|
nginx.enableSSL = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
backup.dirs = [ config.services.grocy.dataDir ];
|
||||||
|
|
||||||
|
}
|
|
@ -1,32 +1,34 @@
|
||||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||||
# and may be overwritten by future invocations. Please make changes
|
# and may be overwritten by future invocations. Please make changes
|
||||||
# to /etc/nixos/configuration.nix instead.
|
# to /etc/nixos/configuration.nix instead.
|
||||||
{ config, lib, pkgs, ... }:
|
{ modulesPath, config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
<nixpkgs/nixos/modules/installer/scan/not-detected.nix>
|
"${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 =
|
|
@ -1,6 +1,4 @@
|
||||||
{ pkgs, config, lib, ... }:
|
{ pkgs, config, lib, ... }: {
|
||||||
let unstablePkgs = import <nixpkgs-unstable> { };
|
|
||||||
in {
|
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
#./home-assistant/mpd.nix
|
#./home-assistant/mpd.nix
|
||||||
|
@ -156,12 +154,13 @@ in {
|
||||||
|
|
||||||
{
|
{
|
||||||
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"
|
||||||
|
@ -187,65 +186,67 @@ in {
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
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 = [ ];
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.home-assistant = {
|
services.home-assistant = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = unstablePkgs.home-assistant;
|
package = pkgs.unstable.home-assistant;
|
||||||
#package = unstablePkgs.home-assistant.override {
|
#package = pkgs.unstable.home-assistant.override {
|
||||||
# python3 = unstablePkgs.python37;
|
# python3 = pkgs.unstable.python37;
|
||||||
# extraPackages = python: [
|
# extraPackages = python: [
|
||||||
# # todo : check which is still needed
|
# # todo : check which is still needed
|
||||||
# python.netdisco
|
# python.netdisco
|
|
@ -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 = [
|
232
nixos/configs/pepe/home-assistant/light-control.nix
Normal file
232
nixos/configs/pepe/home-assistant/light-control.nix
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
{ pkgs, lib, config, ... }: {
|
||||||
|
|
||||||
|
services.mqtt.light-control.enable = true;
|
||||||
|
services.mqtt.light-control.loglevel = "debug";
|
||||||
|
services.mqtt.light-control.config = {
|
||||||
|
credentials = {
|
||||||
|
host = "tcp://localhost:1883";
|
||||||
|
user = "homeassistant";
|
||||||
|
password = "hallo";
|
||||||
|
};
|
||||||
|
scenes = [
|
||||||
|
{
|
||||||
|
name = "up-dark";
|
||||||
|
ignored_sensors = [
|
||||||
|
"zigbee2mqtt/door_sensor_1"
|
||||||
|
"zigbee2mqtt/door_sensor_4"
|
||||||
|
"zigbee2mqtt/door_sensor_5"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "half";
|
||||||
|
ignored_sensors = [
|
||||||
|
"zigbee2mqtt/door_sensor_1"
|
||||||
|
"zigbee2mqtt/door_sensor_4"
|
||||||
|
"zigbee2mqtt/door_sensor_5"
|
||||||
|
];
|
||||||
|
disabled_switches = [
|
||||||
|
"zigbee2mqtt/led_1"
|
||||||
|
"zigbee2mqtt/led_2"
|
||||||
|
"zigbee2mqtt/light_2"
|
||||||
|
"zigbee2mqtt/light_4"
|
||||||
|
"zigbee2mqtt/light_5"
|
||||||
|
"zigbee2mqtt/light_7"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "down";
|
||||||
|
ignored_sensors = [
|
||||||
|
"zigbee2mqtt/door_sensor_1"
|
||||||
|
"zigbee2mqtt/door_sensor_4"
|
||||||
|
"zigbee2mqtt/door_sensor_5"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "up-bright";
|
||||||
|
disabled_switches = [
|
||||||
|
"zigbee2mqtt/led_1"
|
||||||
|
"zigbee2mqtt/led_2"
|
||||||
|
"zigbee2mqtt/light_2"
|
||||||
|
"zigbee2mqtt/light_4"
|
||||||
|
"zigbee2mqtt/light_5"
|
||||||
|
"zigbee2mqtt/light_7"
|
||||||
|
];
|
||||||
|
ignored_sensors = [ "zigbee2mqtt/door_sensor_4" ];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "outside";
|
||||||
|
room_tracking_enabled = false;
|
||||||
|
ignored_sensors = [ "zigbee2mqtt/door_sensor_4" ];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "night";
|
||||||
|
room_tracking_enabled = false;
|
||||||
|
brightness = 25;
|
||||||
|
ignored_sensors =
|
||||||
|
[ "zigbee2mqtt/motion_sensor_7" "zigbee2mqtt/door_sensor_4" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
sensors =
|
||||||
|
let
|
||||||
|
door = { topic, room }: {
|
||||||
|
topic = topic;
|
||||||
|
key = "contact";
|
||||||
|
room = room;
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
light = { topic, rooms, delay ? 0 }: {
|
||||||
|
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 {
|
||||||
|
topic = "zigbee2mqtt/light_2";
|
||||||
|
rooms = [ "office_room" ];
|
||||||
|
})
|
||||||
|
(light {
|
||||||
|
topic = "zigbee2mqtt/light_4";
|
||||||
|
rooms = [ "office_room" ];
|
||||||
|
})
|
||||||
|
(light {
|
||||||
|
topic = "zigbee2mqtt/light_5";
|
||||||
|
rooms = [ "storage_room" ];
|
||||||
|
})
|
||||||
|
(light {
|
||||||
|
topic = "zigbee2mqtt/light_7";
|
||||||
|
rooms = [ "sleeping_room" ];
|
||||||
|
})
|
||||||
|
(led {
|
||||||
|
topic = "zigbee2mqtt/led_1";
|
||||||
|
rooms = [ "office_room" ];
|
||||||
|
})
|
||||||
|
(led {
|
||||||
|
topic = "zigbee2mqtt/led_2";
|
||||||
|
rooms = [ "kitchen" ];
|
||||||
|
})
|
||||||
|
|
||||||
|
#(sonoff {
|
||||||
|
# id = "PAL01";
|
||||||
|
# rooms = [ "bed_room" ];
|
||||||
|
#})
|
||||||
|
#(sonoff {
|
||||||
|
# id = "PAL03";
|
||||||
|
# rooms = [ "living_room" ];
|
||||||
|
#})
|
||||||
|
#(sonoff {
|
||||||
|
# id = "PAL04";
|
||||||
|
# rooms = [ "bed_room" ];
|
||||||
|
#})
|
||||||
|
#(sonoff {
|
||||||
|
# id = "PAL06";
|
||||||
|
# rooms = [ "kitchen" ];
|
||||||
|
#})
|
||||||
|
## monitor and speakers
|
||||||
|
#(sonoff {
|
||||||
|
# id = "PAL07";
|
||||||
|
# rooms = [ "bed_room" ];
|
||||||
|
# delay = 180;
|
||||||
|
#})
|
||||||
|
#(sonoff {
|
||||||
|
# id = "PAL08";
|
||||||
|
# rooms = [ "bed_room" ];
|
||||||
|
# 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
182
nixos/configs/pepe/home-assistant/stocks.nix
Normal file
182
nixos/configs/pepe/home-assistant/stocks.nix
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
{ lib, config, pkgs, ... }:
|
||||||
|
let
|
||||||
|
|
||||||
|
folderPath = config.services.home-assistant.configDir;
|
||||||
|
|
||||||
|
# find symbols with
|
||||||
|
# https://www.alphavantage.co/query?function=SYMBOL_SEARCH&keywords=<keywords>&apikey=<api_key>
|
||||||
|
# as described here : https://www.alphavantage.co/documentation/#symbolsearch
|
||||||
|
#
|
||||||
|
# example:
|
||||||
|
# --------
|
||||||
|
# stocks = [
|
||||||
|
# {
|
||||||
|
# symbol = "GOOGL";
|
||||||
|
# name = "google";
|
||||||
|
# friendly_name = "Google";
|
||||||
|
# currency = "$";
|
||||||
|
# # I own 50 and bought at a price of 1000
|
||||||
|
# own = {
|
||||||
|
# pieces = 50;
|
||||||
|
# price = 1000;
|
||||||
|
# };
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
stocks = import <secrets/home-assistant/stocks>;
|
||||||
|
filePath = name: "${folderPath}/stock_${name}.json";
|
||||||
|
|
||||||
|
cleanup_list = list: lib.filter (entry: entry != { }) (lib.flatten list);
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
|
sensor = cleanup_list (map
|
||||||
|
({ name, currency, own ? { }, ... }: [
|
||||||
|
{
|
||||||
|
platform = "file";
|
||||||
|
name = "stock_${name}";
|
||||||
|
file_path = filePath name;
|
||||||
|
value_template = "{{ value_json.price}} ${currency}";
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
platform = "file";
|
||||||
|
name = "stock_${name}_change";
|
||||||
|
file_path = filePath name;
|
||||||
|
value_template = "{{ value_json.change}} ${currency}";
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
platform = "file";
|
||||||
|
name = "stock_${name}_change_percent";
|
||||||
|
file_path = filePath name;
|
||||||
|
value_template = "{{ value_json.change_percent}} %";
|
||||||
|
}
|
||||||
|
(lib.optionalAttrs (own != { }) {
|
||||||
|
platform = "file";
|
||||||
|
name = "stock_${name}_profit";
|
||||||
|
file_path = filePath name;
|
||||||
|
value_template = ''
|
||||||
|
{{ "{:,.2f}".format( value_json.price * ${toString own.pieces} - ${
|
||||||
|
toString (own.pieces * own.price)
|
||||||
|
} ) }} ${currency}'';
|
||||||
|
})
|
||||||
|
])
|
||||||
|
stocks);
|
||||||
|
|
||||||
|
homeassistant = {
|
||||||
|
whitelist_external_dirs = [ folderPath ];
|
||||||
|
customize = builtins.listToAttrs (cleanup_list (map
|
||||||
|
({ name, own ? { }, ... }: [
|
||||||
|
{
|
||||||
|
name = "sensor.stock_${name}";
|
||||||
|
value = {
|
||||||
|
icon = "mdi:cash-usd-outline";
|
||||||
|
friendly_name = "Price";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "sensor.stock_${name}_change";
|
||||||
|
value = {
|
||||||
|
icon = "mdi:radar";
|
||||||
|
friendly_name = "Difference";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "sensor.stock_${name}_change_percent";
|
||||||
|
value = {
|
||||||
|
icon = "mdi:radar";
|
||||||
|
friendly_name = "Percent";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(lib.optionalAttrs (own != { }) {
|
||||||
|
name = "sensor.stock_${name}_profit";
|
||||||
|
value = {
|
||||||
|
icon = "mdi:radar";
|
||||||
|
friendly_name = "Profit";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
])
|
||||||
|
stocks));
|
||||||
|
};
|
||||||
|
|
||||||
|
group = (builtins.listToAttrs (map
|
||||||
|
({ name, friendly_name, own ? { }, ... }: {
|
||||||
|
name = "stock_${name}";
|
||||||
|
value = {
|
||||||
|
name = "${friendly_name} Aktie";
|
||||||
|
entities = [
|
||||||
|
"sensor.stock_${name}"
|
||||||
|
"sensor.stock_${name}_change"
|
||||||
|
"sensor.stock_${name}_change_percent"
|
||||||
|
] ++ (lib.optional (own != { }) "sensor.stock_${name}_profit");
|
||||||
|
};
|
||||||
|
})
|
||||||
|
stocks));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services =
|
||||||
|
let
|
||||||
|
pullService = { name, symbol, currency, ... }: {
|
||||||
|
name = "pull_stock_${name}";
|
||||||
|
value = {
|
||||||
|
enable = true;
|
||||||
|
before = [ "home-assistant.service" ];
|
||||||
|
wantedBy = [ "home-assistant.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
User = "hass";
|
||||||
|
Type = "oneshot";
|
||||||
|
};
|
||||||
|
description = "pull stock_${name} for homeassistant";
|
||||||
|
script = ''
|
||||||
|
SYMBOL="${symbol}"
|
||||||
|
CURRENCY="${currency}"
|
||||||
|
APIKEY=${
|
||||||
|
lib.fileContents <secrets/home-assistant/alphavantage/apikey>
|
||||||
|
}
|
||||||
|
|
||||||
|
${pkgs.curl}/bin/curl --location --silent \
|
||||||
|
"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=$SYMBOL&apikey=$APIKEY" \
|
||||||
|
| ${pkgs.jq}/bin/jq --compact-output \
|
||||||
|
'.["Global Quote"] |
|
||||||
|
{
|
||||||
|
price: .["05. price"] | tonumber,
|
||||||
|
currency: "'$CURRENCY'",
|
||||||
|
change_percent: .["10. change percent"] | .[0:-1] | tonumber,
|
||||||
|
change: .["09. change"] | tonumber,
|
||||||
|
last_date: .["07. latest trading day"],
|
||||||
|
}' \
|
||||||
|
>> ${filePath name}
|
||||||
|
|
||||||
|
# old and stupid
|
||||||
|
#${pkgs.curl}/bin/curl --location --silent \
|
||||||
|
#"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=$SYMBOL&interval=5min&apikey=$APIKEY" \
|
||||||
|
#| ${pkgs.jq}/bin/jq --compact-output \
|
||||||
|
# '.["Time Series (5min)"] | to_entries | [ .[]
|
||||||
|
# | { date : .key , value : .value["4. close"], currency: "'$CURRENCY'" } ]
|
||||||
|
# | 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
|
||||||
|
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 = [
|
|
@ -2,8 +2,7 @@
|
||||||
# no need to set ZIGBEE2MQTT_DATA anymore
|
# no need to set ZIGBEE2MQTT_DATA anymore
|
||||||
assert lib.versionOlder lib.version "21.03";
|
assert lib.versionOlder lib.version "21.03";
|
||||||
|
|
||||||
let unstable = import <nixpkgs-unstable> { };
|
{
|
||||||
in {
|
|
||||||
imports = [
|
imports = [
|
||||||
./mqtt.nix
|
./mqtt.nix
|
||||||
./zigbee2mqtt/service.nix
|
./zigbee2mqtt/service.nix
|
||||||
|
@ -23,7 +22,7 @@ in {
|
||||||
enable = true;
|
enable = true;
|
||||||
#package = pkgs.own_zigbee2mqtt;
|
#package = pkgs.own_zigbee2mqtt;
|
||||||
#package = unstable.zigbee2mqtt;
|
#package = unstable.zigbee2mqtt;
|
||||||
package = unstable.zigbee2mqtt.overrideAttrs (old: rec {
|
package = pkgs.unstable.zigbee2mqtt.overrideAttrs (old: rec {
|
||||||
version = "1.18.1";
|
version = "1.18.1";
|
||||||
src = pkgs.fetchFromGitHub {
|
src = pkgs.fetchFromGitHub {
|
||||||
owner = "Koenkk";
|
owner = "Koenkk";
|
250
nixos/configs/pepe/home-assistant/zigbee2mqtt/buttons.nix
Normal file
250
nixos/configs/pepe/home-assistant/zigbee2mqtt/buttons.nix
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
{ pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
|
||||||
|
# we create 3 input_boolean which get toggled by the 3 types of buttons pressed.
|
||||||
|
# input_boolean.single_${name} : single click
|
||||||
|
# input_boolean.double_${name} : double click
|
||||||
|
# input_boolean.hold_${name} : hold
|
||||||
|
# if you override these input (via states) you have to create the input yourself
|
||||||
|
|
||||||
|
# https://www.zigbee2mqtt.io/devices/WXKG12LM.html
|
||||||
|
allDevices = {
|
||||||
|
"button_a1" = {
|
||||||
|
id = "0x00158d0002b04f65";
|
||||||
|
#groups = [ "living_room" ];
|
||||||
|
states.single = "input_boolean.situation_toggle";
|
||||||
|
states.hold = "input_boolean.printer_toggle";
|
||||||
|
states.double = "input_boolean.windows_up";
|
||||||
|
};
|
||||||
|
"button_a2" = {
|
||||||
|
id = "0x00158d0002b04f09";
|
||||||
|
#groups = [ "bed_room" ];
|
||||||
|
states.single = "input_boolean.situation_toggle";
|
||||||
|
states.hold = "input_boolean.printer_toggle";
|
||||||
|
states.double = "input_boolean.windows_up";
|
||||||
|
};
|
||||||
|
"button_a3" = {
|
||||||
|
id = "0x00158d0002b00e04";
|
||||||
|
#groups = [ "bed_room" ];
|
||||||
|
states.single = "input_boolean.situation_toggle";
|
||||||
|
states.hold = "input_boolean.printer_toggle";
|
||||||
|
states.double = "input_boolean.windows_up";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
|
(name:
|
||||||
|
{ id, ... }: {
|
||||||
|
name = id;
|
||||||
|
value = {
|
||||||
|
retain = false;
|
||||||
|
friendly_name = name;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
|
# define input_boolean
|
||||||
|
# --------------------
|
||||||
|
# which get toggled by the buttons
|
||||||
|
input_boolean =
|
||||||
|
let stripEmpty = lib.filter (a: a != { });
|
||||||
|
in builtins.listToAttrs (stripEmpty (lib.flatten (lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ states ? { }, ... }: [
|
||||||
|
(lib.optionalAttrs (!lib.hasAttr "single" states) {
|
||||||
|
name = "single_${name}";
|
||||||
|
value = { icon = "mdi:toggle-switch"; };
|
||||||
|
})
|
||||||
|
(lib.optionalAttrs (!lib.hasAttr "double" states) {
|
||||||
|
name = "double_${name}";
|
||||||
|
value = { icon = "mdi:toggle-switch"; };
|
||||||
|
})
|
||||||
|
(lib.optionalAttrs (!lib.hasAttr "hold" states) {
|
||||||
|
name = "hold_${name}";
|
||||||
|
value = { icon = "mdi:toggle-switch"; };
|
||||||
|
})
|
||||||
|
])
|
||||||
|
allDevices)));
|
||||||
|
|
||||||
|
# define meta information sensors
|
||||||
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ ... }: [
|
||||||
|
{
|
||||||
|
platform = "mqtt";
|
||||||
|
name = name;
|
||||||
|
icon = "mdi:toggle-switch";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
value_template = "{{ value_json.click }}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "battery_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
unit_of_measurement = "%";
|
||||||
|
icon = "mdi:battery-10";
|
||||||
|
value_template = "{{ value_json.battery }}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "link_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
icon = "mdi:signal";
|
||||||
|
unit_of_measurement = "lqi";
|
||||||
|
value_template = "{{ value_json.linkquality }}";
|
||||||
|
}
|
||||||
|
])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
|
binary_sensor = lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ ... }: {
|
||||||
|
name = name;
|
||||||
|
platform = "mqtt";
|
||||||
|
device_class = "motion";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
payload_on = true;
|
||||||
|
payload_off = false;
|
||||||
|
value_template = "{{ value_json.occupancy }}";
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
# create groups
|
||||||
|
# -------------
|
||||||
|
#group = let
|
||||||
|
# # to have nice panels for every device
|
||||||
|
# sensorGroups = lib.mapAttrs (name:
|
||||||
|
# { states ? { }, ... }:
|
||||||
|
# let
|
||||||
|
# entityIds = { single ? "input_boolean.single_${name}"
|
||||||
|
# , double ? "input_boolean.double_${name}"
|
||||||
|
# , hold ? "input_boolean.hold_${name}", ... }: [
|
||||||
|
# single
|
||||||
|
# double
|
||||||
|
# hold
|
||||||
|
# ];
|
||||||
|
# in {
|
||||||
|
# entities = [ "sensor.${name}" ] ++ (entityIds states)
|
||||||
|
# ++ [ "sensor.battery_${name}" "sensor.link_${name}" ];
|
||||||
|
# }) allDevices;
|
||||||
|
# # sort lights into given groups.
|
||||||
|
# sortedInGroups = let
|
||||||
|
# groupEntries = lib.zipAttrs (lib.flatten (lib.mapAttrsToList (name:
|
||||||
|
# { groups ? [ ], states ? { }, ... }:
|
||||||
|
# map (groupName: {
|
||||||
|
# "${groupName}" = if (lib.hasAttr "single" states) then
|
||||||
|
# states.single
|
||||||
|
# else
|
||||||
|
# "input_boolean.single_${name}";
|
||||||
|
# }) groups) allDevices));
|
||||||
|
# in lib.mapAttrs (name: entities: { inherit entities; }) groupEntries;
|
||||||
|
#in sortedInGroups // sensorGroups // {
|
||||||
|
# all_sensors.entities =
|
||||||
|
# lib.mapAttrsToList (name: { ... }: "binary_sensor.${name}") allDevices;
|
||||||
|
#};
|
||||||
|
|
||||||
|
# create automation
|
||||||
|
# -----------------
|
||||||
|
automation =
|
||||||
|
let
|
||||||
|
|
||||||
|
# single click
|
||||||
|
toggle_single_button_input = lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ states ? { }, ... }:
|
||||||
|
let
|
||||||
|
entityId =
|
||||||
|
if (lib.hasAttr "single" states) then
|
||||||
|
states.single
|
||||||
|
else
|
||||||
|
"input_boolean.single_${name}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
alias = "toggle single click ${name}";
|
||||||
|
trigger = {
|
||||||
|
platform = "mqtt";
|
||||||
|
topic = "zigbee2mqtt/${name}";
|
||||||
|
};
|
||||||
|
condition = {
|
||||||
|
condition = "template";
|
||||||
|
value_template = ''{{ "single" == trigger.payload_json.click}}'';
|
||||||
|
};
|
||||||
|
action = {
|
||||||
|
service = "input_boolean.toggle";
|
||||||
|
data.entity_id = entityId;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
# double click
|
||||||
|
toggle_double_button_input = lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ states ? { }, ... }:
|
||||||
|
let
|
||||||
|
entityId =
|
||||||
|
if (lib.hasAttr "double" states) then
|
||||||
|
states.double
|
||||||
|
else
|
||||||
|
"input_boolean.double_${name}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
alias = "toggle double click ${name}";
|
||||||
|
trigger = {
|
||||||
|
platform = "mqtt";
|
||||||
|
topic = "zigbee2mqtt/${name}";
|
||||||
|
};
|
||||||
|
condition = {
|
||||||
|
condition = "template";
|
||||||
|
value_template = ''{{ "double" == trigger.payload_json.click}}'';
|
||||||
|
};
|
||||||
|
action = {
|
||||||
|
service = "input_boolean.toggle";
|
||||||
|
data.entity_id = entityId;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
# hold
|
||||||
|
toggle_hold_button_input = lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ states ? { }, ... }:
|
||||||
|
let
|
||||||
|
entityId =
|
||||||
|
if (lib.hasAttr "hold" states) then
|
||||||
|
states.hold
|
||||||
|
else
|
||||||
|
"input_boolean.hold_${name}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
alias = "toggle hold ${name}";
|
||||||
|
trigger = {
|
||||||
|
platform = "mqtt";
|
||||||
|
topic = "zigbee2mqtt/${name}";
|
||||||
|
};
|
||||||
|
condition = {
|
||||||
|
condition = "template";
|
||||||
|
value_template = ''{{ "hold" == trigger.payload_json.action}}'';
|
||||||
|
};
|
||||||
|
action = {
|
||||||
|
service = "input_boolean.toggle";
|
||||||
|
data.entity_id = entityId;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
in
|
||||||
|
lib.flatten (toggle_single_button_input ++ toggle_double_button_input
|
||||||
|
++ toggle_hold_button_input);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
101
nixos/configs/pepe/home-assistant/zigbee2mqtt/doors.nix
Normal file
101
nixos/configs/pepe/home-assistant/zigbee2mqtt/doors.nix
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
{ pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
|
||||||
|
# https://www.zigbee2mqtt.io/devices/MCCGQ11LM.html
|
||||||
|
allDevices = {
|
||||||
|
"door_sensor_1" = { id = "0x00158d000312dc52"; };
|
||||||
|
"door_sensor_2" = { id = "0x00158d000316d5bf"; };
|
||||||
|
"door_sensor_3" = { id = "0x00158d0002f9516f"; };
|
||||||
|
"door_sensor_4" = { id = "0x00158d00031383b9"; };
|
||||||
|
"door_sensor_5" = { id = "0x00158d0003120d3e"; };
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
|
(name:
|
||||||
|
{ id, ... }: {
|
||||||
|
name = id;
|
||||||
|
value = {
|
||||||
|
retain = false;
|
||||||
|
friendly_name = name;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
|
# define meta information sensors
|
||||||
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ ... }: [
|
||||||
|
{
|
||||||
|
name = "battery_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
unit_of_measurement = "%";
|
||||||
|
icon = "mdi:battery-10";
|
||||||
|
value_template = "{{ value_json.battery }}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "link_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
icon = "mdi:signal";
|
||||||
|
unit_of_measurement = "lqi";
|
||||||
|
value_template = "{{ value_json.linkquality }}";
|
||||||
|
}
|
||||||
|
])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
|
binary_sensor = lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ ... }: {
|
||||||
|
name = name;
|
||||||
|
platform = "mqtt";
|
||||||
|
device_class = "door";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
payload_on = false;
|
||||||
|
payload_off = true;
|
||||||
|
value_template = "{{ value_json.contact}}";
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
# create groups
|
||||||
|
# -------------
|
||||||
|
group =
|
||||||
|
let
|
||||||
|
# to have nice panels for every device
|
||||||
|
sensorGroups = lib.mapAttrs
|
||||||
|
(name:
|
||||||
|
{ ... }: {
|
||||||
|
entities = [
|
||||||
|
"binary_sensor.${name}"
|
||||||
|
"sensor.battery_${name}"
|
||||||
|
"sensor.link_${name}"
|
||||||
|
];
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
# sort lights into given groups.
|
||||||
|
sortedInGroups =
|
||||||
|
let
|
||||||
|
groupEntries = lib.zipAttrs (lib.flatten (lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ groups ? [ ], ... }:
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
57
nixos/configs/pepe/home-assistant/zigbee2mqtt/fyrtur.nix
Normal file
57
nixos/configs/pepe/home-assistant/zigbee2mqtt/fyrtur.nix
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
{ pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
|
||||||
|
# https://www.zigbee2mqtt.io/devices/E1757.html
|
||||||
|
allDevices = {
|
||||||
|
"office_fyrtur_1" = { id = "0x680ae2fffe64fa40"; };
|
||||||
|
"office_fyrtur_2" = { id = "0x680ae2fffe91d234"; };
|
||||||
|
"bedroom_fyrtur_1" = { id = "0x680ae2fffe6e9f41"; };
|
||||||
|
"broken_fyrtur_1" = { id = "0x680ae2fffe8f6411"; };
|
||||||
|
};
|
||||||
|
|
||||||
|
# -t "zigbee2mqtt/fyrtur1/set" -m '{"position":100}'
|
||||||
|
# -t "zigbee2mqtt/fyrtur1/set" -m '{"position":15}'
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
|
(name:
|
||||||
|
{ id, ... }: {
|
||||||
|
name = id;
|
||||||
|
value = {
|
||||||
|
retain = false;
|
||||||
|
friendly_name = name;
|
||||||
|
transition = 0.1;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ ... }: [
|
||||||
|
{
|
||||||
|
name = "battery_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
unit_of_measurement = "%";
|
||||||
|
icon = "mdi:battery-10";
|
||||||
|
value_template = "{{ value_json.battery }}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "link_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
icon = "mdi:signal";
|
||||||
|
unit_of_measurement = "lqi";
|
||||||
|
value_template = "{{ value_json.linkquality }}";
|
||||||
|
}
|
||||||
|
])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
85
nixos/configs/pepe/home-assistant/zigbee2mqtt/heater.nix
Normal file
85
nixos/configs/pepe/home-assistant/zigbee2mqtt/heater.nix
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
{ pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
|
||||||
|
# https://www.zigbee2mqtt.io/devices/SPZB0001.html
|
||||||
|
allDevices = {
|
||||||
|
"office_heater_1" = { id = "0x00158d00032f5ee4"; }; # office
|
||||||
|
"office_heater_2" = { id = "0x00158d00032f5f9f"; }; # office (kitchen)
|
||||||
|
"bedroom_heater_1" = { id = "0x00158d00032f6d1e"; }; # bed room
|
||||||
|
"storage_heater_1" = { id = "0x00158d00032f604d"; }; # abstell raum
|
||||||
|
};
|
||||||
|
|
||||||
|
# -t "zigbee2mqtt/heater3/set" -m '{"system_mode":"auto","current_heating_setpoint":23}'
|
||||||
|
# -t "zigbee2mqtt/heater3/set" -m '{"system_mode":"off"}'
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
|
(name:
|
||||||
|
{ id, ... }: {
|
||||||
|
name = id;
|
||||||
|
value = {
|
||||||
|
legacy = false;
|
||||||
|
retain = false;
|
||||||
|
friendly_name = name;
|
||||||
|
transition = 1;
|
||||||
|
debounce = 0.5;
|
||||||
|
filtered_attributes = [
|
||||||
|
"battery_low"
|
||||||
|
"eurotronic_host_flags"
|
||||||
|
"eurotronic_system_mode"
|
||||||
|
#"occupied_heating_setpoint"
|
||||||
|
#"pi_heating_demand"
|
||||||
|
#"unoccupied_heating_setpoint"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ ... }: [
|
||||||
|
{
|
||||||
|
name = "battery_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
unit_of_measurement = "%";
|
||||||
|
icon = "mdi:battery-10";
|
||||||
|
value_template = "{{ value_json.battery }}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "link_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
icon = "mdi:signal";
|
||||||
|
unit_of_measurement = "lqi";
|
||||||
|
value_template = "{{ value_json.linkquality }}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
platform = "mqtt";
|
||||||
|
name = "temperature_${name}";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
unit_of_measurement = "°C";
|
||||||
|
device_class = "temperature";
|
||||||
|
value_template = "{{ value_json.local_temperature }}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
platform = "mqtt";
|
||||||
|
name = "pi_heating_demand_${name}";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
unit_of_measurement = "%";
|
||||||
|
value_template = "{{ value_json.pi_heating_demand }}";
|
||||||
|
}
|
||||||
|
])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
48
nixos/configs/pepe/home-assistant/zigbee2mqtt/leds.nix
Normal file
48
nixos/configs/pepe/home-assistant/zigbee2mqtt/leds.nix
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
{ pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
|
||||||
|
# https://www.zigbee2mqtt.io/devices/GL-C-007-1ID.html
|
||||||
|
allDevices = {
|
||||||
|
"led_1" = { id = "0x00124b001f7a5be9"; };
|
||||||
|
"led_2" = { id = "0x00124b001ee958b3"; };
|
||||||
|
};
|
||||||
|
|
||||||
|
# -t "zigbee2mqtt/led_1/set" -m '{"state":"ON","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":"OFF"}'
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
|
(name:
|
||||||
|
{ id, ... }: {
|
||||||
|
name = id;
|
||||||
|
value = {
|
||||||
|
retain = false;
|
||||||
|
friendly_name = name;
|
||||||
|
transition = 1;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
|
light = lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ ... }: {
|
||||||
|
platform = "mqtt";
|
||||||
|
name = name;
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
command_topic = "zigbee2mqtt/${name}/set";
|
||||||
|
value_template = "{{ value_json.click }}";
|
||||||
|
brightness = true;
|
||||||
|
color_temp = true;
|
||||||
|
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:
|
76
nixos/configs/pepe/home-assistant/zigbee2mqtt/motion.nix
Normal file
76
nixos/configs/pepe/home-assistant/zigbee2mqtt/motion.nix
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
{ pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
|
||||||
|
# https://www.zigbee2mqtt.io/devices/RTCGQ01LM.html
|
||||||
|
allDevices = {
|
||||||
|
|
||||||
|
"motion_sensor_1" = { id = "0x00158d0002fbd451"; };
|
||||||
|
"motion_sensor_2" = { id = "0x00158d0002f9a6b8"; };
|
||||||
|
"motion_sensor_3" = { id = "0x00158d0002f04522"; };
|
||||||
|
"motion_sensor_4" = { id = "0x00158d0002f9a558"; };
|
||||||
|
"motion_sensor_5" = { id = "0x00158d0002f9a56f"; };
|
||||||
|
"motion_sensor_6" = { id = "0x00158d0002f9a5cb"; };
|
||||||
|
"motion_sensor_7" = { id = "0x00158d0002f9a6aa"; };
|
||||||
|
"motion_sensor_8" = { id = "0x00158d0002f04637"; };
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
|
(name:
|
||||||
|
{ id, timeout ? 65, ... }: {
|
||||||
|
name = id;
|
||||||
|
value = {
|
||||||
|
retain = false;
|
||||||
|
friendly_name = name;
|
||||||
|
# should not be set below 60 seconds
|
||||||
|
occupancy_timeout = timeout;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
|
# define meta information sensors
|
||||||
|
binary_sensor = lib.flatten (lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ ... }: [{
|
||||||
|
name = "${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
value_template = "{{ value_json.occupancy }}";
|
||||||
|
#icon = "mdi:battery-10";
|
||||||
|
payload_on = true;
|
||||||
|
payload_off = false;
|
||||||
|
device_class = "motion";
|
||||||
|
}])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
|
# define meta information sensors
|
||||||
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ ... }: [
|
||||||
|
{
|
||||||
|
name = "battery_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
unit_of_measurement = "%";
|
||||||
|
icon = "mdi:battery-10";
|
||||||
|
value_template = "{{ value_json.battery }}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "link_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
icon = "mdi:signal";
|
||||||
|
unit_of_measurement = "lqi";
|
||||||
|
value_template = "{{ value_json.linkquality }}";
|
||||||
|
}
|
||||||
|
])
|
||||||
|
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";
|
||||||
|
|
112
nixos/configs/pepe/home-assistant/zigbee2mqtt/temperatur.nix
Normal file
112
nixos/configs/pepe/home-assistant/zigbee2mqtt/temperatur.nix
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
{ pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
|
||||||
|
# https://www.zigbee2mqtt.io/devices/WSDCGQ11LM.html
|
||||||
|
allDevices = {
|
||||||
|
"temperature_sensor_1" = {
|
||||||
|
id = "0x00158d0002d79220";
|
||||||
|
groups = [ "living_room" ];
|
||||||
|
};
|
||||||
|
"temperature_sensor_2" = {
|
||||||
|
id = "0x00158d0002d7913d";
|
||||||
|
groups = [ "living_room" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
services.zigbee2mqttConfiguration = lib.mapAttrs'
|
||||||
|
(name:
|
||||||
|
{ id, ... }: {
|
||||||
|
name = id;
|
||||||
|
value = {
|
||||||
|
retain = false;
|
||||||
|
friendly_name = name;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
allDevices;
|
||||||
|
|
||||||
|
services.homeAssistantConfig = {
|
||||||
|
|
||||||
|
# define meta information sensors
|
||||||
|
sensor = lib.flatten (lib.mapAttrsToList
|
||||||
|
(name:
|
||||||
|
{ ... }: [
|
||||||
|
{
|
||||||
|
platform = "mqtt";
|
||||||
|
name = name;
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
unit_of_measurement = "°C";
|
||||||
|
device_class = "temperature";
|
||||||
|
value_template = "{{ value_json.temperature }}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
platform = "mqtt";
|
||||||
|
name = "humidity_${name}";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
unit_of_measurement = "%";
|
||||||
|
device_class = "humidity";
|
||||||
|
value_template = "{{ value_json.humidity }}";
|
||||||
|
}
|
||||||
|
#{
|
||||||
|
# platform = "mqtt";
|
||||||
|
# name = "pressure_${name}";
|
||||||
|
# state_topic = "zigbee2mqtt/${name}";
|
||||||
|
# availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
# unit_of_measurement = "hPa";
|
||||||
|
# device_class = "pressure";
|
||||||
|
# value_template = "{{ value_json.pressure }}";
|
||||||
|
#}
|
||||||
|
{
|
||||||
|
name = "battery_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
unit_of_measurement = "%";
|
||||||
|
icon = "mdi:battery-10";
|
||||||
|
value_template = "{{ value_json.battery }}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "link_${name}";
|
||||||
|
platform = "mqtt";
|
||||||
|
state_topic = "zigbee2mqtt/${name}";
|
||||||
|
availability_topic = "zigbee2mqtt/bridge/state";
|
||||||
|
icon = "mdi:signal";
|
||||||
|
unit_of_measurement = "lqi";
|
||||||
|
value_template = "{{ value_json.linkquality }}";
|
||||||
|
}
|
||||||
|
])
|
||||||
|
allDevices);
|
||||||
|
|
||||||
|
# create groups
|
||||||
|
# -------------
|
||||||
|
#group = let
|
||||||
|
# # to have nice panels for every device
|
||||||
|
# sensorGroups = lib.mapAttrs (name:
|
||||||
|
# { ... }: {
|
||||||
|
# entities = [
|
||||||
|
# "sensor.${name}"
|
||||||
|
# "sensor.humidity_${name}"
|
||||||
|
# #"sensor.pressure_${name}"
|
||||||
|
# "sensor.battery_${name}"
|
||||||
|
# "sensor.link_${name}"
|
||||||
|
# ];
|
||||||
|
# }) allDevices;
|
||||||
|
# # sort lights into given groups.
|
||||||
|
# sortedInGroups = let
|
||||||
|
# groupEntries = lib.zipAttrs (lib.flatten (lib.mapAttrsToList (name:
|
||||||
|
# { groups ? [ ], ... }:
|
||||||
|
# map (groupName: { "${groupName}" = "sensor.${name}"; }) groups)
|
||||||
|
# allDevices));
|
||||||
|
# in lib.mapAttrs (name: entities: { inherit entities; }) groupEntries;
|
||||||
|
#in sortedInGroups // sensorGroups // {
|
||||||
|
# all_sensors.entities =
|
||||||
|
# lib.mapAttrsToList (name: { ... }: "sensor.${name}") allDevices;
|
||||||
|
#};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
92
nixos/configs/pepe/mpd.nix
Normal file
92
nixos/configs/pepe/mpd.nix
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
{
|
||||||
|
services.mpd = {
|
||||||
|
enable = true;
|
||||||
|
network.listenAddress = "any";
|
||||||
|
musicDirectory = "/media/syncthing/music-library";
|
||||||
|
playlistDirectory = "/media/syncthing/music-library/playlists";
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups."syncthing".members = [ "mpd" ];
|
||||||
|
|
||||||
|
sound.enable = true;
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
6680 # mopidy
|
||||||
|
6600 # mpd
|
||||||
|
1234 # zeroconf
|
||||||
|
];
|
||||||
|
|
||||||
|
users.users."spotifyd" = {
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets.spotify_pass = {
|
||||||
|
owner = "spotifyd";
|
||||||
|
};
|
||||||
|
sops.secrets.spotify_user = {
|
||||||
|
owner = "spotifyd";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.spotifyd.enable = true;
|
||||||
|
services.spotifyd.config = ''
|
||||||
|
[global]
|
||||||
|
username_cmd = "cat ${config.sops.secrets.spotify_user.path}"
|
||||||
|
password_cmd = "cat ${config.sops.secrets.spotify_pass.path}"
|
||||||
|
backend = "alsa" # use portaudio for macOS [homebrew]
|
||||||
|
# The alsa audio device to stream audio to. To get a
|
||||||
|
# list of valid devices, run `aplay -L`,
|
||||||
|
#device = "alsa_audio_device" # omit for macOS
|
||||||
|
# The alsa mixer used by `spotifyd`.
|
||||||
|
mixer = "PCM" # omit for macOS
|
||||||
|
|
||||||
|
# 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"
|
||||||
|
|
||||||
|
# The volume controller. Each one behaves different to
|
||||||
|
# volume increases. For possible values, run
|
||||||
|
# `spotifyd --help`.
|
||||||
|
volume_controller = "alsa" # use softvol for macOS
|
||||||
|
|
||||||
|
# The name that gets displayed under the connect tab on
|
||||||
|
# official clients. Spaces are not allowed!
|
||||||
|
device_name = "DJane"
|
||||||
|
|
||||||
|
# The audio bitrate. 96, 160 or 320 kbit/s
|
||||||
|
bitrate = 320
|
||||||
|
|
||||||
|
# The directory used to cache audio data. This setting can save
|
||||||
|
# a lot of bandwidth when activated, as it will avoid re-downloading
|
||||||
|
# audio files when replaying them.
|
||||||
|
#
|
||||||
|
# Note: The file path does not get expanded. Environment variables and
|
||||||
|
# shell placeholders like $HOME or ~ don't work!
|
||||||
|
#cache_path = "cache_directory"
|
||||||
|
|
||||||
|
# If set to true, audio data does NOT get cached.
|
||||||
|
no_audio_cache = true
|
||||||
|
|
||||||
|
# Volume on startup between 0 and 100
|
||||||
|
# NOTE: This variable's type will change in v0.4, to a number (instead of string)
|
||||||
|
initial_volume = "90"
|
||||||
|
|
||||||
|
# If set to true, enables volume normalisation between songs.
|
||||||
|
volume_normalisation = false
|
||||||
|
|
||||||
|
# The normalisation pregain that is applied for each song.
|
||||||
|
# normalisation_pregain = -10
|
||||||
|
|
||||||
|
# The port `spotifyd` uses to announce its service over the network.
|
||||||
|
zeroconf_port = 1234
|
||||||
|
|
||||||
|
# The proxy `spotifyd` will use to connect to spotify.
|
||||||
|
#proxy = "http://proxy.example.org:8080"
|
||||||
|
|
||||||
|
# The displayed device type in Spotify clients.
|
||||||
|
# Can be unknown, computer, tablet, smartphone, speaker, t_v,
|
||||||
|
# a_v_r (Audio/Video Receiver), s_t_b (Set-Top Box), and audio_dongle.
|
||||||
|
device_type = "computer"
|
||||||
|
'';
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -17,12 +17,15 @@
|
||||||
#};
|
#};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sops.secrets.syncthing_cert = { };
|
||||||
|
sops.secrets.syncthing_key = { };
|
||||||
|
|
||||||
services.syncthing = {
|
services.syncthing = {
|
||||||
enable = true;
|
enable = true;
|
||||||
openDefaultPorts = true;
|
openDefaultPorts = true;
|
||||||
declarative = {
|
declarative = {
|
||||||
cert = toString <secrets/syncthing/cert.pem>;
|
cert = toString config.sops.secrets.syncthing_cert.path;
|
||||||
key = toString <secrets/syncthing/key.pem>;
|
key = toString config.sops.secrets.syncthing_key.path;
|
||||||
|
|
||||||
overrideFolders = true;
|
overrideFolders = true;
|
||||||
folders = {
|
folders = {
|
24
nixos/configs/pepe/taskwarrior-pushover.nix
Normal file
24
nixos/configs/pepe/taskwarrior-pushover.nix
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
users.users."taskwarrior-pushover".isSystemUser = true;
|
||||||
|
|
||||||
|
sops.secrets.pushoverApiToken.owner = "taskwarrior-pushover";
|
||||||
|
sops.secrets.pushoverUserKey.owner = "taskwarrior-pushover";
|
||||||
|
sops.secrets.taskwarriorCa.owner = "taskwarrior-pushover";
|
||||||
|
sops.secrets.taskwarriorCertificate.owner = "taskwarrior-pushover";
|
||||||
|
sops.secrets.taskwarriorKey.owner = "taskwarrior-pushover";
|
||||||
|
|
||||||
|
services.taskwarrior-pushover = {
|
||||||
|
enable = true;
|
||||||
|
recurrence = "on";
|
||||||
|
onCalendar = "06:30:00";
|
||||||
|
server = "taskd.ingolf-wagner.de:53589";
|
||||||
|
pushoverApiTokenFile = config.sops.secrets.pushoverApiToken.path;
|
||||||
|
pushoverUserKeyFile = config.sops.secrets.pushoverUserKey.path;
|
||||||
|
caFile = config.sops.secrets.taskwarriorCa.path;
|
||||||
|
certificateFile = config.sops.secrets.taskwarriorCertificate.path;
|
||||||
|
keyFile = config.sops.secrets.taskwarriorKey.path;
|
||||||
|
credentials = "1337/palo/ed0fdbe8-2dc3-408b-84cb-d07d363bccd2";
|
||||||
|
};
|
||||||
|
}
|
|
@ -15,4 +15,7 @@ with lib;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sops.secrets.tinc_retiolum_ed25519_key = { };
|
||||||
|
sops.secrets.tinc_retiolum_rsa_key = { };
|
||||||
|
|
||||||
}
|
}
|
|
@ -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, ... }:
|
||||||
{
|
{ }
|
||||||
|
|
||||||
}
|
|
|
@ -1,25 +1,20 @@
|
||||||
{ config, pkgs, lib, ... }: {
|
{ config, pkgs, lib, ... }: {
|
||||||
imports = [
|
imports = [
|
||||||
|
|
||||||
<system/proxy>
|
../../system/proxy
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
|
|
||||||
<system/server/packages.nix>
|
../../system/server/packages.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./tinc.nix
|
./tinc.nix
|
||||||
./codimd.nix
|
./codimd.nix
|
||||||
./bitwarden.nix
|
./bitwarden.nix
|
||||||
#./syncplay.nix
|
#./syncplay.nix
|
||||||
|
./grocy.nix
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
nix = {
|
sops.defaultSopsFile = ../../secrets/sputnik.yaml;
|
||||||
package = pkgs.nixUnstable;
|
|
||||||
extraOptions = ''
|
|
||||||
experimental-features = nix-command flakes
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.hostName = "sputnik";
|
networking.hostName = "sputnik";
|
||||||
networking.useDHCP = true;
|
networking.useDHCP = true;
|
||||||
|
|
||||||
|
@ -40,7 +35,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
services.custom.ssh.sshd.rootKeyFiles =
|
services.custom.ssh.sshd.rootKeyFiles =
|
||||||
[ (toString <secrets/ssh/jenkins_rsa.pub>) ];
|
[ ../../assets/ssh/jenkins.pub ];
|
||||||
|
|
||||||
# make sure ssh is only available trough the tinc
|
# make sure ssh is only available trough the tinc
|
||||||
networking.firewall.extraCommands = ''
|
networking.firewall.extraCommands = ''
|
16
nixos/configs/sputnik/grocy.nix
Normal file
16
nixos/configs/sputnik/grocy.nix
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.grocy = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
culture = "de";
|
||||||
|
currency = "EUR";
|
||||||
|
};
|
||||||
|
hostName = "grocy.ingolf-wagner.de";
|
||||||
|
nginx.enableSSL = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
backup.dirs = [ config.services.grocy.dataDir ];
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||||
# and may be overwritten by future invocations. Please make changes
|
# and may be overwritten by future invocations. Please make changes
|
||||||
# to /etc/nixos/configuration.nix instead.
|
# to /etc/nixos/configuration.nix instead.
|
||||||
{ config, lib, pkgs, ... }:
|
{ modulesPath, config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [ <nixpkgs/nixos/modules/profiles/qemu-guest.nix> ];
|
#imports = [ <nixpkgs/nixos/modules/profiles/qemu-guest.nix> ];
|
||||||
|
imports = [ "${modulesPath}/profiles/qemu-guest.nix" ];
|
||||||
|
|
||||||
boot.initrd.availableKernelModules =
|
boot.initrd.availableKernelModules =
|
||||||
[ "ata_piix" "uhci_hcd" "virtio_pci" "sd_mod" "sr_mod" ];
|
[ "ata_piix" "uhci_hcd" "virtio_pci" "sd_mod" "sr_mod" ];
|
|
@ -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;
|
|
@ -1,6 +1,7 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
|
|
||||||
|
# todo create flake for this
|
||||||
errorPages = pkgs.fetchgit {
|
errorPages = pkgs.fetchgit {
|
||||||
url = "https://git.ingolf-wagner.de/palo/http-errors.git";
|
url = "https://git.ingolf-wagner.de/palo/http-errors.git";
|
||||||
rev = "74b8e4c1d9bbba3db6ad858b888e1867318af1f0";
|
rev = "74b8e4c1d9bbba3db6ad858b888e1867318af1f0";
|
||||||
|
@ -27,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 ];
|
||||||
|
@ -62,6 +64,7 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
"git.ingolf-wagner.de" = {
|
"git.ingolf-wagner.de" = {
|
||||||
listen = [
|
listen = [
|
||||||
{
|
{
|
||||||
|
@ -115,6 +118,21 @@ in {
|
||||||
} // error.locations;
|
} // error.locations;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
"grocy.ingolf-wagner.de" = {
|
||||||
|
listen = [
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 4443;
|
||||||
|
ssl = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
addr = "0.0.0.0";
|
||||||
|
port = 80;
|
||||||
|
ssl = false;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
"paste.ingolf-wagner.de" = {
|
"paste.ingolf-wagner.de" = {
|
||||||
listen = [
|
listen = [
|
||||||
{
|
{
|
||||||
|
@ -358,45 +376,6 @@ in {
|
||||||
} // error.locations;
|
} // error.locations;
|
||||||
};
|
};
|
||||||
|
|
||||||
#"home.ingolf-wagner.de" = {
|
|
||||||
# listen = [
|
|
||||||
# {
|
|
||||||
# addr = "0.0.0.0";
|
|
||||||
# port = 4443;
|
|
||||||
# ssl = true;
|
|
||||||
# }
|
|
||||||
# {
|
|
||||||
# addr = "0.0.0.0";
|
|
||||||
# port = 80;
|
|
||||||
# ssl = false;
|
|
||||||
# }
|
|
||||||
# ];
|
|
||||||
# extraConfig = ''
|
|
||||||
# proxy_buffering off;
|
|
||||||
# # client certificate
|
|
||||||
# ssl_client_certificate ${<secrets/client-cert/ca.crt>};
|
|
||||||
# # make verification optional, so we can display a 403 message to those
|
|
||||||
# # who fail authentication
|
|
||||||
# ssl_verify_client optional;
|
|
||||||
# '';
|
|
||||||
# forceSSL = true;
|
|
||||||
# enableACME = true;
|
|
||||||
# locations."/" = {
|
|
||||||
# proxyPass = "http://pepe.private:8123";
|
|
||||||
# proxyWebsockets = true;
|
|
||||||
# extraConfig = ''
|
|
||||||
# # if the client-side certificate failed to authenticate, show a 403
|
|
||||||
# # message to the client
|
|
||||||
# if ($ssl_client_verify != SUCCESS) {
|
|
||||||
# return 403;
|
|
||||||
# }
|
|
||||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
# proxy_set_header Upgrade $http_upgrade;
|
|
||||||
# proxy_set_header Connection $connection_upgrade;
|
|
||||||
# '';
|
|
||||||
# };
|
|
||||||
#};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -461,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}
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue