Home Assistant test setup

Signed-off-by: Magic_RB <magic_rb@redalder.org>
This commit is contained in:
Magic_RB 2022-01-18 00:23:43 +01:00
parent 3d80b2d137
commit 312452014f
No known key found for this signature in database
GPG key ID: 08D5287CC5DDCA0E
12 changed files with 661 additions and 0 deletions

View file

@ -0,0 +1,78 @@
{ nglib, nixpkgs }:
nglib.makeSystem {
system = "x86_64-linux";
name = "nixng-home-assistant";
inherit nixpkgs;
config = ({ pkgs, config, nglib, ... }:
let
ids = config.ids;
in
{
config = {
dumb-init = {
enable = true;
type.services = { };
};
init.services.home-assistant = {
shutdownOnExit = true;
};
services.home-assistant = {
enable = true;
envsubst = true;
customComponents = {
xiaomi_gateway3 = pkgs.fetchFromGitHub {
owner = "AlexxIT";
repo = "XiaomiGateway3";
rev = "v1.6.5";
sha256 = "sha256-RSIJqsbgnktl7zNaxAKUoMjbkrJ1aJTej0vjlCgstJ8=";
} + "/custom_components/xiaomi_gateway3";
};
config = with { inherit (builtins) toString; };
{ default_config = {};
http.server_port = "8123";
logger.default = "info";
homeassistant =
{ name = "Home";
latitude = "\${LATITUDE}";
longitude = "\${LONGTITUDE}";
elevation = "\${ELEVATION}";
# currency = "EUR";
unit_system = "metric";
time_zone = "\${TIME_ZONE}";
internal_url = "http://localhost:8123/";
};
frontend.themes =
{ };
};
package =
(pkgs.home-assistant.override
{ extraComponents =
[ "http"
"homeassistant"
"image"
"person"
"cloud"
"onboarding"
"frontend"
"safe_mode"
"met"
"zha"
"mobile_app"
"dhcp"
"logbook"
"history"
"ssdp"
"mqtt"
];
extraPackages = ps: with ps;
[ xmodem
];
}).overridePythonAttrs (old:
{ doCheck = false;
});
};
};
});
}

33
containers/mosquitto.nix Normal file
View file

@ -0,0 +1,33 @@
{ nglib, nixpkgs }:
nglib.makeSystem {
system = "x86_64-linux";
name = "nixng-mosquitto";
inherit nixpkgs;
config = ({ pkgs, config, nglib, ... }:
let
ids = config.ids;
in
{
config = {
dumb-init = {
enable = true;
type.services = { };
};
init.services.mosquitto = {
shutdownOnExit = true;
};
services.mosquitto = {
enable = true;
config = {
listener =
["1883 0.0.0.0"
({ password_file = "/secrets/mqtt_password";
})
];
};
};
};
});
}

169
containers/postfix.nix Normal file
View file

@ -0,0 +1,169 @@
{ nglib, nixpkgs }:
nglib.makeSystem {
system = "x86_64-linux";
name = "nixng-postfix";
inherit nixpkgs;
config = ({ pkgs, config, ... }:
{
config = {
dumb-init = {
enable = true;
type.services = {};
};
init.services.postfix = {
shutdownOnExit = true;
};
services.postfix = {
enable = true;
masterConfig = {
pickup = {
type = "unix";
private = "n";
chroot = "n";
wakeup = "60";
maxproc = "1";
command = "pickup";
};
cleanup = { type = "unix"; private = "n"; chroot = "n"; maxproc = "0";
command = "cleanup"; };
qmgr = { type = "unix"; private = "n"; chroot = "n"; wakeup = "300";
maxproc = "1"; command = "qmgr"; };
tlsmgr = { type = "unix"; wakeup = "1000?"; maxproc = 1; command = "tlsmgr"; };
rewrite = { type = "unix"; chroot = "n"; command = "trivial-rewrite"; };
bounce = { type = "unix"; chroot = "n"; maxproc = 0; command = "bounce"; };
defer = { type = "unix"; chroot = "n"; maxproc = 0; command = "bounce"; };
trace = { type = "unix"; chroot = "n"; maxproc = 0; command = "bounce"; };
verify = { type = "unix"; chroot = "n"; maxproc = 1; command = "verify"; };
flush = { type = "unix"; chroot = "n"; wakeup = "1000?"; maxproc = "0";
command = "flush"; };
proxymap = { type = "unix"; chroot = "n"; command = "proxymap"; };
proxywrite = { type = "unix"; chroot = "n"; maxproc = "1";
command = "proxymap"; };
smtp = [ { type = "unix"; chroot = "n"; command = "smtp"; }
{ type = "inet"; private = "n"; chroot = "n"; command = "smtpd"; }
];
relay = { type = "unix"; chroot = "n"; command = ''
smtp
-o syslog_name=postfix/$service_name
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
''; };
showq = { type = "unix"; private = "n"; chroot = "n"; command = "showq"; };
error = { type = "unix"; chroot = "n"; command = "error"; };
retry = { type = "unix"; chroot = "n"; command = "error"; };
discard = { type = "unix"; chroot = "n"; command = "discard"; };
local = { type = "unix"; unpriv = "n"; chroot = "n"; command = "local"; };
virtual = { type = "unix"; unpriv = "n"; chroot = "n"; command = "virtual"; };
lmtp = { type = "unix"; chroot = "n"; command = "lmtp"; };
anvil = { type = "unix"; chroot = "n"; maxproc = 1; command = "anvil"; };
scache = { type = "unix"; chroot = "n"; maxproc = 1; command = "scache"; };
postlog =
{ type = "unix-dgram"; private = "n"; chroot = "n"; maxproc = "1";
command = "postlogd"; };
};
mainConfig = {
smptd_banner = [ "$myhostname" "ESMTP" "$mail_name" "(Ubuntu)" ];
biff = "no";
# delay_warning_time = "4h";
append_dot_mydomain = "no";
readme_directory = "no";
compatibility_level = 2;
smtpd_tls_cert_file = "/etc/letsencrypt/live/example.com/fullchain.pem";
smtpd_tls_key_file = "/etc/letsencrypt/live/example.com/privkey.pem";
smtpd_use_tls = "yes";
smtpd_tls_auth_only = "yes";
smtp_tls_security_level = "may";
smtpd_tls_security_level = "may";
smtpd_sasl_security_options = [ "noanonymous" "noplaintext" ];
smtpd_sasl_tls_security_options = "noanonymous";
smtpd_sasl_type = "dovecot";
smtpd_sasl_path = "private/auth";
smtpd_sals_auth_enable = "yes";
smtpd_helo_restrictions =
[ "permit_mynetworks"
"permit_sals_authenticated"
"reject_invalid_helo_hostname"
"reject_non_fqdn_helo_hostname"
];
smtpd_recipient_restrictions =
[ "permit_mynetworks"
"permit_sasl_authenticated"
"reject_non_fqdn_recipient"
"reject_unknown_recipient_domain"
"reject_unlisted_recipient"
"reject_unauth_destination"
];
smtpd_sender_restrictions =
[ "permit_mynetworks"
"permit_sasl_authenticated"
"reject_non_fqdn_sender"
"reject_unknown_sender_domain"
];
smtpd_relay_restrictions =
[ "permit_mynetworks"
"permit_sasl_authenticated"
"defer_unauth_destination"
];
myhostname = "example.org";
alias_maps = "hash:/etc/aliases";
alias_database = "hash:/etc/aliases";
mydoamin = "example.org";
myorigin = "$mydomain";
mydestination = "localhost";
relayhost = "";
mynetworks =
[ "127.0.0.0/8"
"[::ffff:127.0.0.0]/104"
"[::1]/128"
];
mailbox_size_limit = 0;
recipient_delimiter = "+";
inet_interfaces = "all";
inet_protocols = "all";
virtual_transport = "lmtp:unix:private/dovecot-lmtp";
virtual_mailbox_domains = "mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf";
virtual_mailbox_maps = "mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf";
virtual_alias_maps =
[ "mysql:/etc/postfix/mysql-virtual-alias-maps.cf"
"mysql:/etc/postfix/mysql-virtual-email2email.cf"
];
disable_vrfy_command = "yes";
strict_rfc821_envelopes = "yes";
# smtpd_etrn_restrictions = "yes";
# smtpd_reject_unlisted_sender = "yes";
# smtpd_reject_unlisted_recipient = "yes";
smtpd_delay_reject = "yes";
smtpd_helo_required = "yes";
smtp_always_send_ehlo = "yes";
# smtpd_hard_error_limit = 1;
smtpd_timeout = "30s";
smtp_helo_timeout = "15s";
smtp_rcpt_timeout = "15s";
smtpd_recipient_limit = "15s";
minimal_backoff_time = "180s";
maximal_backoff_time = "3h";
invalid_hostname_reject_code = 550;
non_fqdn_reject_code = 550;
unknown_address_reject_code = 550;
unknown_client_reject_code = 550;
unknown_hostname_reject_code = 550;
unverified_recipent_reject_code = 550;
unverified_sender_reject_code = 550;
};
};
};
});
}

View file

@ -0,0 +1,59 @@
{ nglib, nixpkgs }:
nglib.makeSystem {
system = "x86_64-linux";
name = "nixng-zigbee2mqtt";
inherit nixpkgs;
config = ({ pkgs, config, nglib, ... }:
let
ids = config.ids;
in
{
config = {
dumb-init = {
enable = true;
type.services = { };
};
init.services.zigbee2mqtt = {
shutdownOnExit = true;
};
services.zigbee2mqtt = {
enable = true;
user = "root";
envsubst = true;
package = (import (pkgs.fetchFromGitHub {
owner = "NixOS";
repo = "nixpkgs";
rev = "0c408a087b4751c887e463e3848512c12017be25";
sha256 = "sha256-vBVwv3+kPrxbNyfo48cB5cc5/4tq5zlJGas/qw8XNBE=";
}) { inherit (pkgs.stdenv.hostPlatform) system; }).zigbee2mqtt;
config =
{ homeassistant = true;
permit_join = true;
mqtt = {
base_topic = "zigbee2mqtt";
server = "mqtt://localhost:1883";
user = "\${MQTT_USER}";
password = "\${MQTT_PASSWORD}";
};
frontend =
{ port = 8456;
host = "0.0.0.0";
};
advanced =
{ pan_id = 15408;
};
serial.port = "/dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_4c004e9c53c9eb118a9f8b4f1d69213e-if00-port0";
devices = "devices.yaml";
groups = "groups.yaml";
log_level = "debug";
};
};
};
});
}

View file

@ -35,6 +35,9 @@
camptules = (import ./containers/camptules.nix (base // { inherit (inputs) camptules; }));
gitea = import ./containers/gitea.nix base;
minecraft = import ./containers/minecraft.nix base;
mosquitto = import ./containers/mosquitto.nix base;
zigbee2mqtt = import ./containers/zigbee2mqtt.nix base;
home-assistant = import ./containers/home-assistant.nix base;
};
in
{

View file

@ -0,0 +1,3 @@
path "kv/data/home-assistant" {
capabilities = ["read"]
}

View file

@ -0,0 +1,19 @@
type = "csi"
id = "home-assistant_hass"
name = "home-assistant_hass"
plugin_id = "nfs"
capability {
access_mode = "single-node-writer"
attachment_mode = "file-system"
}
context {
server = "blowhole.in.redalder.org"
share = "/var/nfs/home-assistant_hass"
}
mount_options {
fs_type = "nfs"
mount_flags = [ "nolock" ]
}

View file

@ -0,0 +1,19 @@
type = "csi"
id = "home-assistant_mosquitto"
name = "home-assistant_mosquitto"
plugin_id = "nfs"
capability {
access_mode = "single-node-writer"
attachment_mode = "file-system"
}
context {
server = "blowhole.in.redalder.org"
share = "/var/nfs/home-assistant_mosquitto"
}
mount_options {
fs_type = "nfs"
mount_flags = [ "nolock" ]
}

View file

@ -0,0 +1,19 @@
type = "csi"
id = "home-assistant_zigbee2mqtt"
name = "home-assistant_zigbee2mqtt"
plugin_id = "nfs"
capability {
access_mode = "single-node-writer"
attachment_mode = "file-system"
}
context {
server = "blowhole.in.redalder.org"
share = "/var/nfs/home-assistant_zigbee2mqtt"
}
mount_options {
fs_type = "nfs"
mount_flags = [ "nolock" ]
}

View file

@ -0,0 +1,3 @@
path "kv/data/mqtt" {
capabilities = ["read"]
}

View file

@ -0,0 +1,249 @@
job "home-assistant" {
datacenters = [ "homelab-1" ]
type = "service"
constraint {
attribute = "${attr.unique.hostname}"
value = "blowhole"
}
group "zigbee2mqtt" {
count = 1
restart {
attempts = 5
delay = "5s"
}
network {
mode = "bridge"
port "http" {
static = 8456
to = 8456
}
}
volume "home-assistant_zigbee2mqtt" {
type = "csi"
source = "home-assistant_zigbee2mqtt"
read_only = false
attachment_mode = "file-system"
access_mode = "single-node-writer"
}
service {
name = "zigbee2mqtt"
port = "8456"
connect {
sidecar_service {
proxy {
upstreams {
destination_name = "mqtt"
local_bind_port = 1883
datacenter = "homelab-1"
}
}
}
}
}
task "zigbee2mqtt" {
driver = "docker"
vault {
policies = ["zigbee2mqtt-policy"]
}
config {
image = "nixng-zigbee2mqtt:local"
memory_hard_limit = 256
devices = [
{
host_path = "/dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_4c004e9c53c9eb118a9f8b4f1d69213e-if00-port0"
container_path = "/dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_4c004e9c53c9eb118a9f8b4f1d69213e-if00-port0"
}
]
}
resources {
cpu = 128
memory = 128
}
volume_mount {
volume = "home-assistant_zigbee2mqtt"
destination = "/var/zigbee2mqtt"
read_only = false
}
template {
data = <<EOF
{{ with secret "kv/data/zigbee2mqtt" }}
XIAOMI_HUB_ADDRESS={{ .Data.data.xiaomi_hub_address }}
{{ end }}
{{ with secret "kv/data/mqtt" }}
MQTT_PASSWORD={{ .Data.data.password }}
MQTT_USER={{ .Data.data.user }}
{{ end }}
EOF
destination = "secrets/environment"
env = true
perms = "444"
}
}
}
group "mqtt" {
count = 1
restart {
attempts = 5
delay = "5s"
}
network {
mode = "bridge"
}
volume "home-assistant_mosquitto" {
type = "csi"
source = "home-assistant_mosquitto"
read_only = false
attachment_mode = "file-system"
access_mode = "single-node-writer"
}
service {
name = "mqtt"
port = "1883"
connect {
sidecar_service {}
}
}
task "mosquitto" {
driver = "docker"
vault {
policies = ["mosquitto-policy"]
}
config {
image = "nixng-mosquitto:local"
memory_hard_limit = 256
}
resources {
cpu = 128
memory = 128
}
volume_mount {
volume = "home-assistant_mosquitto"
destination = "/var/mosquitto"
read_only = false
}
template {
data = <<EOF
{{ with secret "kv/data/mqtt" }}
{{ .Data.data.user}}:{{ .Data.data.hash }}
{{ end }}
EOF
destination = "secrets/mqtt_password"
perms = "444"
}
}
}
group "home-assistant" {
count = 1
restart {
attempts = 5
delay = "5s"
}
network {
mode = "bridge"
port "http" {
static = 8123
to = 8123
}
}
volume "home-assistant_hass" {
type = "csi"
source = "home-assistant_hass"
read_only = false
attachment_mode = "file-system"
access_mode = "single-node-writer"
}
service {
name = "home-assistant"
port = "8123"
connect {
sidecar_service {
proxy {
upstreams {
destination_name = "mqtt"
local_bind_port = 1883
datacenter = "homelab-1"
}
}
}
}
}
task "home-assistant" {
driver = "docker"
vault {
policies = ["home-assistant-policy"]
}
config {
image = "nixng-home-assistant:local"
memory_hard_limit = 256
}
resources {
cpu = 128
memory = 128
}
volume_mount {
volume = "home-assistant_hass"
destination = "/var/home-assistant"
read_only = false
}
template {
data = <<EOF
{{ with secret "kv/data/home-assistant" }}
LATITUDE={{ .Data.data.latitude }}
LONGTITUDE={{ .Data.data.longtitude }}
ELEVATION={{ .Data.data.elevation }}
TIME_ZONE={{ .Data.data.time_zone }}
{{ end }}
EOF
destination = "secrets/environment"
env = true
perms = "400"
}
}
}
}

View file

@ -0,0 +1,7 @@
path "kv/data/mqtt" {
capabilities = ["read"]
}
path "kv/data/zigbee2mqtt" {
capabilities = ["read"]
}