Refactoring
This commit is contained in:
parent
209526d7c0
commit
8e8041e423
51 changed files with 1414 additions and 1368 deletions
|
|
@ -7,11 +7,11 @@
|
|||
./services
|
||||
];
|
||||
|
||||
networking.hostName = "aluminium";
|
||||
services.openssh.enable = true;
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
|
||||
networking = {
|
||||
hostName = "aluminium";
|
||||
useDHCP = false;
|
||||
vlans = {
|
||||
lechner = {
|
||||
|
|
@ -78,6 +78,15 @@
|
|||
iifname "voice" udp dport 5059 accept
|
||||
ip saddr 217.10.68.150 udp dport 5060 accept
|
||||
'';
|
||||
nftables.tables.pppoe = {
|
||||
family = "ip";
|
||||
content = ''
|
||||
chain clamp {
|
||||
type filter hook forward priority mangle;
|
||||
oifname "ppp0" tcp flags syn tcp option maxseg size set rt mtu comment "clamp MSS to Path MTU"
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -116,16 +125,6 @@
|
|||
};
|
||||
};
|
||||
|
||||
networking.nftables.tables.pppoe = {
|
||||
family = "ip";
|
||||
content = ''
|
||||
chain clamp {
|
||||
type filter hook forward priority mangle;
|
||||
oifname "ppp0" tcp flags syn tcp option maxseg size set rt mtu comment "clamp MSS to Path MTU"
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
zramSwap = {
|
||||
enable = true;
|
||||
algorithm = "zstd";
|
||||
|
|
|
|||
|
|
@ -14,21 +14,6 @@ let
|
|||
voicemail-sounds = pkgs.callPackage ./voicemail-sounds { };
|
||||
in
|
||||
{
|
||||
systemd.services.asterisk-voicemail-sounds = {
|
||||
wantedBy = [ "asterisk.service" ];
|
||||
after = [ "asterisk.service" ];
|
||||
script = ''
|
||||
ln -sfn \
|
||||
${voicemail-sounds}/unavail.wav \
|
||||
/var/spool/asterisk/voicemail/lechner/876/unavail.wav
|
||||
'';
|
||||
restartTriggers = [ voicemail-sounds ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
};
|
||||
|
||||
services.asterisk = {
|
||||
enable = true;
|
||||
confFiles = {
|
||||
|
|
@ -169,12 +154,12 @@ in
|
|||
useTheseDefaultConfFiles = [ ];
|
||||
};
|
||||
|
||||
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"
|
||||
|
|
@ -194,84 +179,99 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
systemd.services."asterisk-reload-endpoint@" = {
|
||||
description = "Check if asterisk endpoint is identified and reload it when it is not.";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
systemd.services = {
|
||||
"asterisk-reload-endpoint@" = {
|
||||
description = "Check if asterisk endpoint is identified and reload it when it is not.";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
};
|
||||
environment = {
|
||||
ENDPOINT = "%I";
|
||||
};
|
||||
script = ''
|
||||
export PATH=${pkgs.lib.makeBinPath [pkgs.asterisk pkgs.gnused pkgs.gnugrep]}
|
||||
if ! asterisk -r -x "pjsip show endpoint $ENDPOINT" | sed -n '/^===/,/^\s*ParameterName/{//!p}' | grep -q 'Identify:'; then
|
||||
asterisk -r -x "module reload res_pjsip_endpoint_identifier_ip.so"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
environment = {
|
||||
ENDPOINT = "%I";
|
||||
asterisk-voicemail-sounds = {
|
||||
wantedBy = [ "asterisk.service" ];
|
||||
after = [ "asterisk.service" ];
|
||||
script = ''
|
||||
ln -sfn \
|
||||
${voicemail-sounds}/unavail.wav \
|
||||
/var/spool/asterisk/voicemail/lechner/876/unavail.wav
|
||||
'';
|
||||
restartTriggers = [ voicemail-sounds ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
};
|
||||
script = ''
|
||||
export PATH=${pkgs.lib.makeBinPath [pkgs.asterisk pkgs.gnused pkgs.gnugrep]}
|
||||
if ! asterisk -r -x "pjsip show endpoint $ENDPOINT" | sed -n '/^===/,/^\s*ParameterName/{//!p}' | grep -q 'Identify:'; then
|
||||
asterisk -r -x "module reload res_pjsip_endpoint_identifier_ip.so"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
"asterisk-voicemail-call@" = {
|
||||
description = "Check if voicemail exists and place a call to the voicemail application.";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
};
|
||||
scriptArgs = "%I";
|
||||
script = ''
|
||||
export PATH=${pkgs.lib.makeBinPath [pkgs.asterisk pkgs.coreutils pkgs.findutils]}
|
||||
number="$(echo "$1" | cut -d ':' -f 1)"
|
||||
user="$(echo "$1" | cut -d ':' -f 2)"
|
||||
channel="PJSIP/$(echo "$1" | cut -d ':' -f 3)"
|
||||
|
||||
systemd.timers.asterisk-reload-endpoint = {
|
||||
description = "Check if asterisk endpoint is identified and reload it when it is not.";
|
||||
after = [ "asterisk.service" ];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
Persistent = true;
|
||||
OnCalendar = "*-*-* *:*:00";
|
||||
Unit = "asterisk-reload-endpoint@sipgate.service";
|
||||
if ! find "/var/spool/asterisk/voicemail/$user/$number/INBOX/" -mindepth 1 -maxdepth 1 | read; then
|
||||
exit
|
||||
fi
|
||||
|
||||
callfile="$(mktemp -p /tmp XXXXXXXXXX.call)"
|
||||
chmod 644 "$callfile"
|
||||
|
||||
cat > "$callfile" << EOF
|
||||
Channel: $channel
|
||||
WaitTime: 15
|
||||
Application: VoiceMailMain
|
||||
Data: $number@$user
|
||||
CallerID: Voicemail
|
||||
EOF
|
||||
|
||||
mv "$callfile" /var/spool/asterisk/outgoing/
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services."asterisk-voicemail-call@" = {
|
||||
description = "Check if voicemail exists and place a call to the voicemail application.";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
systemd.timers = {
|
||||
asterisk-reload-endpoint = {
|
||||
description = "Check if asterisk endpoint is identified and reload it when it is not.";
|
||||
after = [ "asterisk.service" ];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
Persistent = true;
|
||||
OnCalendar = "*-*-* *:*:00";
|
||||
Unit = "asterisk-reload-endpoint@sipgate.service";
|
||||
};
|
||||
};
|
||||
scriptArgs = "%I";
|
||||
script = ''
|
||||
export PATH=${pkgs.lib.makeBinPath [pkgs.asterisk pkgs.coreutils pkgs.findutils]}
|
||||
number="$(echo "$1" | cut -d ':' -f 1)"
|
||||
user="$(echo "$1" | cut -d ':' -f 2)"
|
||||
channel="PJSIP/$(echo "$1" | cut -d ':' -f 3)"
|
||||
|
||||
if ! find "/var/spool/asterisk/voicemail/$user/$number/INBOX/" -mindepth 1 -maxdepth 1 | read; then
|
||||
exit
|
||||
fi
|
||||
|
||||
callfile="$(mktemp -p /tmp XXXXXXXXXX.call)"
|
||||
chmod 644 "$callfile"
|
||||
|
||||
cat > "$callfile" << EOF
|
||||
Channel: $channel
|
||||
WaitTime: 15
|
||||
Application: VoiceMailMain
|
||||
Data: $number@$user
|
||||
CallerID: Voicemail
|
||||
EOF
|
||||
|
||||
mv "$callfile" /var/spool/asterisk/outgoing/
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.timers.asterisk-voicemail-call-10 = {
|
||||
description = "Check if voicemail exists and place a call to the voicemail application.";
|
||||
after = [ "asterisk.service" ];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
Persistent = true;
|
||||
OnCalendar = "*-*-* 07..22:00,20,40:00";
|
||||
Unit = "asterisk-voicemail-call@876:lechner:10.service";
|
||||
asterisk-voicemail-call-10 = {
|
||||
description = "Check if voicemail exists and place a call to the voicemail application.";
|
||||
after = [ "asterisk.service" ];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
Persistent = true;
|
||||
OnCalendar = "*-*-* 07..22:00,20,40:00";
|
||||
Unit = "asterisk-voicemail-call@876:lechner:10.service";
|
||||
};
|
||||
};
|
||||
asterisk-voicemail-call-11 = {
|
||||
description = "Check if voicemail exists and place a call to the voicemail application.";
|
||||
after = [ "asterisk.service" ];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
Persistent = true;
|
||||
OnCalendar = "*-*-* 07..22:00,10,30:50";
|
||||
Unit = "asterisk-voicemail-call@876:lechner:11.service";
|
||||
};
|
||||
};
|
||||
};
|
||||
systemd.timers.asterisk-voicemail-call-11 = {
|
||||
description = "Check if voicemail exists and place a call to the voicemail application.";
|
||||
after = [ "asterisk.service" ];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
Persistent = true;
|
||||
OnCalendar = "*-*-* 07..22:00,10,30:50";
|
||||
Unit = "asterisk-voicemail-call@876:lechner:11.service";
|
||||
};
|
||||
};
|
||||
|
||||
#voicemailCallScript
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,8 +78,8 @@ in
|
|||
unit_system = "metric";
|
||||
time_zone = "Europe/Berlin";
|
||||
temperature_unit = "C";
|
||||
longitude = config.location.longitude;
|
||||
latitude = config.location.latitude;
|
||||
inherit (config.location) longitude;
|
||||
inherit (config.location) latitude;
|
||||
};
|
||||
default_config = { };
|
||||
"automation nix" = [
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@
|
|||
./services
|
||||
];
|
||||
|
||||
services.fstrim.enable = true;
|
||||
|
||||
networking = {
|
||||
hostName = "copper";
|
||||
extraHosts = lib.concatStringsSep "\n" (
|
||||
|
|
@ -32,24 +30,28 @@
|
|||
priority = 1;
|
||||
};
|
||||
|
||||
services.snapper.configs = {
|
||||
home = {
|
||||
SUBVOLUME = "/home";
|
||||
ALLOW_USERS = [ "jalr" ];
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
TIMELINE_LIMIT_HOURLY = 12;
|
||||
TIMELINE_LIMIT_DAILY = 7;
|
||||
TIMELINE_LIMIT_WEEKLY = 4;
|
||||
TIMELINE_LIMIT_MONTHLY = 3;
|
||||
TIMELINE_LIMIT_YEARLY = 0;
|
||||
BACKGROUND_COMPARISON = "yes";
|
||||
NUMBER_CLEANUP = "no";
|
||||
NUMBER_MIN_AGE = "1800";
|
||||
NUMBER_LIMIT = "100";
|
||||
NUMBER_LIMIT_IMPORTANT = "10";
|
||||
EMPTY_PRE_POST_CLEANUP = "yes";
|
||||
EMPTY_PRE_POST_MIN_AGE = "1800";
|
||||
services = {
|
||||
fstrim.enable = true;
|
||||
flatpak.enable = true;
|
||||
snapper.configs = {
|
||||
home = {
|
||||
SUBVOLUME = "/home";
|
||||
ALLOW_USERS = [ "jalr" ];
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
TIMELINE_LIMIT_HOURLY = 12;
|
||||
TIMELINE_LIMIT_DAILY = 7;
|
||||
TIMELINE_LIMIT_WEEKLY = 4;
|
||||
TIMELINE_LIMIT_MONTHLY = 3;
|
||||
TIMELINE_LIMIT_YEARLY = 0;
|
||||
BACKGROUND_COMPARISON = "yes";
|
||||
NUMBER_CLEANUP = "no";
|
||||
NUMBER_MIN_AGE = "1800";
|
||||
NUMBER_LIMIT = "100";
|
||||
NUMBER_LIMIT_IMPORTANT = "10";
|
||||
EMPTY_PRE_POST_CLEANUP = "yes";
|
||||
EMPTY_PRE_POST_MIN_AGE = "1800";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -68,7 +70,5 @@
|
|||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
|
||||
services.flatpak.enable = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{ ... }@inputs:
|
||||
inputs:
|
||||
let
|
||||
hardware = inputs.nixos-hardware.nixosModules;
|
||||
in
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ let
|
|||
luksDev = "-part3";
|
||||
biosBoot = "-part4";
|
||||
};
|
||||
efiSystemPartitions = (map (diskName: diskName + partitionScheme.efiBoot) (lib.attrValues disks));
|
||||
efiSystemPartitions = map (diskName: diskName + partitionScheme.efiBoot) (lib.attrValues disks);
|
||||
in
|
||||
with lib; {
|
||||
imports = [
|
||||
|
|
@ -154,19 +154,19 @@ with lib; {
|
|||
};
|
||||
supportedFilesystems = [ "zfs" ];
|
||||
zfs = {
|
||||
devNodes = devNodes;
|
||||
inherit devNodes;
|
||||
forceImportRoot = false;
|
||||
};
|
||||
loader = {
|
||||
efi = {
|
||||
canTouchEfiVariables = (if removableEfi then false else true);
|
||||
efiSysMountPoint = ("/boot/efis/" + (head (lib.attrValues disks))
|
||||
+ partitionScheme.efiBoot);
|
||||
canTouchEfiVariables = if removableEfi then false else true;
|
||||
efiSysMountPoint = "/boot/efis/" + (head (lib.attrValues disks))
|
||||
+ partitionScheme.efiBoot;
|
||||
};
|
||||
generationsDir.copyKernels = true;
|
||||
grub = {
|
||||
enable = true;
|
||||
devices = (map (diskName: devNodes + diskName) (attrValues disks));
|
||||
devices = map (diskName: devNodes + diskName) (attrValues disks);
|
||||
efiInstallAsRemovable = removableEfi;
|
||||
copyKernels = true;
|
||||
efiSupport = true;
|
||||
|
|
@ -176,11 +176,11 @@ with lib; {
|
|||
terminal_input --append serial
|
||||
terminal_output --append serial
|
||||
'';
|
||||
extraInstallCommands = (toString (map
|
||||
extraInstallCommands = toString (map
|
||||
(diskName: ''
|
||||
${pkgs.coreutils-full}/bin/cp -r ${config.boot.loader.efi.efiSysMountPoint}/EFI /boot/efis/${diskName}${partitionScheme.efiBoot}
|
||||
'')
|
||||
(tail (attrValues disks))));
|
||||
(tail (attrValues disks)));
|
||||
};
|
||||
};
|
||||
kernelParams = [
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@ in
|
|||
services.avahi = {
|
||||
enable = true;
|
||||
allowInterfaces = [ interfaces.lan ];
|
||||
publish.domain = true;
|
||||
publish.enable = true;
|
||||
publish.userServices = true;
|
||||
publish.workstation = true;
|
||||
openFirewall = false;
|
||||
publish = {
|
||||
domain = true;
|
||||
enable = true;
|
||||
userServices = true;
|
||||
workstation = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.interfaces."${interfaces.lan}".allowedUDPPorts = [
|
||||
|
|
|
|||
|
|
@ -8,23 +8,29 @@ in
|
|||
sopsFile = ../secrets.yaml;
|
||||
};
|
||||
|
||||
services.calibre-server = {
|
||||
enable = true;
|
||||
port = ports.calibre-server.tcp;
|
||||
host = "127.0.0.1";
|
||||
};
|
||||
|
||||
services.calibre-web = {
|
||||
enable = true;
|
||||
user = config.services.calibre-server.user;
|
||||
group = config.services.calibre-server.group;
|
||||
listen = {
|
||||
ip = "127.0.0.1";
|
||||
port = ports.calibre-web.tcp;
|
||||
services = {
|
||||
calibre-server = {
|
||||
enable = true;
|
||||
port = ports.calibre-server.tcp;
|
||||
host = "127.0.0.1";
|
||||
};
|
||||
|
||||
calibre-web = {
|
||||
enable = true;
|
||||
inherit (config.services.calibre-server) user;
|
||||
inherit (config.services.calibre-server) group;
|
||||
listen = {
|
||||
ip = "127.0.0.1";
|
||||
port = ports.calibre-web.tcp;
|
||||
};
|
||||
options = {
|
||||
enableBookUploading = true;
|
||||
reverseProxyAuth = {
|
||||
enable = true;
|
||||
header = "X-Remote-User";
|
||||
};
|
||||
};
|
||||
};
|
||||
options.enableBookUploading = true;
|
||||
options.reverseProxyAuth.enable = true;
|
||||
options.reverseProxyAuth.header = "X-Remote-User";
|
||||
};
|
||||
|
||||
systemd.services.calibre-web = {
|
||||
|
|
|
|||
|
|
@ -5,256 +5,264 @@ let
|
|||
domain = "hass.jalr.de";
|
||||
in
|
||||
{
|
||||
sops.secrets.home-assistant = {
|
||||
sopsFile = ../secrets.yaml;
|
||||
owner = "root";
|
||||
group = "hass";
|
||||
mode = "0640";
|
||||
};
|
||||
sops.secrets."mqtt-users/home-assistant" = {
|
||||
sopsFile = ../secrets.yaml;
|
||||
};
|
||||
sops.secrets."mqtt-users/valetudo" = {
|
||||
sopsFile = ../secrets.yaml;
|
||||
};
|
||||
services.home-assistant = {
|
||||
enable = true;
|
||||
lovelaceConfig = {
|
||||
title = "Home";
|
||||
views = [
|
||||
{
|
||||
path = "default_view";
|
||||
title = "Home";
|
||||
cards = [
|
||||
{
|
||||
title = "Eingang";
|
||||
type = "entities";
|
||||
entities = [
|
||||
{
|
||||
entity = "light.eingang_deckenleuchte_deckenleuchte";
|
||||
name = "Deckenleuchte";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
name = "Esstisch";
|
||||
type = "entities";
|
||||
entities = [
|
||||
{
|
||||
entity = "light.yeelight_meteorite_ambient_light";
|
||||
name = "Ambient light";
|
||||
}
|
||||
{
|
||||
entity = "light.yeelight_meteorite_ceiling_light";
|
||||
name = "Ceiling light";
|
||||
}
|
||||
{
|
||||
entity = "light.yeelight_meteorite_night_light";
|
||||
name = "Night light";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
sops.secrets = {
|
||||
home-assistant = {
|
||||
sopsFile = ../secrets.yaml;
|
||||
owner = "root";
|
||||
group = "hass";
|
||||
mode = "0640";
|
||||
};
|
||||
extraComponents = [
|
||||
# See https://www.home-assistant.io/integrations
|
||||
"bthome"
|
||||
"caldav"
|
||||
"esphome"
|
||||
"local_todo"
|
||||
"openweathermap"
|
||||
"wyoming"
|
||||
"xiaomi_ble"
|
||||
"vlc_telnet"
|
||||
];
|
||||
customComponents = with pkgs.home-assistant-custom-components; [
|
||||
adaptive_lighting
|
||||
];
|
||||
customLovelaceModules = with pkgs.home-assistant-custom-lovelace-modules; [
|
||||
valetudo-map-card
|
||||
];
|
||||
lovelaceConfigWritable = false;
|
||||
configWritable = false;
|
||||
config = {
|
||||
http = {
|
||||
server_host = [ "127.0.0.1" ];
|
||||
server_port = ports.home-assistant.tcp;
|
||||
use_x_forwarded_for = true;
|
||||
trusted_proxies = [ "127.0.0.1" ];
|
||||
};
|
||||
homeassistant = {
|
||||
unit_system = "metric";
|
||||
time_zone = "Europe/Berlin";
|
||||
temperature_unit = "C";
|
||||
longitude = config.location.longitude;
|
||||
latitude = config.location.latitude;
|
||||
external_url = "https://${domain}/";
|
||||
internal_url = "https://${domain}/";
|
||||
};
|
||||
default_config = { };
|
||||
adaptive_lighting = {
|
||||
lights = [
|
||||
"light.yeelight_meteorite_ceiling_light"
|
||||
"light.eingang_deckenleuchte_deckenleuchte"
|
||||
"light.led_panel_schreibtisch_panel"
|
||||
"light.kueche_leiste_led_light"
|
||||
"light.badspiegel_background_light"
|
||||
"light.badspiegel_front_light"
|
||||
"mqtt-users/home-assistant" = {
|
||||
sopsFile = ../secrets.yaml;
|
||||
};
|
||||
"mqtt-users/valetudo" = {
|
||||
sopsFile = ../secrets.yaml;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.interfaces = {
|
||||
"${interfaces.lan}".allowedTCPPorts = [ ports.mqtt.tcp ];
|
||||
iot.allowedTCPPorts = [ ports.mqtt.tcp ];
|
||||
};
|
||||
|
||||
services = {
|
||||
home-assistant = {
|
||||
enable = true;
|
||||
lovelaceConfig = {
|
||||
title = "Home";
|
||||
views = [
|
||||
{
|
||||
path = "default_view";
|
||||
title = "Home";
|
||||
cards = [
|
||||
{
|
||||
title = "Eingang";
|
||||
type = "entities";
|
||||
entities = [
|
||||
{
|
||||
entity = "light.eingang_deckenleuchte_deckenleuchte";
|
||||
name = "Deckenleuchte";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
name = "Esstisch";
|
||||
type = "entities";
|
||||
entities = [
|
||||
{
|
||||
entity = "light.yeelight_meteorite_ambient_light";
|
||||
name = "Ambient light";
|
||||
}
|
||||
{
|
||||
entity = "light.yeelight_meteorite_ceiling_light";
|
||||
name = "Ceiling light";
|
||||
}
|
||||
{
|
||||
entity = "light.yeelight_meteorite_night_light";
|
||||
name = "Night light";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
"automation nix" = [
|
||||
{
|
||||
alias = "Waschmaschine fertig Benachrichtigung";
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "sensor.waschmaschine_aktueller_vorgang";
|
||||
to = "Knitterschutz/Ende";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "notify.mobile_app_shift6mq";
|
||||
data = {
|
||||
message = "Die Waschmaschine hat das Programm beendet.";
|
||||
title = "Wäsche fertig";
|
||||
};
|
||||
}
|
||||
extraComponents = [
|
||||
# See https://www.home-assistant.io/integrations
|
||||
"bthome"
|
||||
"caldav"
|
||||
"esphome"
|
||||
"local_todo"
|
||||
"openweathermap"
|
||||
"wyoming"
|
||||
"xiaomi_ble"
|
||||
"vlc_telnet"
|
||||
];
|
||||
customComponents = with pkgs.home-assistant-custom-components; [
|
||||
adaptive_lighting
|
||||
];
|
||||
customLovelaceModules = with pkgs.home-assistant-custom-lovelace-modules; [
|
||||
valetudo-map-card
|
||||
];
|
||||
lovelaceConfigWritable = false;
|
||||
configWritable = false;
|
||||
config = {
|
||||
http = {
|
||||
server_host = [ "127.0.0.1" ];
|
||||
server_port = ports.home-assistant.tcp;
|
||||
use_x_forwarded_for = true;
|
||||
trusted_proxies = [ "127.0.0.1" ];
|
||||
};
|
||||
homeassistant = {
|
||||
unit_system = "metric";
|
||||
time_zone = "Europe/Berlin";
|
||||
temperature_unit = "C";
|
||||
inherit (config.location) longitude;
|
||||
inherit (config.location) latitude;
|
||||
external_url = "https://${domain}/";
|
||||
internal_url = "https://${domain}/";
|
||||
};
|
||||
default_config = { };
|
||||
adaptive_lighting = {
|
||||
lights = [
|
||||
"light.yeelight_meteorite_ceiling_light"
|
||||
"light.eingang_deckenleuchte_deckenleuchte"
|
||||
"light.led_panel_schreibtisch_panel"
|
||||
"light.kueche_leiste_led_light"
|
||||
"light.badspiegel_background_light"
|
||||
"light.badspiegel_front_light"
|
||||
];
|
||||
}
|
||||
];
|
||||
"automation ui" = "!include automations.yaml";
|
||||
"scene nix" = [
|
||||
];
|
||||
"scene ui" = "!include scenes.yaml";
|
||||
bluetooth = { };
|
||||
device_tracker = [
|
||||
{
|
||||
platform = "bluetooth_le_tracker";
|
||||
}
|
||||
];
|
||||
"script nix" = [
|
||||
{
|
||||
lights_off_except = {
|
||||
icon = "mdi:home-lightbulb";
|
||||
fields.exclude_lights.description = "Excluded lights as list";
|
||||
sequence = [
|
||||
};
|
||||
"automation nix" = [
|
||||
{
|
||||
alias = "Waschmaschine fertig Benachrichtigung";
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "sensor.waschmaschine_aktueller_vorgang";
|
||||
to = "Knitterschutz/Ende";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "logbook.log";
|
||||
data_template = {
|
||||
entity_id = "script.turn_off_lights";
|
||||
name = "Exclude log";
|
||||
message = "Turning of all lights except: {{ exclude_lights }}";
|
||||
service = "notify.mobile_app_shift6mq";
|
||||
data = {
|
||||
message = "Die Waschmaschine hat das Programm beendet.";
|
||||
title = "Wäsche fertig";
|
||||
};
|
||||
}
|
||||
{
|
||||
service = "light.turn_off";
|
||||
data_template.entity_id = ''
|
||||
{{ states.light | rejectattr('entity_id', 'in', exclude_lights) | rejectattr('state', 'in', 'off') | join(',', attribute='entity_id') }}
|
||||
'';
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
"automation ui" = "!include automations.yaml";
|
||||
"scene nix" = [
|
||||
];
|
||||
"scene ui" = "!include scenes.yaml";
|
||||
bluetooth = { };
|
||||
device_tracker = [
|
||||
{
|
||||
platform = "bluetooth_le_tracker";
|
||||
}
|
||||
];
|
||||
"script nix" = [
|
||||
{
|
||||
lights_off_except = {
|
||||
icon = "mdi:home-lightbulb";
|
||||
fields.exclude_lights.description = "Excluded lights as list";
|
||||
sequence = [
|
||||
{
|
||||
service = "logbook.log";
|
||||
data_template = {
|
||||
entity_id = "script.turn_off_lights";
|
||||
name = "Exclude log";
|
||||
message = "Turning of all lights except: {{ exclude_lights }}";
|
||||
};
|
||||
}
|
||||
{
|
||||
service = "light.turn_off";
|
||||
data_template.entity_id = ''
|
||||
{{ states.light | rejectattr('entity_id', 'in', exclude_lights) | rejectattr('state', 'in', 'off') | join(',', attribute='entity_id') }}
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
];
|
||||
"script ui" = "!include scripts.yaml";
|
||||
calendar = [
|
||||
{
|
||||
platform = "caldav";
|
||||
username = "jalr@jalr.de";
|
||||
password = "!secret radicale";
|
||||
url = "https://cal.jalr.de/radicale";
|
||||
}
|
||||
];
|
||||
mqtt = { };
|
||||
media_player = [
|
||||
{
|
||||
platform = "mpd";
|
||||
name = "mpd@iron";
|
||||
host = "127.0.0.1";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
mosquitto = {
|
||||
enable = true;
|
||||
persistence = true;
|
||||
listeners = [
|
||||
{
|
||||
port = ports.mqtt.tcp;
|
||||
users = {
|
||||
valetudo = {
|
||||
passwordFile = config.sops.secrets."mqtt-users/valetudo".path;
|
||||
acl = [
|
||||
"readwrite homeassistant/+/donald/#"
|
||||
"readwrite valetudo/donald/#"
|
||||
];
|
||||
};
|
||||
home-assistant = {
|
||||
passwordFile = config.sops.secrets."mqtt-users/home-assistant".path;
|
||||
acl = [ "readwrite #" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
"script ui" = "!include scripts.yaml";
|
||||
calendar = [
|
||||
{
|
||||
platform = "caldav";
|
||||
username = "jalr@jalr.de";
|
||||
password = "!secret radicale";
|
||||
url = "https://cal.jalr.de/radicale";
|
||||
}
|
||||
];
|
||||
mqtt = { };
|
||||
media_player = [
|
||||
{
|
||||
platform = "mpd";
|
||||
name = "mpd@iron";
|
||||
host = "127.0.0.1";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
persistence = true;
|
||||
listeners = [
|
||||
{
|
||||
port = ports.mqtt.tcp;
|
||||
users = {
|
||||
valetudo = {
|
||||
passwordFile = config.sops.secrets."mqtt-users/valetudo".path;
|
||||
acl = [
|
||||
"readwrite homeassistant/+/donald/#"
|
||||
"readwrite valetudo/donald/#"
|
||||
];
|
||||
};
|
||||
home-assistant = {
|
||||
passwordFile = config.sops.secrets."mqtt-users/home-assistant".path;
|
||||
acl = [ "readwrite #" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
systemd.services = {
|
||||
home-assistant.serviceConfig.ExecStartPre = [
|
||||
(
|
||||
pkgs.writeShellScript "home-assistant-secrets" ''
|
||||
ln -sf "${config.sops.secrets.home-assistant.path}" "${config.services.home-assistant.configDir}/secrets.yaml"
|
||||
''
|
||||
)
|
||||
];
|
||||
};
|
||||
|
||||
systemd.services.hass-vlc = {
|
||||
script = ''
|
||||
exec ${pkgs.vlc}/bin/cvlc \
|
||||
--no-video \
|
||||
-I telnet \
|
||||
--telnet-password=vlc \
|
||||
--sout='#transcode{acodec=s16le,channels=2,samplerate=48000}:std{access=file,mux=raw,dst=/run/snapserver/hass.fifo}' \
|
||||
--aout=none
|
||||
'';
|
||||
wants = [ "snapserver.service" ];
|
||||
after = [ "snapserver.service" ];
|
||||
serviceConfig = {
|
||||
BindPaths = [ "/run/snapserver/hass.fifo" ];
|
||||
BindReadOnlyPaths = [ "/nix/store" "/etc/ssl/certs" "/etc/static/ssl/certs" ];
|
||||
CapabilityBoundingSet = "";
|
||||
DynamicUser = "true";
|
||||
Group = "snapserver";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = lib.mkForce true;
|
||||
PrivateUsers = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "noaccess";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
RootDirectory = "/run/hass-vlc";
|
||||
RuntimeDirectory = "hass-vlc";
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [ "@system-service" "~@privileged" ];
|
||||
hass-vlc = {
|
||||
script = ''
|
||||
exec ${pkgs.vlc}/bin/cvlc \
|
||||
--no-video \
|
||||
-I telnet \
|
||||
--telnet-password=vlc \
|
||||
--sout='#transcode{acodec=s16le,channels=2,samplerate=48000}:std{access=file,mux=raw,dst=/run/snapserver/hass.fifo}' \
|
||||
--aout=none
|
||||
'';
|
||||
wants = [ "snapserver.service" ];
|
||||
after = [ "snapserver.service" ];
|
||||
serviceConfig = {
|
||||
BindPaths = [ "/run/snapserver/hass.fifo" ];
|
||||
BindReadOnlyPaths = [ "/nix/store" "/etc/ssl/certs" "/etc/static/ssl/certs" ];
|
||||
CapabilityBoundingSet = "";
|
||||
DynamicUser = "true";
|
||||
Group = "snapserver";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = lib.mkForce true;
|
||||
PrivateUsers = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "noaccess";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
RootDirectory = "/run/hass-vlc";
|
||||
RuntimeDirectory = "hass-vlc";
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [ "@system-service" "~@privileged" ];
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
networking.firewall.interfaces."${interfaces.lan}".allowedTCPPorts = [ ports.mqtt.tcp ];
|
||||
networking.firewall.interfaces.iot.allowedTCPPorts = [ ports.mqtt.tcp ];
|
||||
|
||||
systemd.services.home-assistant.serviceConfig.ExecStartPre = [
|
||||
(
|
||||
pkgs.writeShellScript "home-assistant-secrets" ''
|
||||
ln -sf "${config.sops.secrets.home-assistant.path}" "${config.services.home-assistant.configDir}/secrets.yaml"
|
||||
''
|
||||
)
|
||||
];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass"
|
||||
"f ${config.services.home-assistant.configDir}/scenes.yaml 0755 hass hass"
|
||||
|
|
|
|||
|
|
@ -13,27 +13,27 @@ let
|
|||
};
|
||||
in
|
||||
{
|
||||
sops.secrets = (
|
||||
lib.listToAttrs (map
|
||||
(name: lib.nameValuePair "wireguard_key_${name}" {
|
||||
sopsFile = ../secrets.yaml;
|
||||
})
|
||||
[
|
||||
"hetzner-ha"
|
||||
]
|
||||
)
|
||||
sops.secrets = lib.listToAttrs (map
|
||||
(name: lib.nameValuePair "wireguard_key_${name}" {
|
||||
sopsFile = ../secrets.yaml;
|
||||
})
|
||||
[
|
||||
"hetzner-ha"
|
||||
]
|
||||
);
|
||||
|
||||
networking.iproute2.enable = true;
|
||||
networking.iproute2.rttablesExtraConfig = ''
|
||||
${toString rtTable.id} ${rtTable.name}
|
||||
'';
|
||||
|
||||
networking.wireguard.interfaces = {
|
||||
hetzner-ha = {
|
||||
networking = {
|
||||
iproute2 = {
|
||||
enable = true;
|
||||
rttablesExtraConfig = ''
|
||||
${toString rtTable.id} ${rtTable.name}
|
||||
'';
|
||||
};
|
||||
firewall.allowedUDPPorts = [ listenPort ];
|
||||
wireguard.interfaces.hetzner-ha = {
|
||||
ips = [ "${externalIp}/32" ];
|
||||
privateKeyFile = config.sops.secrets.wireguard_key_hetzner-ha.path;
|
||||
listenPort = listenPort;
|
||||
inherit listenPort;
|
||||
table = rtTable.name;
|
||||
postSetup = ''
|
||||
${pkgs.iproute2}/bin/ip rule add from ${externalIp} to 192.168.0.0/16 table main priority 10
|
||||
|
|
@ -44,7 +44,7 @@ in
|
|||
${pkgs.iproute2}/bin/ip rule del from ${externalIp} table ${rtTable.name} priority 20
|
||||
'';
|
||||
peers = [{
|
||||
publicKey = publicKey;
|
||||
inherit publicKey;
|
||||
endpoint = "${remoteHost}:${toString remotePort}";
|
||||
persistentKeepalive = 25;
|
||||
allowedIPs = [
|
||||
|
|
@ -53,6 +53,4 @@ in
|
|||
}];
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedUDPPorts = [ listenPort ];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,19 +14,21 @@ in
|
|||
enableACME = true;
|
||||
forceSSL = true;
|
||||
basicAuthFile = config.sops.secrets.radicale-htpasswd.path;
|
||||
locations."/radicale/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString ports.radicale.tcp}/";
|
||||
recommendedProxySettings = true;
|
||||
#basicAuthFile = "";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Script-Name /radicale;
|
||||
proxy_set_header X-Remote-User $remote_user;
|
||||
'';
|
||||
# proxy_pass_request_headers = on;
|
||||
# underscores_in_headers = on;
|
||||
locations = {
|
||||
"/radicale/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString ports.radicale.tcp}/";
|
||||
recommendedProxySettings = true;
|
||||
#basicAuthFile = "";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Script-Name /radicale;
|
||||
proxy_set_header X-Remote-User $remote_user;
|
||||
'';
|
||||
# proxy_pass_request_headers = on;
|
||||
# underscores_in_headers = on;
|
||||
};
|
||||
"/.well-known/caldav".return = "301 $scheme://$host:$server_port/radicale";
|
||||
"/.well-known/carddav".return = "301 $scheme://$host:$server_port/radicale";
|
||||
};
|
||||
locations."/.well-known/caldav".return = "301 $scheme://$host:$server_port/radicale";
|
||||
locations."/.well-known/carddav".return = "301 $scheme://$host:$server_port/radicale";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ let
|
|||
ports = import ../ports.nix args;
|
||||
domain = "rmfakecloud.jalr.de";
|
||||
cfg = config.services.rmfakecloud;
|
||||
mkEnvironment = (settings: lib.strings.concatLines (
|
||||
mkEnvironment = settings: lib.strings.concatLines (
|
||||
lib.attrsets.mapAttrsToList (name: value: "export ${name}='${value}'") settings
|
||||
));
|
||||
);
|
||||
managementScript = pkgs.writeShellScriptBin "rmfakecloud" ''
|
||||
[[ $(id -u) == "rmfakecloud" ]] || exec sudo -u rmfakecloud -- "$0" "$@"
|
||||
set -a
|
||||
|
|
|
|||
|
|
@ -24,54 +24,44 @@
|
|||
|
||||
services.blueman.enable = true;
|
||||
|
||||
systemd.services.bluetooth-auto-pair = {
|
||||
wantedBy = [
|
||||
"bluetooth.service"
|
||||
];
|
||||
after = [
|
||||
"bluetooth.service"
|
||||
];
|
||||
bindsTo = [
|
||||
"bluetooth.service"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = pkgs.writeShellScript "exec-start" ''
|
||||
${pkgs.bluez}/bin/bluetoothctl <<EOF
|
||||
discoverable on
|
||||
pairable on
|
||||
EOF
|
||||
systemd.services = {
|
||||
bluetooth-auto-pair = {
|
||||
wantedBy = [ "bluetooth.service" ];
|
||||
after = [ "bluetooth.service" ];
|
||||
bindsTo = [ "bluetooth.service" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = pkgs.writeShellScript "exec-start" ''
|
||||
${pkgs.bluez}/bin/bluetoothctl <<EOF
|
||||
discoverable on
|
||||
pairable on
|
||||
EOF
|
||||
|
||||
${pkgs.coreutils}/bin/yes | ${pkgs.bluez-tools}/bin/bt-agent -c NoInputNoOutput
|
||||
'';
|
||||
ExecStop = pkgs.writeShellScript "exec-stop" ''
|
||||
kill -s SIGINT $MAINPID
|
||||
'';
|
||||
Restart = "on-failure";
|
||||
${pkgs.coreutils}/bin/yes | ${pkgs.bluez-tools}/bin/bt-agent -c NoInputNoOutput
|
||||
'';
|
||||
ExecStop = pkgs.writeShellScript "exec-stop" ''
|
||||
kill -s SIGINT $MAINPID
|
||||
'';
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.bluealsa-aplay = {
|
||||
wantedBy = [
|
||||
"multi-user.target"
|
||||
];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.bluez-alsa}/bin/bluealsa-aplay --profile-a2dp --pcm=default:CARD=bluetooth 00:00:00:00:00:00";
|
||||
Restart = "on-failure";
|
||||
SupplementaryGroups = [ "audio" ];
|
||||
bluealsa-aplay = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.bluez-alsa}/bin/bluealsa-aplay --profile-a2dp --pcm=default:CARD=bluetooth 00:00:00:00:00:00";
|
||||
Restart = "on-failure";
|
||||
SupplementaryGroups = [ "audio" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.bluealsa-a2dp = {
|
||||
wantedBy = [
|
||||
"multi-user.target"
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.bluez-alsa}/bin/bluealsa -p a2dp-sink";
|
||||
Restart = "on-failure";
|
||||
bluealsa-a2dp = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.bluez-alsa}/bin/bluealsa -p a2dp-sink";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,50 +30,52 @@ in
|
|||
|
||||
jalr.libvirt.enable = true;
|
||||
|
||||
systemd.services.libvirt-guests.serviceConfig.ExecStop = [
|
||||
""
|
||||
"${shutdownAndroidVm} ${vmName}"
|
||||
"${pkgs.libvirt}/libexec/libvirt-guests.sh stop"
|
||||
];
|
||||
systemd.services = {
|
||||
libvirt-guests.serviceConfig.ExecStop = [
|
||||
""
|
||||
"${shutdownAndroidVm} ${vmName}"
|
||||
"${pkgs.libvirt}/libexec/libvirt-guests.sh stop"
|
||||
];
|
||||
|
||||
systemd.services."whatsapp@" = {
|
||||
description = "Start Android VM, wait for WhatsApp and shut down VM.";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
};
|
||||
environment.VM = "%i";
|
||||
script = ''
|
||||
export PATH=${pkgs.lib.makeBinPath [pkgs.libvirt pkgs.gnused pkgs.android-tools pkgs.coreutils]}
|
||||
"whatsapp@" = {
|
||||
description = "Start Android VM, wait for WhatsApp and shut down VM.";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
};
|
||||
environment.VM = "%i";
|
||||
script = ''
|
||||
export PATH=${pkgs.lib.makeBinPath [pkgs.libvirt pkgs.gnused pkgs.android-tools pkgs.coreutils]}
|
||||
|
||||
domstate="$(virsh domstate "$VM")"
|
||||
domstate="$(virsh domstate "$VM")"
|
||||
|
||||
if [ "$domstate" != "running" ]; then
|
||||
virsh start "$VM"
|
||||
fi
|
||||
|
||||
echo "Wait until IP of Android VM is known"
|
||||
while :; do
|
||||
host="$(virsh -q domifaddr --domain "$VM" | sed -n -r 's#.*ipv4\s*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/[0-9]+$#\1#p')"
|
||||
if [ "$host" ]; then
|
||||
break
|
||||
if [ "$domstate" != "running" ]; then
|
||||
virsh start "$VM"
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
port=5555
|
||||
adb connect "$host:$port"
|
||||
echo "Wait until IP of Android VM is known"
|
||||
while :; do
|
||||
host="$(virsh -q domifaddr --domain "$VM" | sed -n -r 's#.*ipv4\s*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/[0-9]+$#\1#p')"
|
||||
if [ "$host" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "Waiting for WhatsApp"
|
||||
while ! adb -s "$host:$port" shell -- pgrep com.whatsapp > /dev/null; do
|
||||
sleep 1
|
||||
done
|
||||
port=5555
|
||||
adb connect "$host:$port"
|
||||
|
||||
echo "Sleeping..."
|
||||
sleep 5m
|
||||
echo "Waiting for WhatsApp"
|
||||
while ! adb -s "$host:$port" shell -- pgrep com.whatsapp > /dev/null; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "Shutting down Android"
|
||||
adb -s "$host:$port" shell -- reboot -p
|
||||
'';
|
||||
echo "Sleeping..."
|
||||
sleep 5m
|
||||
|
||||
echo "Shutting down Android"
|
||||
adb -s "$host:$port" shell -- reboot -p
|
||||
'';
|
||||
};
|
||||
};
|
||||
systemd.timers."whatsapp-${vmName}" = {
|
||||
description = "Start Android VM to run WhatsApp";
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
boot.initrd.postDeviceCommands =
|
||||
let
|
||||
device = config.disko.devices.disk.virt.content.partitions.linux.device;
|
||||
inherit (config.disko.devices.disk.virt.content.partitions.linux) device;
|
||||
in
|
||||
lib.mkAfter ''
|
||||
mkdir /mnt
|
||||
|
|
@ -14,16 +14,17 @@
|
|||
btrfs subvolume snapshot /mnt/root-blank /mnt/root
|
||||
'';
|
||||
|
||||
services.openssh = {
|
||||
hostKeys = lib.mkForce [{
|
||||
path = "/persist/etc/ssh/ssh_host_ed25519_key";
|
||||
type = "ed25519";
|
||||
}];
|
||||
services = {
|
||||
openssh = {
|
||||
hostKeys = lib.mkForce [{
|
||||
path = "/persist/etc/ssh/ssh_host_ed25519_key";
|
||||
type = "ed25519";
|
||||
}];
|
||||
};
|
||||
forgejo.stateDir = "/persist/var/lib/forgejo";
|
||||
postgresql.dataDir = "/persist/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}";
|
||||
};
|
||||
|
||||
services.forgejo.stateDir = "/persist/var/lib/forgejo";
|
||||
services.postgresql.dataDir = "/persist/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}";
|
||||
|
||||
fileSystems."/persist".neededForBoot = true;
|
||||
environment.persistence."/persist" = {
|
||||
hideMounts = true;
|
||||
|
|
|
|||
|
|
@ -10,44 +10,44 @@ in
|
|||
owner = config.systemd.services.hedgedoc.serviceConfig.User;
|
||||
sopsFile = ../secrets.yaml;
|
||||
};
|
||||
services.hedgedoc = {
|
||||
enable = true;
|
||||
settings =
|
||||
let
|
||||
day = 24 * 60 * 60 * 1000;
|
||||
in
|
||||
{
|
||||
domain = domain;
|
||||
protocolUseSSL = true;
|
||||
csp.enable = true;
|
||||
port = ports.hedgedoc.tcp;
|
||||
db = {
|
||||
dialect = "postgres";
|
||||
host = "/run/postgresql";
|
||||
user = "hedgedoc";
|
||||
database = "hedgedoc";
|
||||
services = {
|
||||
hedgedoc = {
|
||||
enable = true;
|
||||
settings =
|
||||
let
|
||||
day = 24 * 60 * 60 * 1000;
|
||||
in
|
||||
{
|
||||
inherit domain;
|
||||
protocolUseSSL = true;
|
||||
csp.enable = true;
|
||||
port = ports.hedgedoc.tcp;
|
||||
db = {
|
||||
dialect = "postgres";
|
||||
host = "/run/postgresql";
|
||||
user = "hedgedoc";
|
||||
database = "hedgedoc";
|
||||
};
|
||||
allowEmailRegister = false;
|
||||
sessionSecret = config.sops.secrets.hedgedoc-session-secret.path;
|
||||
sessionLife = 90 * day;
|
||||
};
|
||||
allowEmailRegister = false;
|
||||
sessionSecret = config.sops.secrets.hedgedoc-session-secret.path;
|
||||
sessionLife = 90 * day;
|
||||
};
|
||||
postgresql = {
|
||||
enable = true;
|
||||
ensureDatabases = [ "hedgedoc" ];
|
||||
ensureUsers = [{
|
||||
name = "hedgedoc";
|
||||
ensureDBOwnership = true;
|
||||
}];
|
||||
};
|
||||
nginx.virtualHosts."${domain}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://${cfg.settings.host}:${toString cfg.settings.port}";
|
||||
};
|
||||
};
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
ensureDatabases = [ "hedgedoc" ];
|
||||
ensureUsers = [{
|
||||
name = "hedgedoc";
|
||||
ensureDBOwnership = true;
|
||||
}];
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."${domain}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://${cfg.settings.host}:${toString cfg.settings.port}";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,15 +6,13 @@ let
|
|||
publicKey = "GCmQs7upvDYFueEfqD2yJkkOZg3K7YaGluWWzdjsyTo=";
|
||||
in
|
||||
{
|
||||
sops.secrets = (
|
||||
lib.listToAttrs (map
|
||||
(name: lib.nameValuePair "wireguard_key_${name}" {
|
||||
sopsFile = ../secrets.yaml;
|
||||
})
|
||||
[
|
||||
"hetzner-ha"
|
||||
]
|
||||
)
|
||||
sops.secrets = lib.listToAttrs (map
|
||||
(name: lib.nameValuePair "wireguard_key_${name}" {
|
||||
sopsFile = ../secrets.yaml;
|
||||
})
|
||||
[
|
||||
"hetzner-ha"
|
||||
]
|
||||
);
|
||||
|
||||
#boot.kernel.sysctl = {
|
||||
|
|
@ -22,24 +20,27 @@ in
|
|||
# "net.ipv4.conf.hetzner-ha.proxy_arp" = 1;
|
||||
# "net.ipv4.conf.enp1s0.proxy_arp" = 1;
|
||||
#};
|
||||
networking.interfaces.hetzner-ha.proxyARP = true;
|
||||
networking.interfaces.enp1s0.proxyARP = true;
|
||||
|
||||
networking.wireguard.interfaces = {
|
||||
hetzner-ha = {
|
||||
ips = [ ];
|
||||
privateKeyFile = config.sops.secrets.wireguard_key_hetzner-ha.path;
|
||||
listenPort = listenPort;
|
||||
networking = {
|
||||
interfaces = {
|
||||
hetzner-ha.proxyARP = true;
|
||||
enp1s0.proxyARP = true;
|
||||
};
|
||||
firewall.allowedUDPPorts = [ listenPort ];
|
||||
wireguard.interfaces = {
|
||||
hetzner-ha = {
|
||||
ips = [ ];
|
||||
privateKeyFile = config.sops.secrets.wireguard_key_hetzner-ha.path;
|
||||
inherit listenPort;
|
||||
|
||||
peers = [{
|
||||
publicKey = publicKey;
|
||||
persistentKeepalive = 25;
|
||||
allowedIPs = [
|
||||
"159.69.103.126/32"
|
||||
];
|
||||
}];
|
||||
peers = [{
|
||||
inherit publicKey;
|
||||
persistentKeepalive = 25;
|
||||
allowedIPs = [
|
||||
"159.69.103.126/32"
|
||||
];
|
||||
}];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedUDPPorts = [ listenPort ];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,14 @@
|
|||
{
|
||||
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "virtio_pci" "virtio_scsi" "usbhid" "sr_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
boot = {
|
||||
initrd = {
|
||||
availableKernelModules = [ "xhci_pci" "virtio_pci" "virtio_scsi" "usbhid" "sr_mod" ];
|
||||
kernelModules = [ ];
|
||||
};
|
||||
kernelModules = [ ];
|
||||
extraModulePackages = [ ];
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
|
|
|
|||
|
|
@ -23,67 +23,15 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
services.pretix = {
|
||||
enable = true;
|
||||
settings = {
|
||||
pretix = {
|
||||
instance_name = "Digitaler Dienst GmbH";
|
||||
url = "https://${domain}";
|
||||
registration = false;
|
||||
password_reset = true;
|
||||
};
|
||||
locale = {
|
||||
default = "de";
|
||||
timezone = "Europe/Berlin";
|
||||
};
|
||||
mail = {
|
||||
from = "no-reply@tickets.weinturm-open-air.de";
|
||||
};
|
||||
redis.location = "unix:///run/redis-pretix/redis.sock?db=0";
|
||||
celery.backend = "redis+socket:///run/redis-pretix/redis.sock?virtual_host=2";
|
||||
celery.broker = "redis+socket:///run/redis-pretix/redis.sock?virtual_host=1";
|
||||
};
|
||||
nginx = {
|
||||
enable = true;
|
||||
inherit domain;
|
||||
};
|
||||
gunicorn = {
|
||||
extraArgs = [
|
||||
"--workers=${toString gunicornWorkers}"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Add user to `redis-pretix` group
|
||||
# to grant access to /run/redis-pretix/redis.sock
|
||||
users.users.pretix.extraGroups = [ "redis-pretix" ];
|
||||
|
||||
services.pretix-banktool = {
|
||||
enable = true;
|
||||
days = 14;
|
||||
secretsFile = config.sops.secrets.pretix-banktool-cfg.path;
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
|
||||
services.nginx = lib.mkIf cfg.nginx.enable {
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
virtualHosts = {
|
||||
"${cfg.nginx.domain}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
kTLS = true;
|
||||
extraConfig = ''
|
||||
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload' always;
|
||||
more_set_headers Referrer-Policy same-origin;
|
||||
more_set_headers X-Content-Type-Options nosniff;
|
||||
'';
|
||||
serverAliases = extraDomains;
|
||||
};
|
||||
};
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = lib.mkForce "helfer@weinturm-open-air.de";
|
||||
};
|
||||
|
||||
jalr.mailserver = {
|
||||
|
|
@ -101,8 +49,62 @@ in
|
|||
spam.enable = false;
|
||||
};
|
||||
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = lib.mkForce "helfer@weinturm-open-air.de";
|
||||
services = {
|
||||
pretix = {
|
||||
enable = true;
|
||||
settings = {
|
||||
pretix = {
|
||||
instance_name = "Digitaler Dienst GmbH";
|
||||
url = "https://${domain}";
|
||||
registration = false;
|
||||
password_reset = true;
|
||||
};
|
||||
locale = {
|
||||
default = "de";
|
||||
timezone = "Europe/Berlin";
|
||||
};
|
||||
mail = {
|
||||
from = "no-reply@tickets.weinturm-open-air.de";
|
||||
};
|
||||
redis.location = "unix:///run/redis-pretix/redis.sock?db=0";
|
||||
celery.backend = "redis+socket:///run/redis-pretix/redis.sock?virtual_host=2";
|
||||
celery.broker = "redis+socket:///run/redis-pretix/redis.sock?virtual_host=1";
|
||||
};
|
||||
nginx = {
|
||||
enable = true;
|
||||
inherit domain;
|
||||
};
|
||||
gunicorn = {
|
||||
extraArgs = [
|
||||
"--workers=${toString gunicornWorkers}"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
pretix-banktool = {
|
||||
enable = true;
|
||||
days = 14;
|
||||
secretsFile = config.sops.secrets.pretix-banktool-cfg.path;
|
||||
};
|
||||
|
||||
nginx = lib.mkIf cfg.nginx.enable {
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
virtualHosts = {
|
||||
"${cfg.nginx.domain}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
kTLS = true;
|
||||
extraConfig = ''
|
||||
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload' always;
|
||||
more_set_headers Referrer-Policy same-origin;
|
||||
more_set_headers X-Content-Type-Options nosniff;
|
||||
'';
|
||||
serverAliases = extraDomains;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue