aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Wilken2023-12-03 21:48:06 +0100
committerTimo Wilken2023-12-13 19:39:32 +0100
commit91211036d84baa5e15286539ddadbe6b3d6e7b22 (patch)
tree0511988d8fb40648ede92a086a251b5519a3ccfa
parent5be8cd1a02ef562a9a8ee251d3cc401585dd3491 (diff)
Expose Grafana externally
-rwxr-xr-xregenerate-secrets.sh8
-rw-r--r--tw/services/grafana.scm30
-rw-r--r--tw/system/files/grafana/metrics-credentials.enc9
-rw-r--r--tw/system/vin.scm15
4 files changed, 56 insertions, 6 deletions
diff --git a/regenerate-secrets.sh b/regenerate-secrets.sh
index 2aafb7ee..6b31a24c 100755
--- a/regenerate-secrets.sh
+++ b/regenerate-secrets.sh
@@ -9,6 +9,9 @@ encto () {
}
store () {
+ # Overwriting an existing encrypted file will change its content, even if
+ # its decrypted content does not change, so leave it alone.
+ [ -e "$3" ] && return 0
pass show "$2" > /dev/null || return 1
pass show "$2" | head -1 | encto "$1" "$3"
}
@@ -40,3 +43,8 @@ encto lud tw/system/files/mythic-dns.scm.enc << EOF
"$(pass show www/mythic-beasts/dns-lud | sed -rn '/^username: /s///p')" ; username
"$(pass show www/mythic-beasts/dns-lud | head -1)" ; password
EOF
+
+encto vin tw/system/files/grafana/metrics-credentials.enc << EOF
+GF_METRICS_BASIC_AUTH_USERNAME=$(pass show computers/vin/grafana/metrics | sed -rn '/^username: /s///p')
+GF_METRICS_BASIC_AUTH_PASSWORD=$(pass show computers/vin/grafana/metrics | head -1)
+EOF
diff --git a/tw/services/grafana.scm b/tw/services/grafana.scm
index 6555ba62..a796ba19 100644
--- a/tw/services/grafana.scm
+++ b/tw/services/grafana.scm
@@ -6,22 +6,31 @@
#:use-module (gnu services configuration)
#:use-module (gnu services databases)
#:use-module (gnu services shepherd)
+ #:use-module (guix records)
+ #:use-module (tw services web)
#:export (grafana-service-type
grafana-configuration))
;; TODO: Mimir for long-term Prometheus metrics storage?
;; TODO: Store Grafana data in Postgres instead of SQLite?
-;; TODO: Back up /var/lib/grafana, especially grafana.db
(define %grafana-user "grafana")
(define %grafana-uid 472) ; to match container
-;; TODO: reverse proxy to make it accessible at http://vin.wg/grafana?
(define-configuration/no-serialization grafana-configuration
+ ;; TODO: update to 10.2.2
+ ;; https://hub.docker.com/r/grafana/grafana-oss/tags
(container (string "docker.io/grafana/grafana-oss:9.5.2") "Container image to run.")
+ (domain (string "localhost") "The external domain which will resolve to this
+Grafana instance.")
(bind-address (string "0.0.0.0") "The host IP to bind to.")
(host-port (integer 3000) "The port to bind to on the host.")
- (data-path (string "/var/lib/grafana") "The path to store data in, on the host."))
+ (data-path (string "/var/lib/grafana") "The path to store data in, on the host.")
+ (metrics-credentials-file (string "/etc/grafana/metrics-credentials") "The
+file name containing the user name and password to use for basic
+authentication to Grafana's metrics endpoint. These are specified as the
+GF_METRICS_BASIC_AUTH_USERNAME and GF_METRICS_BASIC_AUTH_PASSWORD environment
+variables."))
(define (grafana-accounts config)
(list (user-account
@@ -43,6 +52,7 @@
(list #$(file-append docker-cli "/bin/docker") "run" "--rm" "--network=host"
"--name" "grafana" "--user" '#$%grafana-user
"-v" '#$(format #f "~a:/var/lib/grafana" (grafana-configuration-data-path config))
+ "--env-file" '#$(grafana-configuration-metrics-credentials-file config)
;; https://grafana.com/docs/grafana/latest/setup-grafana/configure-docker/
"-e" "GF_SERVER_PROTOCOL=http" ; use Wireguard for encryption
"-e" '#$(format #f "GF_SERVER_HTTP_ADDR=~a" (grafana-configuration-bind-address config))
@@ -58,11 +68,23 @@
'#$(grafana-configuration-container config))))
(stop #~(make-kill-destructor)))))
+(define (grafana-reverse-proxy config)
+ (match-record config <grafana-configuration> (domain bind-address host-port)
+ (if (string=? domain "localhost") (list)
+ (list (https-reverse-proxy-configuration
+ (domains (list domain))
+ (destination-port host-port)
+ (destination-ip
+ (if (string=? bind-address "0.0.0.0")
+ "127.0.0.1"
+ bind-address)))))))
+
(define grafana-service-type
(service-type
(name 'grafana)
(extensions
(list (service-extension shepherd-root-service-type grafana-shepherd-service)
- (service-extension account-service-type grafana-accounts)))
+ (service-extension account-service-type grafana-accounts)
+ (service-extension https-reverse-proxy-service-type grafana-reverse-proxy)))
(default-value (grafana-configuration))
(description "Grafana server, running under Docker.")))
diff --git a/tw/system/files/grafana/metrics-credentials.enc b/tw/system/files/grafana/metrics-credentials.enc
new file mode 100644
index 00000000..3e1bf1fe
--- /dev/null
+++ b/tw/system/files/grafana/metrics-credentials.enc
@@ -0,0 +1,9 @@
+-----BEGIN AGE ENCRYPTED FILE-----
+YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IC9TV0hVQSBxbVk0
+YTUvTnV6TEI3bmRHSTNiNVZIcUc4OEZtVW9PcXNsczZYYjAya1R3ClRLRXFTdjc1
+djl3SXArQlloc1VENktIbUxJTmRmU0E0MzFjcktKR2dsVGcKLS0tIFAzcXY4VEhY
+R3dLZlh6Vzl3VDYxcW8rNTZwNXl5dG1MZUpESnRvNFBtS28KOJgtJ5BkwrdX+93W
+VGoh3vbzeCWdwOGCTqheJ1wgOGyGmCqSI/itWgydfvYdDyXCtusVZPTnn0Q1sonT
+Ag/4jjm0vBM0LTrhHPHvi8SJIevsEjNhF8TJbTBYPJw4iqRl6WR+ZW3CTQbFZNLA
+f/0x4hTgXVf8wvo=
+-----END AGE ENCRYPTED FILE-----
diff --git a/tw/system/vin.scm b/tw/system/vin.scm
index 65870e1f..c3cbc50c 100644
--- a/tw/system/vin.scm
+++ b/tw/system/vin.scm
@@ -3,6 +3,7 @@
#:use-module (gnu bootloader grub)
#:use-module (gnu packages databases)
#:use-module (gnu services admin) ; unattended-upgrade-service-type
+ #:use-module (gnu services certbot)
#:use-module (gnu services databases)
#:use-module (gnu services docker)
#:use-module (gnu services dbus)
@@ -161,13 +162,19 @@
(encrypted-file (local-file "files/restic/vin-grafana.enc"))
(destination "/etc/restic/vin-grafana")
(user "restic")
- (group "restic"))))))
+ (group "restic"))
+ (secret
+ ;; Set GF_METRICS_BASIC_AUTH_{USERNAME,PASSWORD} variables.
+ (encrypted-file (local-file "files/grafana/metrics-credentials.enc"))
+ (destination "/etc/grafana/metrics-credentials"))))))
;; For running the Grafana docker container.
(service grafana-service-type
(grafana-configuration
+ (domain "grafana.twilken.net")
(data-path "/var/lib/grafana")
- (bind-address (server-wireguard-address host-name))))
+ (bind-address (server-wireguard-address host-name))
+ (metrics-credentials-file "/etc/grafana/metrics-credentials")))
(service docker-service-type) ; required by `grafana-service-type'
(service dbus-root-service-type) ; required by `docker-service-type'
(service elogind-service-type) ; required by `docker-service-type'
@@ -191,6 +198,10 @@
(keep-daily 30)
(keep-monthly -1))))
+ (service certbot-service-type
+ (certbot-configuration
+ (email "letsencrypt@twilken.net")))
+
;; Personal statistics exporter: stores hledger data (and soon location
;; data?) in Postgres for Grafana to read.
(service syncthing-service-type