Compare commits

..

No commits in common. "esphome" and "main" have entirely different histories.

31 changed files with 309 additions and 605 deletions

5
esphome/.gitignore vendored
View file

@ -1,5 +0,0 @@
# Gitignore settings for ESPHome
# This is an example and may include too much for your use-case.
# You can modify this file to suit your needs.
/.esphome/
/secrets.yaml

View file

@ -1,56 +0,0 @@
esphome:
name: "door"
friendly_name: "Door"
platform: ESP32
board: esp-wrover-kit
api:
encryption:
key: !secret apikey_door
ota:
- platform: esphome
password: !secret otapass_door
ethernet:
type: LAN8720
mdc_pin: GPIO23
mdio_pin: GPIO18
clk_mode: GPIO0_IN
phy_addr: 1
power_pin: GPIO16
logger:
output:
- platform: gpio
pin: GPIO2
id: output_relay
button:
- platform: template
name: "door opener"
id: btn_door_opener
icon: mdi:lock-open
on_press:
- output.turn_on: output_relay
- delay: 2s
- output.turn_off: output_relay
time:
- platform: sntp
id: sntp_time
timezone: Europe/Berlin
servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org
wireguard:
address: 10.20.16.2
private_key: !secret wireguard_key_door
peer_endpoint: jalr-bw.duckdns.org
peer_public_key: Ew25M4+OxfBGfW3g98m2chq+TIgWhxpVulrsuFmwOic=
netmask: 255.255.255.252
peer_port: 51001
peer_persistent_keepalive: 120s

View file

@ -1,2 +0,0 @@
└^cЭi5▌V└@#пмkf1▓8г^БdГЦ╦ПЗ╖CУ┴╞jMZп■Щeb0J>│╖╟P╜йpЭД╡ыP*)┤Ё┐╩м║ODж%╔ЮDЧ▌╞╫Ц2╖╠╢о0 ВрюH─▀2─Х vzЪFЭ▌┼?yL║3!┤╝░K║сцс┼Eд,|%tc4ИpZШ⌡ЧД▌#6т═koMx|Еe├┌V_9└S}7р╕в÷Bт┐]Жs°°НШtvax╣╤>p╥И┴j%ZYкДог^Ф_pV║╟[Mh#╩b=щ═3~и:Ф{
└oLOу∙MМtC╓<ar╥ZХ│&Уu╙┌,ы ╣н=z╣Ac╤>╜#lZЕOM═@┤ёЩiл═)Рзu╗ю╖;┘

101
flake.lock generated
View file

@ -7,11 +7,11 @@
]
},
"locked": {
"lastModified": 1745369821,
"narHash": "sha256-mi6cAjuBztm9gFfpiVo6mAn81cCID6nmDXh5Kmyjwyc=",
"lastModified": 1727196810,
"narHash": "sha256-xQzgXRlczZoFfrUdA4nD5qojCQVqpiIk82aYINQZd+U=",
"owner": "nix-community",
"repo": "disko",
"rev": "c5140c6079ff690e85eac0b86e254de16a79a4b7",
"rev": "6d42596a35d34918a905e8539a44d3fc91f42b5b",
"type": "github"
},
"original": {
@ -41,11 +41,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"lastModified": 1726560853,
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"type": "github"
},
"original": {
@ -125,15 +125,16 @@
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
]
"nixpkgs-unstable"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1742649964,
"narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
"lastModified": 1726745158,
"narHash": "sha256-D5AegvGoEjt4rkKedmxlSEmC+nNLMBPWFxvmYnVLhjk=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
"rev": "4e743a6920eab45e8ba0fbe49dc459f1423a4b74",
"type": "github"
},
"original": {
@ -145,11 +146,11 @@
},
"nixos-hardware": {
"locked": {
"lastModified": 1745392233,
"narHash": "sha256-xmqG4MZArM1JNxPJ33s0MtuBzgnaCO9laARoU3AfP8E=",
"lastModified": 1727040444,
"narHash": "sha256-19FNN5QT9Z11ZUMfftRplyNN+2PgcHKb3oq8KMW/hDA=",
"owner": "nixos",
"repo": "nixos-hardware",
"rev": "8bf8a2a0822365bd8f44fd1a19d7ed0a1d629d64",
"rev": "d0cb432a9d28218df11cbd77d984a2a46caeb5ac",
"type": "github"
},
"original": {
@ -161,16 +162,64 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1745279238,
"narHash": "sha256-AQ7M9wTa/Pa/kK5pcGTgX/DGqMHyzsyINfN7ktsI7Fo=",
"lastModified": 1726969270,
"narHash": "sha256-8fnFlXBgM/uSvBlLWjZ0Z0sOdRBesyNdH0+esxqizGc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "9684b53175fc6c09581e94cc85f05ab77464c7e3",
"rev": "23cbb250f3bf4f516a2d0bf03c51a30900848075",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-24.11",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1720386169,
"narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "194846768975b7ad2c4988bdb82572c00222c0d7",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable_2": {
"locked": {
"lastModified": 1725762081,
"narHash": "sha256-vNv+aJUW5/YurRy1ocfvs4q/48yVESwlC/yHzjkZSP8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "dc454045f5b5d814e5862a6d057e7bb5c29edc05",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1726937504,
"narHash": "sha256-bvGoiQBvponpZh8ClUcmJ6QnsNKw0EMrCQJARK3bI1c=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "9357f4f23713673f310988025d9dc261c20e70c6",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
@ -211,6 +260,7 @@
"nix-pre-commit-hooks": "nix-pre-commit-hooks",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs",
"nixpkgs-unstable": "nixpkgs-unstable",
"sbruder-overlay": "sbruder-overlay",
"sops-nix": "sops-nix"
}
@ -229,11 +279,11 @@
"poetry2nix": "poetry2nix"
},
"locked": {
"lastModified": 1743090264,
"narHash": "sha256-0eKQMldOcNBwkzf09zJWf8io3Kd3PjGQSnhpOueWEdk=",
"lastModified": 1719952130,
"narHash": "sha256-j38XlExNwK4ycmoNEdH/dHUd1QGdNvD3gx/UuLY+04Q=",
"owner": "sbruder",
"repo": "nixpkgs-overlay",
"rev": "f107df0aba9e3d582d1c01b40392416e47fb28dd",
"rev": "3487b8ce24d40cc898f3dba0a9af5e028e1d5844",
"type": "github"
},
"original": {
@ -246,14 +296,15 @@
"inputs": {
"nixpkgs": [
"nixpkgs"
]
],
"nixpkgs-stable": "nixpkgs-stable_2"
},
"locked": {
"lastModified": 1745310711,
"narHash": "sha256-ePyTpKEJTgX0gvgNQWd7tQYQ3glIkbqcW778RpHlqgA=",
"lastModified": 1726524647,
"narHash": "sha256-qis6BtOOBBEAfUl7FMHqqTwRLB61OL5OFzIsOmRz2J4=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "5e3e92b16d6fdf9923425a8d4df7496b2434f39c",
"rev": "e2d404a7ea599a013189aa42947f66cede0645c8",
"type": "github"
},
"original": {

View file

@ -1,40 +1,31 @@
{
inputs = {
disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
disko.inputs.nixpkgs.follows = "nixpkgs";
disko.url = "github:nix-community/disko";
flake-utils.url = "github:numtide/flake-utils";
nix-pre-commit-hooks = {
url = "github:cachix/pre-commit-hooks.nix/master";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix/master";
nix-pre-commit-hooks.inputs.flake-utils.follows = "flake-utils";
nix-pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs-unstable";
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11";
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05";
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
nixos-hardware.url = "github:nixos/nixos-hardware/master";
krops = {
url = "github:Mic92/krops";
inputs.flake-utils.follows = "flake-utils";
inputs.nixpkgs.follows = "nixpkgs";
};
krops.url = "github:Mic92/krops";
krops.inputs.flake-utils.follows = "flake-utils";
krops.inputs.nixpkgs.follows = "nixpkgs";
sops-nix = {
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
sops-nix.url = "github:Mic92/sops-nix";
sops-nix.inputs.nixpkgs.follows = "nixpkgs";
sbruder-overlay = {
url = "github:sbruder/nixpkgs-overlay";
inputs = {
flake-utils.follows = "flake-utils";
nix-pre-commit-hooks.follows = "nix-pre-commit-hooks";
nixpkgs.follows = "nixpkgs";
};
};
sbruder-overlay.url = "github:sbruder/nixpkgs-overlay";
sbruder-overlay.inputs.flake-utils.follows = "flake-utils";
sbruder-overlay.inputs.nix-pre-commit-hooks.follows = "nix-pre-commit-hooks";
sbruder-overlay.inputs.nixpkgs.follows = "nixpkgs";
};
outputs =
@ -59,13 +50,8 @@
src = ./.;
hooks = {
black.enable = true;
deadnix.enable = true;
nixpkgs-fmt.enable = true;
shellcheck.enable = true;
statix = {
enable = true;
settings.ignore = [ ".direnv" ];
};
};
};
};
@ -73,13 +59,13 @@
devShells.default = pkgs.mkShell {
name = "fablab-nixos-config";
buildInputs = with pkgs; [
buildInputs = (with pkgs; [
black
nixpkgs-fmt
shellcheck
sops
ssh-to-pgp
];
]);
shellHook = ''
find ${./keys} -type f -print0 | xargs -0 ${pkgs.gnupg}/bin/gpg --quiet --import
@ -87,7 +73,7 @@
};
apps = lib.mapAttrs
(_name: program: { type = "app"; program = toString program; })
(name: program: { type = "app"; program = toString program; })
(flake-utils.lib.flattenTree {
deploy = lib.recurseIntoAttrs (lib.mapAttrs
(hostname: machine:
@ -121,7 +107,7 @@
});
packages = lib.filterAttrs
(_n: v: lib.elem system v.meta.platforms)
(n: v: lib.elem system v.meta.platforms)
(flake-utils.lib.flattenTree {
inherit (pkgs)
fablab;

View file

@ -1,4 +1,4 @@
inputs:
{ ... }@inputs:
let
hardware = inputs.nixos-hardware.nixosModules;
in

View file

@ -9,15 +9,13 @@
nixpkgs.config = { allowAliases = false; };
console.keyMap = "de";
services.xserver.layout = "de";
services.xserver = {
services.xserver.enable = true;
services.xserver.desktopManager.gnome.enable = true;
services.xserver.displayManager.gdm = {
enable = true;
layout = "de";
desktopManager.gnome.enable = true;
displayManager.gdm = {
enable = true;
autoSuspend = false;
};
autoSuspend = false;
};
security.sudo.wheelNeedsPassword = false;

View file

@ -1,4 +1,4 @@
{ modulesPath, ... }:
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [

View file

@ -1,4 +1,4 @@
{ lib, pkgs, ... }:
{ inputs, lib, pkgs, ... }:
let
ledDevices = {
kanister = {

View file

@ -1,4 +1,4 @@
{ config, ... }:
{ config, lib, pkgs, ... }:
{
imports = [
@ -7,11 +7,11 @@
./services
];
networking.hostName = "raven";
time.timeZone = "Etc/UTC";
networking = {
hostName = "raven";
useDHCP = false;
vlans = {
labprod = {
@ -51,7 +51,6 @@
"voip"
];
};
firewall.allowedTCPPorts = [ 80 443 ];
};
i18n.defaultLocale = "en_US.UTF-8";
@ -85,19 +84,12 @@
services.nginx.enable = true;
networking.firewall.allowedTCPPorts = [ 80 443 ];
# FIXME
networking.hosts = {
"192.168.94.1" = [ "raven.lab.fablab-nea.de" "labsync.lab.fablab-nea.de" ];
};
fablab.luksUsbUnlock = {
enable = true;
devices."${config.disko.devices.disk.nvme.content.partitions.luks.content.name}" = {
keyPath = "${config.networking.hostName}.key";
usbDevice = "by-label/RAM_USB";
waitForDevice = 10;
};
};
system.stateVersion = "24.05";
}

View file

@ -1,6 +1,4 @@
{
boot.initrd.systemd.enable = true;
disko.devices = {
disk = {
nvme = {
@ -23,7 +21,7 @@
size = "100%";
content = {
type = "luks";
name = "raven_crypt";
name = "raven-crypt";
settings = {
allowDiscards = true;
};

View file

@ -1,4 +1,4 @@
{ modulesPath, ... }:
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [

View file

@ -4,10 +4,6 @@ asterisk-ari: ENC[AES256_GCM,data:2+X/DRmRlnVraWWEBXWXJ9XpFnRdD0HDlofQ7jaxNpWRKN
asterisk-voicemail: ENC[AES256_GCM,data:4/Kbt/XMUGIIVpF9/KIMIi/Gx344dIleieVWch5J5z1gz2o5cLIF73qCj+vApDzSHcz2gTzMEKwEV6H8ZsxJse27dNBIdVq1n18oSWWAMT1iOomxxzqESLhF+HTtBIEpBVi5y5zwMRXGh/72SxKY9TXv/KHxTMp8aBhNvoCn2ze1VOcBjyNxGda4gGgFAa4LNTzxQ1B6XpfgkjsH2uY0zaAd8rrsXPrPY6TNS7JxrBLKfKshTiJCElJJJA1pCcRe4/yMqCm14J5+n3FvEOnHC+BQHX+ohJYaBcrZblWF5rH/l25BnUgP4UC9ydk3LmQiLpH20+sTWZwi/FojeID0BahdrzOk0tNCTKwNtfFp2QzYvlQPdFRCINb5k1Pz9DNLx7bSv1mvkeGNbd1YdHvEnPwYrQmAae96kg+Vl8PVRqY7ZsMsktcOfqlw8k/W4DK0G6LBA5U9G7JryS5OeS3kMMo4vQzcjU8/eZMl/XwHB0806k63wI7j3wL9Z5+DGmdLX3z3RgtJunELTcayAwerRptuwidm69hbOhmWEwkCcrR42QNVuDD8Qxp/CnwnmwUawUFBOFIBjbQApT9miOmo3e7nY5fjbf4JUbJ9/0JbT7YtZOEU9ymACobX6fweOsYUoWTXprJDwZkln8omaAbP85g4XgGGoltdTk71OviSSfN3DCKfPwPop8GZ9UEBQN9rNUyllVRoTeaweqN2VJnD/ApWj8A22i66R1CPm6ebXLOjClahs/hCKTeYHXPiDjWb5xd9c0fQBlnHaWbVYLtGzBpf0p9oU7DE2KskzZE2TDat8qCdMeqBcpEwUVGqcqq4YWDPy593XZzpG91NYDAb6GbkYHiZw+OQStEFA4SbN4YdwPB0fZN0iW+IOQPfWgUiRj2wAUYRXRpxPQ2ZDh7Ie0oZbJvhx6ulEM8nKI4q4e3pkzF7KjT2z9KzinkhvjqlpU0vfCm4BFMUcKXVskQsiDA9gz4w0m7Ei4HbyDHoUGVCUDtv0W6IfjrEUsBasxcYkown20rip/CwKTPmKy26bz6iHgUAB6f71Ms8sdKr7gHdnzOK3OBm5I+gell6SsdDDfGgQdUHJwSu8XwwJdc7Faai7+wN1stfSglm4PwuoFIH9ucgVyXrAwLJIQ==,iv:QzVHcduZhvQalSgRWRDoTpc20cYLFwzqDedET/XnBWQ=,tag:mrkXZ3J3Hiy2Q7Y06LsBuA==,type:str]
prometheus-htpasswd: ENC[AES256_GCM,data:kUU0TqnVxQ8jLfjUpBje3eGxJw+ItD/YSNhiny1XPM0PDksnOO8Ecbyqm9W5p3WZIFc+h/FH1AsyNdhXdAhbgMNNxjebq2PNbJr/DeMWTxuf1D9q5iYpDrFGuK6r65DeCPvwN1tlTKkzJnLCqy3LLWbziANplMpmoUL7Ay3S2r5UQNgl4QIL,iv:o23da3kSbMAiF6H3zgja95As89aDK/+jWofvw9ZIjj8=,tag:VPB9YD33Xuk8IKxoBVEXdQ==,type:str]
unpoller-password: ENC[AES256_GCM,data:nvbKOzS657tfumP93kNAD2Edw3+BN3xQ,iv:FZ169TIyHrhazji+b2V4o0XvyzqwNelnR4TkKXuNqWg=,tag:62Y1LTlI+2KdSjq8dHiuSQ==,type:str]
nextcloud-adminpass: ENC[AES256_GCM,data:8yX92evqkh5XDuKaPdaOxXX474mE2m5b,iv:2gKYS2s2oW0s4hhug6Y8n+8M9YMxIzcTLAp5gbktfkQ=,tag:eoT892rpSKvReve4Au+uSA==,type:str]
authelia:
jwtSecret: ENC[AES256_GCM,data:SvFGmrW+eYQr3J9xRpo1IT2H54eX58+Li+aT461bwjS0B6cswlLF/l8O2lRduLghXy80bQDYFOzfO8t0ENowhA==,iv:0jODFRL/ic07B8hLY/6LhY/ll+2uYyKbJJZAV2aZ6sw=,tag:oyTdsbRdzheq1VJRg9/PYw==,type:str]
storageEncryptionKey: ENC[AES256_GCM,data:4v2mpLvi3hRfQJCgek7RZmF/y0zb9WjQewckpp8IAOqq+YggFA2QLoDJW1fIINLNe0ACuPBdVCKQlgqt3ecqXQ==,iv:1qOSty0pNXCW5R4vSH4HTSAvQu/YelKVXUQqWfPcFhM=,tag:WZ7oDQSVn44jVyppeMQYUg==,type:str]
sops:
kms: []
gcp_kms: []
@ -23,8 +19,8 @@ sops:
T2VuTEpzYmhESnJZTW5IS3orRk44ODAK/KBOctiKRH5y/zuI4sIKNK9nze6aDOmc
Eg7zjCXX3hvmowFt45rMKODJ56Dy6uJEgu6OWMWV2M87CphyHKA5fg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-12-03T21:53:44Z"
mac: ENC[AES256_GCM,data:HFbHfL1i24LyNx+5QYgcMmBUwfQeZscdPFQHlgtJcM9Tsx/Y0wyn2B/veYR30GepQ0CBhC0IKsBDfL4K6AooqkhhBKHTVBINTn4ec9yholIJoepn4OmM4A6CE3xEkyE/PQwTEtABbJkMeUbLuZ1FcLYSo0vXfe4Jvs79o/svivk=,iv:lYZyVlvBuZrP7wzWWh+hJ1nlUXsLKQHpFhOZuXdQtqA=,tag:uxRhOkrjRFVhJYPsahxEFw==,type:str]
lastmodified: "2023-08-04T10:58:16Z"
mac: ENC[AES256_GCM,data:yRoKVClRcbqFYM06F+83kU9s0KcoiYEx0fpr4DL39YoDDx3ZdX2aYqOEtPCGHKEccFanDsZSI4Q9jG2NEa9IykI9DDjQtci1pcNkt9VaWgPTTo2KzP086ncQHaKHyy109CjugeC2oQYIOBfSiO5b+/SP5fml2N3rhIGzROz2NRA=,iv:JR2MVuIxVhCDsx8kelTu86x4Snf6yqJ7s9vb/3bj24o=,tag:V9BadPHshitupxnAzYF3Nw==,type:str]
pgp:
- created_at: "2024-09-24T19:30:34Z"
enc: |-
@ -58,4 +54,4 @@ sops:
-----END PGP MESSAGE-----
fp: 47E7559E037A35652DBBF8AA8D3C82F9F309F8EC
unencrypted_suffix: _unencrypted
version: 3.9.1
version: 3.7.3

View file

@ -111,12 +111,12 @@ in
ln -s ${cfg.package}/var/lib/asterisk/static-http/core-en_US.xml /var/lib/asterisk/documentation/core-en_US.xml
'';
sops.secrets = lib.listToAttrs (map
sops.secrets = (lib.listToAttrs (map
(name: lib.nameValuePair "asterisk-${name}" {
sopsFile = ../secrets.yaml;
owner = config.users.users.asterisk.name;
})
secretConfigFiles);
secretConfigFiles));
environment.etc = lib.mapAttrs'
(name: _: lib.nameValuePair
"asterisk/${name}.conf"

View file

@ -1,76 +0,0 @@
{ config, ... }:
let
domain = "authelia.fablab-nea.de";
cfg = config.services.authelia.instances.default;
port = 9001;
in
{
sops.secrets = {
"authelia/jwtSecret" = {
sopsFile = ../secrets.yaml;
owner = cfg.user;
};
"authelia/storageEncryptionKey" = {
sopsFile = ../secrets.yaml;
owner = cfg.user;
};
};
services = {
authelia.instances.default = {
enable = true;
settings = {
server.address = "tcp://127.0.0.1:${toString port}/";
access_control = {
default_policy = "one_factor";
};
notifier.filesystem = {
filename = "/var/lib/authelia-${cfg.name}/notif.txt";
};
storage.postgres = {
address = "unix:///run/postgresql";
database = "authelia-${cfg.name}";
username = "authelia-${cfg.name}";
password = "authelia-${cfg.name}";
};
authentication_backend = {
file.path = "/var/lib/authelia-${cfg.name}/user.yml";
};
session = {
cookies = [
{
inherit domain;
authelia_url = "https://${domain}";
name = "authelia_session";
}
];
};
};
secrets = {
jwtSecretFile = config.sops.secrets."authelia/jwtSecret".path;
storageEncryptionKeyFile = config.sops.secrets."authelia/storageEncryptionKey".path;
};
};
postgresql = {
ensureUsers = [{
name = "authelia-${cfg.name}";
ensureDBOwnership = true;
}];
ensureDatabases = [ "authelia-${cfg.name}" ];
};
nginx.virtualHosts."${domain}" = {
enableACME = true;
forceSSL = true;
extraConfig = ''
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
'';
locations."/" = {
proxyPass = "http://127.0.0.1:${toString port}";
recommendedProxySettings = true;
};
};
};
}

View file

@ -1,4 +1,4 @@
{ lib, pkgs, ... }:
{ inputs, lib, pkgs, ... }:
let
ledDevices = {
workbench-1 = {

View file

@ -1,7 +1,6 @@
{
imports = [
./asterisk.nix
./authelia.nix
./colorchord.nix
./dnsmasq.nix
./dyndns.nix
@ -9,7 +8,6 @@
./grafana.nix
./labsync
./mailhog.nix
./nextcloud.nix
./prometheus.nix
./unifi-controller.nix
./wekan.nix

View file

@ -1,4 +1,4 @@
{ config, ... }:
{ config, lib, pkgs, ... }:
let
domain = "grafana.fablab-nea.de";

View file

@ -5,41 +5,37 @@ let
generator_port = 8695;
in
{
services = {
opentracker.enable = true;
services.opentracker.enable = true;
atftpd = {
enable = true;
root = pkgs.runCommand "pxelinux-tftproot" { } ''
mkdir -p $out/pxelinux.cfg
cp ${pkgs.syslinux}/share/syslinux/{ldlinux.c32,libcom32.c32,libutil.c32,lpxelinux.0,vesamenu.c32} $out
cp ${./splash.png} $out/splash.png
cp ${./pxelinux.cfg} $out/pxelinux.cfg/default
# required to serve labsync/labsync.cfg, which is generated dynamically by a docker container
ln -s /opt/docker/tftpgen/data $out/labsync
'';
services.nginx.virtualHosts."labsync.fablab-nea.de" = {
addSSL = true;
enableACME = true;
locations = {
"/generator/".proxyPass = "http://127.0.0.1:${toString generator_port}/";
};
};
services.nginx.virtualHosts."labsync.lab.fablab-nea.de" = {
locations = {
"/" = {
root = "/opt/docker/tftpgen/data";
extraConfig = ''
autoindex on;
'';
};
"/generator/".proxyPass = "http://127.0.0.1:${toString generator_port}/";
};
};
nginx.virtualHosts = {
"labsync.fablab-nea.de" = {
addSSL = true;
enableACME = true;
locations = {
"/generator/".proxyPass = "http://127.0.0.1:${toString generator_port}/";
};
};
"labsync.lab.fablab-nea.de" = {
locations = {
"/" = {
root = "/opt/docker/tftpgen/data";
extraConfig = ''
autoindex on;
'';
};
"/generator/".proxyPass = "http://127.0.0.1:${toString generator_port}/";
};
};
};
services.atftpd = {
enable = true;
root = pkgs.runCommand "pxelinux-tftproot" { } ''
mkdir -p $out/pxelinux.cfg
cp ${pkgs.syslinux}/share/syslinux/{ldlinux.c32,libcom32.c32,libutil.c32,lpxelinux.0,vesamenu.c32} $out
cp ${./splash.png} $out/splash.png
cp ${./pxelinux.cfg} $out/pxelinux.cfg/default
# required to serve labsync/labsync.cfg, which is generated dynamically by a docker container
ln -s /opt/docker/tftpgen/data $out/labsync
'';
};
networking.firewall.allowedTCPPorts = [

View file

@ -1,3 +1,4 @@
{ config, ... }:
{
services.mailhog.enable = true;
}

View file

@ -1,59 +0,0 @@
{ config, pkgs, ... }:
let
domain = "nextcloud.fablab-nea.de";
in
{
sops.secrets.nextcloud-adminpass = {
sopsFile = ../secrets.yaml;
owner = "nextcloud";
group = "nextcloud";
};
services.nextcloud = {
enable = true;
hostName = domain;
#secretFile =
#config.dbpassFile
https = true;
config = {
adminpassFile = config.sops.secrets.nextcloud-adminpass.path;
dbtype = "pgsql";
};
settings = {
overwriteprotocol = "https";
oidc_login_client_id = "nextcloud";
oidc_login_provider_url = "https://keycloak.fablab-nea.de";
oidc_login_attributes = {
id = "preferred_username";
};
oidc_login_scope = "openid profile";
oidc_login_button_text = "Log in with OpenID";
oidc_login_code_challenge_method = "S256";
};
database.createLocally = true;
extraApps =
with config.services.nextcloud.package.packages.apps;
{
inherit
bookmarks
calendar
contacts
deck
tasks
;
}
// {
oidc_login = pkgs.fetchNextcloudApp {
license = "agpl3Plus";
url = "https://github.com/pulsejet/nextcloud-oidc-login/releases/download/v3.2.0/oidc_login.tar.gz";
sha256 = "sha256-DrbaKENMz2QJfbDKCMrNGEZYpUEvtcsiqw9WnveaPZA=";
};
};
extraAppsEnable = true;
};
services.nginx.virtualHosts."${domain}" = {
forceSSL = true;
enableACME = true;
};
}

View file

@ -1,4 +1,4 @@
{ config, lib, ... }:
{ config, lib, pkgs, ... }:
let
domain = "prometheus.fablab-nea.de";
@ -7,139 +7,137 @@ let
mkStaticTarget = target: mkStaticTargets (lib.singleton target);
in
{
services.prometheus.exporters.node.enable = true;
services.prometheus = {
enable = true;
listenAddress = "127.0.0.1";
webExternalUrl = "https://${domain}";
globalConfig = {
scrape_interval = "15s";
evaluation_interval = "15s";
};
extraFlags = [
"--storage.tsdb.retention.time=90d"
"--web.enable-admin-api"
];
alertmanagers = [
{
static_configs = mkStaticTarget "${cfg.alertmanager.listenAddress}:${toString cfg.alertmanager.port}";
path_prefix = "/alertmanager/";
}
];
alertmanager = {
enable = true;
listenAddress = "127.0.0.1";
webExternalUrl = "https://${domain}/alertmanager";
configuration = {
global.resolve_timeout = "2m";
route = {
receiver = "matrix";
group_by = [ "alertname" ];
group_wait = "3m";
};
receivers = [
{
name = "matrix";
webhook_configs = lib.singleton {
url = "http://localhost/webhook";
};
}
];
};
};
scrapeConfigs = [
{
job_name = "prometheus";
static_configs = mkStaticTargets [
"localhost:${toString cfg.port}"
"kleinturmbuehne-router:9100"
];
}
{
job_name = "node";
static_configs = mkStaticTargets [
"127.0.0.1:9100"
];
}
{
job_name = "asterisk";
metrics_path = "/";
static_configs = mkStaticTargets [
"127.0.0.1:8088"
];
}
{
job_name = "mikrotik";
static_configs = mkStaticTargets [
"${cfg.exporters.mikrotik.listenAddress}:${toString cfg.exporters.mikrotik.port}"
];
}
{
job_name = "unifi";
static_configs = mkStaticTargets [
"${cfg.exporters.unpoller.listenAddress}:${toString cfg.exporters.unpoller.port}"
];
}
];
rules =
let
mkAlert = { name, expr, for ? "1m", description ? null }: {
alert = name;
inherit expr for;
annotations = lib.optionalAttrs (description != null) { inherit description; };
};
in
[
(lib.generators.toYAML { } {
groups = lib.singleton {
name = "alert.rules";
rules = map mkAlert [
{
name = "InstanceDown";
expr = ''up == 0'';
description = "Instance {{ $labels.instance }} of job {{ $labels.job }} has been down for
more than 1 minutes.";
}
];
};
})
];
};
sops.secrets.prometheus-htpasswd = {
owner = "nginx";
sopsFile = ../secrets.yaml;
};
services = {
services.nginx.virtualHosts."${domain}" = {
enableACME = true;
forceSSL = true;
prometheus = {
exporters.node.enable = true;
enable = true;
listenAddress = "127.0.0.1";
webExternalUrl = "https://${domain}";
globalConfig = {
scrape_interval = "15s";
evaluation_interval = "15s";
};
extraFlags = [
"--storage.tsdb.retention.time=90d"
"--web.enable-admin-api"
];
alertmanagers = [
{
static_configs = mkStaticTarget "${cfg.alertmanager.listenAddress}:${toString cfg.alertmanager.port}";
path_prefix = "/alertmanager/";
}
];
alertmanager = {
enable = true;
listenAddress = "127.0.0.1";
webExternalUrl = "https://${domain}/alertmanager";
configuration = {
global.resolve_timeout = "2m";
basicAuthFile = config.sops.secrets.prometheus-htpasswd.path;
route = {
receiver = "matrix";
group_by = [ "alertname" ];
group_wait = "3m";
};
locations = {
"/".proxyPass = "http://${cfg.listenAddress}:${toString cfg.port}";
receivers = [
{
name = "matrix";
webhook_configs = lib.singleton {
url = "http://localhost/webhook";
};
}
];
};
};
scrapeConfigs = [
{
job_name = "prometheus";
static_configs = mkStaticTargets [
"localhost:${toString cfg.port}"
"kleinturmbuehne-router:9100"
];
}
{
job_name = "node";
static_configs = mkStaticTargets [
"127.0.0.1:9100"
];
}
{
job_name = "asterisk";
metrics_path = "/";
static_configs = mkStaticTargets [
"127.0.0.1:8088"
];
}
{
job_name = "mikrotik";
static_configs = mkStaticTargets [
"${cfg.exporters.mikrotik.listenAddress}:${toString cfg.exporters.mikrotik.port}"
];
}
{
job_name = "unifi";
static_configs = mkStaticTargets [
"${cfg.exporters.unpoller.listenAddress}:${toString cfg.exporters.unpoller.port}"
];
}
];
rules =
let
mkAlert = { name, expr, for ? "1m", description ? null }: {
alert = name;
inherit expr for;
annotations = lib.optionalAttrs (description != null) { inherit description; };
};
in
[
(lib.generators.toYAML { } {
groups = lib.singleton {
name = "alert.rules";
rules = map mkAlert [
{
name = "InstanceDown";
expr = ''up == 0'';
description = "Instance {{ $labels.instance }} of job {{ $labels.job }} has been down for
more than 1 minutes.";
}
];
};
})
];
"/alertmanager/".proxyPass = "http://${cfg.alertmanager.listenAddress}:${toString cfg.alertmanager.port}";
};
};
prometheus.exporters.mikrotik = {
enable = true;
listenAddress = "127.0.0.1";
configuration = {
devices = [
];
features = {
bgp = true;
dhcp = true;
routes = true;
optics = true;
};
};
};
nginx.virtualHosts."${domain}" = {
enableACME = true;
forceSSL = true;
basicAuthFile = config.sops.secrets.prometheus-htpasswd.path;
locations = {
"/".proxyPass = "http://${cfg.listenAddress}:${toString cfg.port}";
"/alertmanager/".proxyPass = "http://${cfg.alertmanager.listenAddress}:${toString cfg.alertmanager.port}";
services.prometheus.exporters.mikrotik = {
enable = true;
listenAddress = "127.0.0.1";
configuration = {
devices = [
];
features = {
bgp = true;
dhcp = true;
routes = true;
optics = true;
};
};
};

View file

@ -1,11 +1,13 @@
{ config, pkgs, ... }:
let
promCfg = config.services.prometheus;
in
{
services.unifi = {
enable = true;
openFirewall = true;
unifiPackage = pkgs.unifi8;
mongodbPackage = pkgs.mongodb-7_0;
};
networking.firewall.allowedTCPPorts = [ 8443 ];

View file

@ -1,4 +1,4 @@
{ lib, pkgs, ... }:
{ config, lib, pkgs, ... }:
let
serviceName = "wekan";
databaseName = "wekandb";
@ -62,33 +62,31 @@ in
};
# Create the netowrk
systemd.services = {
init-filerun-network-and-files = {
description = "Create the network bridge ${networkName} for WeKan.";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
systemd.services.init-filerun-network-and-files = {
description = "Create the network bridge ${networkName} for WeKan.";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "oneshot";
script =
let podmancli = "${pkgs.podman}/bin/podman";
in ''
if ! ${podmancli} network ls --format '{{ .Name }}' | grep -qFx -- "${networkName}"; then
${podmancli} network create "${networkName}"
else
echo "network already exists"
fi
'';
};
wekan-restart = {
description = "Restart Wekan services.";
serviceConfig = {
Type = "oneshot";
};
script = ''
${pkgs.systemd}/bin/systemctl restart "podman-${databaseName}.service" "podman-${serviceName}.service"
serviceConfig.Type = "oneshot";
script =
let podmancli = "${pkgs.podman}/bin/podman";
in ''
if ! ${podmancli} network ls --format '{{ .Name }}' | grep -qFx -- "${networkName}"; then
${podmancli} network create "${networkName}"
else
echo "network already exists"
fi
'';
};
systemd.services.wekan-restart = {
description = "Restart Wekan services.";
serviceConfig = {
Type = "oneshot";
};
script = ''
${pkgs.systemd}/bin/systemctl restart "podman-${databaseName}.service" "podman-${serviceName}.service"
'';
};
systemd.timers.wekan-restart = {

View file

@ -1,7 +1,6 @@
{
imports = [
./base.nix
./luksusb.nix
./nix.nix
./pipewire.nix
./pubkeys.nix

View file

@ -1,121 +0,0 @@
{ config, lib, ... }:
let
cfg = config.fablab.luksUsbUnlock;
in
{
options.fablab.luksUsbUnlock = with lib; with lib.types; {
enable = mkEnableOption "unlock LUKS volumes with a USB device on boot";
devices = mkOption {
default = { };
example = {
cryptroot = {
keyPath = "/path/to/the/key";
usbDevice = "by-label/MY_USB";
};
};
type = types.attrsOf (types.submodule {
options = {
keyPath = mkOption {
example = "/mykey.key";
description = mdDoc ''
Path to the key file inside the USB device's filesystem.
`/` is relative to the device's filesystem root.
'';
type = types.str;
};
usbDevice = mkOption {
example = "by-label/BOOTKEY";
description = mdDoc ''
Path to the USB device that contains the keys. (Path relative to `/dev/disk/`)
'';
type = types.str;
};
waitForDevice = mkOption {
default = 5;
example = 10;
description = mdDoc ''
How many seconds to wait for the USB device to be detected by the
kernel.
'';
type = types.ints.unsigned;
};
};
});
};
};
config = lib.mkIf cfg.enable (
let
makeUsbDevPath = usbDevice: "/dev/disk/" + usbDevice;
makeMountPath = usbDevice: "/key/" + (builtins.hashString "md5" usbDevice);
usbFsType = "vfat";
mapAttrsNameValue = f: set:
lib.listToAttrs (map f (lib.attrsToList set));
in
{
boot.initrd = {
kernelModules = [ "uas" "usbcore" "usb_storage" "vfat" "nls_cp437" "nls_iso8859_1" ];
systemd.services =
let
makeService = name: { usbDevice, waitForDevice, ... }:
let
usbDevPath = makeUsbDevPath usbDevice;
usbMountPath = makeMountPath usbDevice;
in
{
description = "Mount ${name} key";
wantedBy = [ "cryptsetup.target" ];
before = [ "systemd-cryptsetup@${name}.service" ];
after = [ "systemd-modules-load.service" ];
unitConfig.DefaultDependencies = "no";
serviceConfig.Type = "oneshot";
script = ''
if awk -v mountpoint="${usbMountPath}" '$2==mountpoint {f=1} END {exit !f}' /proc/mounts; then
exit 0
fi
attempts=0
while [ ! -e ${lib.escapeShellArg usbDevPath} ]; do
sleep 1
if [ $attempts -ge ${toString waitForDevice} ]; then
break;
fi
attempts=$((attempts+1))
done
if [ -e ${lib.escapeShellArg usbDevPath} ]; then
mkdir -m0500 -p ${lib.escapeShellArg usbMountPath}
mount \
-n \
-t ${lib.escapeShellArg usbFsType} \
-o ro,fmask=0137,dmask=0027 \
${lib.escapeShellArg usbDevPath} \
${lib.escapeShellArg usbMountPath}
fi
'';
};
in
mapAttrsNameValue
({ name, value }: {
name = "luksusb-${name}";
value = makeService name value;
})
cfg.devices;
luks.devices = builtins.mapAttrs
(_: { keyPath, usbDevice, ... }:
let
usbMountPath = makeMountPath usbDevice;
in
{
keyFile = "${usbMountPath}/${keyPath}";
keyFileTimeout = 1;
})
cfg.devices;
};
}
);
}

View file

@ -27,6 +27,7 @@ in
registry = with inputs; {
nixpkgs.flake = nixpkgs;
nixpkgs-unstable.flake = nixpkgs-unstable;
};
nixPath = [
"nixpkgs=${inputs.nixpkgs}"
@ -50,5 +51,13 @@ in
nixpkgs.overlays = with inputs; [
self.overlays.default
sbruder-overlay.overlays.default
(final: prev: {
unstable = import nixpkgs-unstable {
inherit (config.nixpkgs)
config
overlays
system;
};
})
];
}

View file

@ -1,6 +1,7 @@
{ pkgs, ... }:
{
sound.enable = true;
hardware.pulseaudio.enable = false;
services.pipewire = {

View file

@ -1,8 +1,8 @@
{ lib, ... }:
{
nixpkgs.config.allowUnfreePredicate = pkg: lib.elem (lib.getName pkg) [
nixpkgs.config.allowUnfreePredicate = (pkg: lib.elem (lib.getName pkg) [
"unifi-controller"
"mongodb"
];
]);
}

View file

@ -1,4 +1,4 @@
_final: prev:
final: prev:
let
inherit (prev) callPackage recurseIntoAttrs;
in

View file

@ -5,7 +5,7 @@ pkgs.mkShell {
nativeBuildInputs = with pkgs; [
(pkgs.writeShellScriptBin "nix" ''
exec -a nix ${pkgs.nixVersions.stable}/bin/nix --experimental-features "nix-command flakes" "$@"
exec -a nix ${pkgs.nixUnstable}/bin/nix --experimental-features "nix-command flakes" "$@"
'')
];
}