forked from
lass.pds.lassul.us/superconfig
This repository has no description
3.8 kB
115 lines
1{ config, pkgs, ... }:
2let
3 domain = "where.is.lassul.us";
4 # home-assistant on styx, reached over retiolum (same as hass/proxy.nix).
5 hass = "http://styx.r:8123";
6 entity = "person.lass";
7 stateDir = "/var/lib/where-lassul-us";
8
9 leaflet = pkgs.fetchzip {
10 url = "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz";
11 hash = "sha256-zzU1O3AxsGn+r3/iL7GJr+LAjLozP0NaJ5DXnZvpllI=";
12 };
13
14 webroot = pkgs.runCommand "${domain}-webroot" { } ''
15 mkdir -p $out/leaflet
16 cp ${./index.html} $out/index.html
17 cp ${./at.html} $out/at.html
18 cp ${./maps.js} $out/maps.js
19 cp ${./maps.css} $out/maps.css
20 cp ${leaflet}/dist/leaflet.js ${leaflet}/dist/leaflet.css $out/leaflet/
21 cp -r ${leaflet}/dist/images $out/leaflet/images
22 '';
23
24 # Pull the last 24h of ${entity} from the hass history API and boil it down
25 # to [{t, lat, lon, acc}] for the page. hass returns every state write
26 # (~1000/day), so consecutive identical coordinates are collapsed.
27 fetch = pkgs.writeShellApplication {
28 name = "where-lassul-us-fetch";
29 runtimeInputs = [
30 pkgs.curl
31 pkgs.jq
32 pkgs.coreutils
33 ];
34 text = ''
35 since=$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ)
36 curl -fsS \
37 -H "Authorization: Bearer $(cat "$CREDENTIALS_DIRECTORY/token")" \
38 "${hass}/api/history/period/$since?filter_entity_id=${entity}&significant_changes_only=0" \
39 | jq -c '
40 .[0]
41 | map(select(.attributes.latitude != null))
42 | map({
43 t: .last_updated,
44 lat: .attributes.latitude,
45 lon: .attributes.longitude,
46 acc: .attributes.gps_accuracy,
47 state: .state
48 })
49 | reduce .[] as $p ([];
50 if length > 0 and .[-1].lat == $p.lat and .[-1].lon == $p.lon
51 then .[:-1] + [$p]
52 else . + [$p]
53 end)
54 | { updated: (now | todate), points: . }
55 ' > "${stateDir}/location.json.tmp"
56 mv "${stateDir}/location.json.tmp" "${stateDir}/location.json"
57 '';
58 };
59in
60{
61 imports = [ ../default.nix ];
62
63 clan.core.vars.generators.where-lassul-us = {
64 files.token = { };
65 prompts.token = {
66 description = ''
67 home-assistant long-lived access token (profile -> security ->
68 long-lived access tokens) with read access to ${entity}.
69 '';
70 type = "hidden";
71 persist = true;
72 };
73 script = ''
74 tr -d '\n' < "$prompts/token" > "$out/token"
75 '';
76 };
77
78 # Static user rather than DynamicUser: the latter hides StateDirectory under
79 # /var/lib/private (0700), which nginx cannot traverse.
80 users.users.where-lassul-us = {
81 isSystemUser = true;
82 group = "where-lassul-us";
83 };
84 users.groups.where-lassul-us = { };
85
86 systemd.services.where-lassul-us-fetch = {
87 description = "fetch ${entity} trail from home-assistant for ${domain}";
88 after = [ "network-online.target" ];
89 wants = [ "network-online.target" ];
90 startAt = "*:0/2";
91 serviceConfig = {
92 Type = "oneshot";
93 User = "where-lassul-us";
94 Group = "where-lassul-us";
95 StateDirectory = "where-lassul-us";
96 StateDirectoryMode = "0755";
97 UMask = "0022";
98 LoadCredential = [ "token:${config.clan.core.vars.generators.where-lassul-us.files.token.path}" ];
99 ExecStart = "${fetch}/bin/where-lassul-us-fetch";
100 };
101 };
102
103 services.nginx.virtualHosts.${domain} = {
104 enableACME = true;
105 forceSSL = true;
106 root = webroot;
107 # share landing page: /at#LAT,LON[@UNIXTIME]
108 locations."= /at".tryFiles = "/at.html =404";
109 locations."= /location.json".extraConfig = ''
110 alias ${stateDir}/location.json;
111 default_type application/json;
112 add_header Cache-Control "no-cache";
113 '';
114 };
115}