Merge "bgpwtf/invoice: render SP/GTU codes on invoices"
diff --git a/app/matrix/lib/matrix.libsonnet b/app/matrix/lib/matrix.libsonnet
index 358b0c9..168844a 100644
--- a/app/matrix/lib/matrix.libsonnet
+++ b/app/matrix/lib/matrix.libsonnet
@@ -47,8 +47,8 @@
             riot: "vectorim/riot-web:v1.7.16",
             casProxy: "registry.k0.hswaw.net/q3k/oauth2-cas-proxy:0.1.4",
             appserviceIRC: "matrixdotorg/matrix-appservice-irc:release-0.17.1",
-            # That's v0.8.2 - we just don't trust that host to not re-tag images.
-            appserviceTelegram: "dock.mau.dev/tulir/mautrix-telegram@sha256:9e68eaa80c9e4a75d9a09ec92dc4898b12d48390e01efa4de40ce882a6f7e330",
+            # :latest tag on 2021/04/10.
+            appserviceTelegram: "dock.mau.dev/tulir/mautrix-telegram@sha256:c6e25cb57e1b67027069e8dc2627338df35d156315c004a6f2b34b6aeaa79f77",
             wellKnown: "registry.k0.hswaw.net/q3k/wellknown:1611960794-adbf560851a46ad0e58b42f0daad7ef19535687c",
         },
 
diff --git a/bgpwtf/machines/modules/router.nix b/bgpwtf/machines/modules/router.nix
index a9de59b..88ad004 100644
--- a/bgpwtf/machines/modules/router.nix
+++ b/bgpwtf/machines/modules/router.nix
@@ -48,11 +48,11 @@
   # Enable the OpenSSH daemon.
   services.openssh.enable = true;
   users.users.root.openssh.authorizedKeys.keys = [
-    "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDD4VJXAXEHEXZk2dxNwehneuJcEGkfXG/U7z4fO79vDVIENdedtXQUyLyhZJc5RTEfHhQj66FwIqzl7mzBHd9x9PuDp6QAYXrkVNMj48s6JXqZqBvF6H/weRqFMf4a2TZv+hG8D0kpvmLheCwWAVRls7Jofnp/My+yDd57GMdsbG/yFEf6WPMiOnA7hxdSJSVihCsCSw2p8PD4GhBe8CVt7xIuinhutjm9zYBjV78NT8acjDUfJh0B1ODTjs7nuW1CC4jybSe2j/OU3Yczj4AxRxBNWuFxUq+jBo9BfpbKLh+Tt7re+zBkaicM77KM/oV6943JJxgHNBBOsv9scZE7 q3k@amnesia"
     "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG599UildOrAq+LIOQjKqtGMwjgjIxozI1jtQQRKHtCP q3k@mimeomia"
     "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQb3YQoiYFZLKwvHYKbu1bMqzNeDCAszQhAe1+QI5SLDOotclyY/vFmOReZOsmyMFl71G2d7d+FbYNusUnNNjTxRYQ021tVc+RkMdLJaORRURmQfEFEKbai6QSFTwErXzuoIzyEPK0lbsQuGgqT9WaVnRzHJ2Q/4+qQbxAS34PuR5NqEkmn4G6LMo3OyJ5mwPkCj9lsqz4BcxRaMWFO3mNcwGDfSW+sqgc3E8N6LKrTpZq3ke7xacpQmcG5DU9VO+2QVPdltl9jWbs3gXjmF92YRNOuKPVfAOZBBsp8JOznfx8s9wDgs7RwPmDpjIAJEyoABqW5hlXfqRbTnfnMvuR informatic@InformaticPC"
     "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDGkMgEVwQM8yeuFUYL2TwlJIq9yUNBmHnwce46zeL2PK2CkMz7sxT/om7sp/K5XDiqeD05Nioe+Dr3drP6B8uI33S5NgxPIfaqQsRS+CBEgk6cqFlcdlKETU/DT+/WsdoO173n7mgGeafPInEuQuGDUID0Fl099kIxtqfAhdeZFMM6/szAZEZsElLJ8K6dp1Ni/jmnXCZhjivZH3AZUlnqrmtDG7FY1bgcOfDXAal45LItughGPtrdiigXe9DK2fW3+9DBZZduh5DMJTNlphAZ+nfSrbyHVKUg6WsgMSprur4KdU47q1QwzqqvEj75JcdP1jOWoZi4F6VJDte9Wb9lhD1jGgjxY9O6Gs4CH35bx15W7CN9hgNa0C8NbPJe/fZYIeMZmJ1m7O2xmnYwP8j+t7RNJWu7Pa3Em4mOEXvhBF07Zfq+Ye/4SluoRgADy5eII2x5fFo5EBhInxK0/X8wF6XZvysalVifoCh7T4Edejoi91oAxFgYAxbboXGlod0eEHIi2hla8SM9+IBHOChmgawKBYp2kzAJyAmHNBF+Pah9G4arVCj/axp/SJZDZbJQoI7UT/fJzEtvlb5RWrHXRq+y6IvjpUq4pzpDWW04+9UMqEEXRmhWOakHfEVM9rN8h3aJBflLUBBnh0Z/hVsKNh8bCRHaKtah8TrD9i+wMw== patryk.jakuszew@gmail.com"
     "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC33naG1ptCvUcRWX9cj9wXM1nW1lyQC4SvMJzWlr9aMD96O8hQ2JMkuIUgUJvorAY02QRplQ2BuoVoVkdkzwjMyi1bL3OdgcKo7Z1yByClGTTocqNJYY0lcUb6EJH8+6e6F9ydrQlSxNzL1uCaA7phZr+yPcmAmWbSfioXn98yXNkE0emHxzJv/nypJY56sDCMC2IXDRd8L2goDtPwgPEW7bWfAQdIFMJ75xOidZOTxJ8eqyXLw/kxY5UlyX66jdoYz1sE5XUHuoQl1AOG9UdlMo0aMhUvP4pX5l7r7EnA9OttKMFB3oWqkVK/R6ynZ52YNOU5BZ9V+Ppaj34W0xNu+p0mbHcCtXYCTrf/OU0hcZDbDaNTjs6Vtcm2wYw9iAKX7Tex+eOMwUwlrlcyPNRV5BTot7lGNYfauHCSIuWJKN4NhCLR/NtVNh4/94eKkPTwJsY6XqDcS7q49wPAs4DAH7BJgsbHPOqygVHrY0YYEfz3Pj0HTxJHQMCP/hQX4fXEGt0BjgoVJbXPAQtPyeg0JuxiUg+b4CgVVfQ6R060MlM1BZzhmh+FY5MJH6nJppS0aHYCvSg8Z68NUlCPKy0jpcyfuAIWQWwSGG1O010WShQG2ELsvNdg5/4HVdCGNl5mmoom6JOd72FOZyQlHDFfeQUQRn9HOeCq/c51rK99SQ== bartek@IHM"
     "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICTR292kx/2CNuWYIsZ6gykQ036aBGrmheIuZa6S1D2x implr@thonk"
+    "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGfIRe1nH6vwjQTjqHNnkKAdr1VYqGEeQnqInmf3A6UN ar@khas"
   ];
 }
diff --git a/cluster/kube/k0.libsonnet b/cluster/kube/k0.libsonnet
index f1d4970..57d39d0 100644
--- a/cluster/kube/k0.libsonnet
+++ b/cluster/kube/k0.libsonnet
@@ -356,6 +356,7 @@
                         { namespace: "gerrit", dns: "gerrit.hackerspace.pl" },
                         { namespace: "gitea-prod", dns: "gitea.hackerspace.pl" },
                         { namespace: "hswaw-prod", dns: "*.hackerspace.pl" },
+                        { namespace: "hswaw-prod", dns: "*.hswaw.net" },
                         { namespace: "internet", dns: "internet.hackerspace.pl" },
                         { namespace: "matrix", dns: "matrix.hackerspace.pl" },
                         { namespace: "onlyoffice-prod", dns: "office.hackerspace.pl" },
diff --git a/ops/machines.nix b/ops/machines.nix
index 03cd541..0e63228 100644
--- a/ops/machines.nix
+++ b/ops/machines.nix
@@ -11,7 +11,10 @@
 # To then deploy derivation $d on $machine:
 #
 #    nix-copy-closure --to root@$machine $d
-#    ssh root@$machine $d/bin/switch-to-configuration
+#    ssh root@$machine $d/bin/switch-to-configuration dry-activate
+#    ssh root@$machine $d/bin/switch-to-configuration test
+#    ssh root@$machine nix-env -p /nix/var/nix/profiles/system --set $d
+#    ssh root@$machine $d/bin/switch-to-configuration boot
 #
 # TODO(q3k): merge this with //cluster/clustercfg - this should be unified!
 
diff --git a/personal/implr/vpn/vpn.jsonnet b/personal/implr/vpn/vpn.jsonnet
index 3f39231..c467c5e 100644
--- a/personal/implr/vpn/vpn.jsonnet
+++ b/personal/implr/vpn/vpn.jsonnet
@@ -19,7 +19,27 @@
                     keepalive 10 60
                     persist-tun
                     persist-key
-                    compress lz4
+                    cipher AES-256-CBC
+                    dh none
+                    ca /mnt/pki/ca.crt
+                    cert /mnt/pki/tls.crt
+                    key /mnt/pki/tls.key
+                |||
+            }
+        },
+        curssys: vpn.Server("openvpn-implr-curssys", 11224, top.tls) {
+            cfg+: {
+                namespace: "implr-vpn",
+                configFile: |||
+                    dev tun
+                    tmp-dir /dev/shm/
+                    proto udp
+                    port 11224
+                    topology subnet
+                    server 172.20.1.0 255.255.255.0
+                    keepalive 10 60
+                    persist-tun
+                    persist-key
                     cipher AES-256-CBC
                     dh none
                     ca /mnt/pki/ca.crt
@@ -33,5 +53,7 @@
         kektop: vpn.Client("kektop", top.servers.praisethesun),
         admin1: vpn.Client("admin1", top.servers.praisethesun),
         desk1: vpn.Client("desk1", top.servers.praisethesun),
+        desk2: vpn.Client("desk2", top.servers.curssys),
+        thonk: vpn.Client("thonk", top.servers.curssys),
     }
 }
diff --git a/personal/q3k/mirko.jsonnet b/personal/q3k/mirko.jsonnet
index db7750e..bfeccff 100644
--- a/personal/q3k/mirko.jsonnet
+++ b/personal/q3k/mirko.jsonnet
@@ -4,7 +4,7 @@
     local top = self,
     shipstuck:: {
         cfg:: {
-            image: "registry.k0.hswaw.net/q3k/shipstuck:315532800-a7282b5aa2952e5eb66a1c3ecf7cdafef8335aba",
+            image: "registry.k0.hswaw.net/q3k/shipstuck:315532800-0939d664a3eac4c0c67b447265c67bbcda9939d4",
             domain: error "domain must be set",
         },
         component(cfg, env): mirko.Component(env, "shipstuck") {
diff --git a/personal/q3k/shipstuck/main.go b/personal/q3k/shipstuck/main.go
index 0224c3d..bacbc5d 100644
--- a/personal/q3k/shipstuck/main.go
+++ b/personal/q3k/shipstuck/main.go
@@ -2,9 +2,7 @@
 
 import (
 	"context"
-	"encoding/json"
 	"flag"
-	"fmt"
 	"net/http"
 	"sync"
 	"time"
@@ -17,43 +15,14 @@
 )
 
 type vessel struct {
-	// No idea what these fields are, but they seem to be related to
-	// latitude/longitude. Use these to detect the stuckness of the ship.
-	GT int64 `json:"gt"`
-	DW int64 `json:"dw"`
+	Speed float64 `json:"ss"`
 }
 
 // get retrieves the current status of the ship - returns true if stack, false
 // otherwise.
-func get(ctx context.Context) (bool, error) {
-	// Sorry vesselfinder, if you made it easy to set up an account I would
-	// gladly pay for the API instead of doing this. Limiting requests to once
-	// every 15 minutes though, that seems fair enough.
-	req, err := http.NewRequestWithContext(ctx, "GET", "https://www.vesselfinder.com/api/pub/click/353136000", nil)
-	if err != nil {
-		return false, fmt.Errorf("NewRequestWithContext: %w", err)
-	}
-	req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0")
-
-	res, err := http.DefaultClient.Do(req)
-	if err != nil {
-		return false, fmt.Errorf("Do: %w", err)
-	}
-
-	defer res.Body.Close()
-
-	v := &vessel{}
-	err = json.NewDecoder(res.Body).Decode(v)
-	if err != nil {
-		return false, fmt.Errorf("Decode: %w", err)
-	}
-
-	if v.GT == 219079 && v.DW == 199489 {
-		return true, nil
-	} else {
-		glog.Infof("Freed! %+v", v)
-		return false, nil
-	}
+func get(ctx context.Context) (shipState, error) {
+	// 2021/03/29/ 17:23 UTC+2 it's been freed!
+	return shipStateFreed, nil
 }
 
 type shipState string
@@ -62,6 +31,7 @@
 	shipStateUnknown shipState = "UNKNOWN"
 	shipStateStuck   shipState = "STUCK"
 	shipStateFreed   shipState = "FREED"
+	shipStateTowed   shipState = "TOWED"
 )
 
 type service struct {
@@ -87,11 +57,7 @@
 					break
 				}
 			} else {
-				if stuck {
-					state = shipStateStuck
-				} else {
-					state = shipStateFreed
-				}
+				state = stuck
 				break
 			}
 		}
@@ -124,8 +90,8 @@
 
 var (
 	timeStuck = timeMust(time.Parse(
-		"At 15:04 Eastern European Time (MST) on 2 January 2006",
-		"At 07:40 Eastern European Time (UTC) on 23 March 2021",
+		"At 15:04 Eastern European Time (-0700) on 2 January 2006",
+		"At 07:40 Eastern European Time (+0200) on 23 March 2021",
 	))
 )
 
@@ -146,6 +112,9 @@
 		res.Elapsed = time.Since(timeStuck).Nanoseconds()
 	case shipStateFreed:
 		res.Current = pb.StatusResponse_STUCKNESS_FREE
+	case shipStateTowed:
+		res.Current = pb.StatusResponse_STUCKNESS_TOWED
+		res.Elapsed = time.Since(timeStuck).Nanoseconds()
 	}
 
 	return res, nil
diff --git a/personal/q3k/shipstuck/proto/shipstuck.proto b/personal/q3k/shipstuck/proto/shipstuck.proto
index f0836e1..a76d199 100644
--- a/personal/q3k/shipstuck/proto/shipstuck.proto
+++ b/personal/q3k/shipstuck/proto/shipstuck.proto
@@ -23,8 +23,9 @@
         STUCKNESS_STUCK = 1;
         STUCKNESS_FREE = 2;
         STUCKNESS_UNKNOWN = 3;
+        STUCKNESS_TOWED = 4;
     };
     Stuckness current = 2;
-    // If STUCK, how many nanoseconds have elapsed since the whoopsie?
+    // If STUCK or TOWED, how many nanoseconds have elapsed since the whoopsie?
     int64 elapsed = 3;
 }