Added teslamate configuration

This commit is contained in:
Alejandro Angulo 2024-02-05 20:20:02 -08:00
parent 00319bf5ee
commit 478198d88e
Signed by: alejandro-angulo
GPG key ID: 75579581C74554B6
13 changed files with 253 additions and 3 deletions

View file

@ -21,6 +21,13 @@ in {
}; };
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
age.secrets = {
teslamate_db_for_grafana = {
file = ../../../../secrets/teslamate_db.age;
owner = "grafana";
};
};
services.grafana = { services.grafana = {
enable = true; enable = true;
settings.server = { settings.server = {
@ -47,6 +54,49 @@ in {
access = "proxy"; access = "proxy";
url = "http://127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}"; url = "http://127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}";
} }
{
name = "TeslaMate";
type = "postgres";
access = "proxy";
url = "localhost:5432";
user = "teslamate";
database = "teslamate";
secureJsonData = {
password = "$__file{${config.age.secrets.teslamate_db_for_grafana.path}}";
};
jsonData = {
# TODO: Automate this somehow?
postgresVersion = "1400";
sslmode = "disable";
};
}
];
};
dashboards = {
settings.providers = [
{
name = "teslamate";
orgId = 1;
folder = "TeslaMate";
folderUid = "Nr4ofiDZk";
type = "file";
disableDeletion = false;
editable = true;
updateIntervalSeconds = 86400;
options.path = "${pkgs.aa.teslamate-grafana-dashboards}/dashboards";
}
{
name = "teslamate_internal";
orgId = 1;
folder = "TeslaMate/Internal";
folderUid = "Nr5ofiDZk";
type = "file";
disableDeletion = false;
editable = true;
updateIntervalSeconds = 86400;
options.path = "${pkgs.aa.teslamate-grafana-dashboards}/dashboards/internal";
}
]; ];
}; };
}; };

View file

@ -17,6 +17,7 @@ in {
age.secrets = { age.secrets = {
hass_mqtt.file = ../../../../secrets/hass_mqtt.age; hass_mqtt.file = ../../../../secrets/hass_mqtt.age;
theengs_ble_mqtt.file = ../../../../secrets/theengs_ble_mqtt.age; theengs_ble_mqtt.file = ../../../../secrets/theengs_ble_mqtt.age;
teslamate_mqtt.file = ../../../../secrets/teslamate_mqtt.age;
}; };
services.mosquitto = { services.mosquitto = {
@ -28,6 +29,7 @@ in {
acl = [ acl = [
"readwrite home/#" "readwrite home/#"
"readwrite homeassistant/#" "readwrite homeassistant/#"
"read teslamate/#"
]; ];
passwordFile = config.age.secrets.hass_mqtt.path; passwordFile = config.age.secrets.hass_mqtt.path;
}; };
@ -38,6 +40,10 @@ in {
]; ];
passwordFile = config.age.secrets.theengs_ble_mqtt.path; passwordFile = config.age.secrets.theengs_ble_mqtt.path;
}; };
teslamate = {
acl = ["readwrite teslamate/#"];
passwordFile = config.age.secrets.teslamate_mqtt.path;
};
}; };
} }
]; ];

View file

@ -0,0 +1,165 @@
{
options,
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.aa.services.teslamate;
in {
options.aa.services.teslamate = with types; {
enable = mkEnableOption "teslamate";
acmeCertName = mkOption {
type = str;
default = "";
description = ''
If set to a non-empty string, forces SSL with the supplied acme
certificate.
'';
};
user = mkOption {
type = str;
default = "teslamate";
description = ''
The user that should run teslamate
'';
};
group = mkOption {
type = str;
default = "teslamate";
description = ''
The group that should be assigned to the user running teslamate
'';
};
database = {
host = mkOption {
type = str;
default = "127.0.0.1";
description = ''
Database host address
'';
};
name = mkOption {
type = str;
default = "teslamate";
description = ''
The database name
'';
};
user = mkOption {
type = str;
default = "teslamate";
description = ''
The user that should have access to the database
'';
};
passwordFile = mkOption {
type = path;
description = lib.mdDoc ''
A file containing the password corresponding to
{option}`database.user`
'';
};
createDatabase = mkOption {
type = bool;
default = false;
description = ''
Whether to create a local database automatically.
'';
};
};
};
config = mkIf cfg.enable {
age.secrets = {
teslamate_encryption.file = ../../../../secrets/teslamate_encryption.age;
teslamate_mqtt.file = ../../../../secrets/teslamate_mqtt.age;
};
# docker-teslamate is the name of the service generated by the
# `virtualisation.oci-contianers` block below
systemd.services."docker-teslamate" = {
preStart = ''
mkdir -p /var/lib/teslamate
# Create file if it doesn't exist, truncate it if does
touch /var/lib/teslamate/env
echo "" > /var/lib/teslamate/env
chmod 600 /var/lib/teslamate/env
echo ENCRYPTION_KEY="$(cat ${config.age.secrets.teslamate_encryption.path})" >> /var/lib/teslamate/env
echo DATABASE_PASS="$(cat ${cfg.database.passwordFile})" >> /var/lib/teslamate/env
echo MQTT_PASSWORD="$(cat ${config.age.secrets.teslamate_mqtt.path})" >> /var/lib/teslamate/env
'';
};
virtualisation.oci-containers = {
backend = "docker";
containers."teslamate" = {
image = "ghcr.io/teslamate-org/teslamate:latest";
environmentFiles = ["/var/lib/teslamate/env"];
environment = {
# TODO: Make this configurable
PORT = "4000";
DATABASE_USER = cfg.database.user;
DATABASE_NAME = cfg.database.name;
DATABASE_HOST = cfg.database.host;
# TODO: Make this configurable.
MQTT_HOST = "192.168.113.42";
MQTT_USERNAME = "teslamate";
TZ = "America/Los_Angeles";
};
extraOptions = ["--cap-drop=all" "--network=host"];
# TODO: Make this configurable
ports = ["4000:4000"];
};
};
users.users.${cfg.user} = {
isSystemUser = true;
group = cfg.group;
};
users.groups.${cfg.group} = {};
services.postgresql = optionalAttrs cfg.database.createDatabase {
enable = mkDefault true;
ensureDatabases = [cfg.database.name];
ensureUsers = [
{
name = cfg.database.user;
ensureDBOwnership = true;
}
];
};
services.nginx = {
enable = true;
virtualHosts."teslamate.kilonull.com" =
{
locations."/" = {
recommendedProxySettings = true;
proxyWebsockets = true;
# TODO: Make port configurable.
proxyPass = "http://127.0.0.1:4000";
};
}
// lib.optionalAttrs (cfg.acmeCertName != "") {
forceSSL = true;
useACMEHost = cfg.acmeCertName;
};
};
networking.firewall.allowedTCPPorts = [4000];
};
}

View file

@ -6,13 +6,13 @@
}: }:
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
pname = "teslamate-grafana-dashboards"; pname = "teslamate-grafana-dashboards";
version = "1.28.2"; version = "1.28.3";
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "teslamate-org"; owner = "teslamate-org";
repo = "teslamate"; repo = "teslamate";
rev = "v${version}"; rev = "v${version}";
hash = "sha256-CH3u6ijzvVdjfTVu06UcyW4NhVQKeUKtC/j+UeDELNc="; hash = "sha256-Iky9zWb3m/ex/amZw2dP5ZOpFw3uyg0JG6e9PkV+t4A=";
}; };
dontBuild = true; dontBuild = true;

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -12,4 +12,7 @@ in {
"nextcloud_admin.age".publicKeys = [users.me machines.node]; "nextcloud_admin.age".publicKeys = [users.me machines.node];
"theengs_ble_mqtt.age".publicKeys = [users.me machines.pi4]; "theengs_ble_mqtt.age".publicKeys = [users.me machines.pi4];
"hass_mqtt.age".publicKeys = [users.me machines.pi4 machines.node]; "hass_mqtt.age".publicKeys = [users.me machines.pi4 machines.node];
"teslamate_db.age".publicKeys = [users.me machines.node];
"teslamate_mqtt.age".publicKeys = [users.me machines.pi4 machines.node];
"teslamate_encryption.age".publicKeys = [users.me machines.node];
} }

8
secrets/teslamate_db.age Normal file
View file

@ -0,0 +1,8 @@
age-encryption.org/v1
-> piv-p256 UIEGzg A2wMmiESse22Vlfg8lbSUz3t2GwGvTE49WPKV81egU0Z
I/7v83H42x/2hhOMRAbyUNgCY/GugzSHr9y4EFWZ3rc
-> ssh-ed25519 Yk7ehg CVe6AyDEb9Ulg5Zn5GQAoQT8jXBkjAWx6CP847XU118
HIaJ4+oos94I7m1UEEErP2jhYNhAmG8/RRmNZrWSxcE
--- U3FNQyx/Ncl59978k3kMtYKNZayk13gAubt+l5RqFJw
W½ÊSÖ4ÿÐB mHYªÖ܇nú`"ß|´¢wèH¦À
Wˆ4

View file

@ -0,0 +1,7 @@
age-encryption.org/v1
-> piv-p256 UIEGzg AuDH1UtCo2ABWz85Uq+kS9CA/X7ZMk4PwCbtSSMHU1rL
pNyYJm4Boy64z0+T9xW/Emgm3cT3oLXXpqtkSGFuWsE
-> ssh-ed25519 Yk7ehg MlNtvtKwytkGrlcF2kBdYA/X4EaCVxuDCPRLkn9qWgo
cC0+E8s0VAKSBojprhU23IP3q77x/VRS7tbfOpPAa10
--- c0LU0eTiBBo1puXxtpfWQM4iBJODzYZ0dAzGSheQ6Og
ñïËì;¨ðvø;ä×UG•óËDÉ.au¬¸#¬¿†Iüê±ß'<27>ÿ‡ÎI<øI¯´ýviôºÕS9VnÎYþí

BIN
secrets/teslamate_mqtt.age Normal file

Binary file not shown.

Binary file not shown.

View file

@ -8,7 +8,10 @@
./zfs.nix ./zfs.nix
]; ];
age.secrets.cf_dns_kilonull.file = ../../../secrets/cf_dns_kilonull.age; age.secrets = {
cf_dns_kilonull.file = ../../../secrets/cf_dns_kilonull.age;
teslamate_db.file = ../../../secrets/teslamate_db.age;
};
aa = { aa = {
nix.enable = true; nix.enable = true;
@ -47,6 +50,14 @@
remoteTargetDatasets = ["tank/backups"]; remoteTargetDatasets = ["tank/backups"];
remoteTargetPublicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhA+9O2OBMDH1Xnj6isu36df5TOdZG8aEA4JpN2K60e syncoid@gospel"]; remoteTargetPublicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhA+9O2OBMDH1Xnj6isu36df5TOdZG8aEA4JpN2K60e syncoid@gospel"];
}; };
services.teslamate = {
enable = true;
database = {
createDatabase = true;
passwordFile = config.age.secrets.teslamate_db.path;
};
acmeCertName = "kilonull.com";
};
services.gitea = { services.gitea = {
enable = true; enable = true;
acmeCertName = "kilonull.com"; acmeCertName = "kilonull.com";