diff --git a/vendor/git.autistici.org/ai3/go-common/clientutil/balancer.go b/vendor/git.autistici.org/ai3/go-common/clientutil/balancer.go
index 8f6e99f197e648ea18bf4024874ec0f5c5594c9a..5c37d6bfcb7e97c0c249d21c236d90df7dcc1637 100644
--- a/vendor/git.autistici.org/ai3/go-common/clientutil/balancer.go
+++ b/vendor/git.autistici.org/ai3/go-common/clientutil/balancer.go
@@ -221,7 +221,7 @@ func (b *balancedBackend) do(ctx context.Context, seq *sequence, req *http.Reque
 	client := &http.Client{
 		Transport: b.transportCache.getTransport(target),
 	}
-	resp, err = client.Do(req.WithContext(ctx))
+	resp, err = client.Do(propagateDeadline(ctx, req))
 	if err == nil && resp.StatusCode != 200 {
 		err = remoteErrorFromResponse(resp)
 		if !isStatusTemporary(resp.StatusCode) {
@@ -235,6 +235,19 @@ func (b *balancedBackend) do(ctx context.Context, seq *sequence, req *http.Reque
 	return
 }
 
+const deadlineHeader = "X-RPC-Deadline"
+
+// Propagate context deadline to the server using a HTTP header.
+func propagateDeadline(ctx context.Context, req *http.Request) *http.Request {
+	req = req.WithContext(ctx)
+	if deadline, ok := ctx.Deadline(); ok {
+		req.Header.Set(deadlineHeader, strconv.FormatInt(deadline.UTC().UnixNano(), 10))
+	} else {
+		req.Header.Del(deadlineHeader)
+	}
+	return req
+}
+
 var errNoTargets = errors.New("no available backends")
 
 type targetGenerator interface {
diff --git a/vendor/git.autistici.org/ai3/go-common/serverutil/http.go b/vendor/git.autistici.org/ai3/go-common/serverutil/http.go
index 604ca98f54357b6d423f341f8e71cd589697555a..641c0b9bcae0001b66322e04b28c9da981617424 100644
--- a/vendor/git.autistici.org/ai3/go-common/serverutil/http.go
+++ b/vendor/git.autistici.org/ai3/go-common/serverutil/http.go
@@ -11,6 +11,7 @@ import (
 	_ "net/http/pprof"
 	"os"
 	"os/signal"
+	"strconv"
 	"syscall"
 	"time"
 
@@ -26,6 +27,7 @@ var gracefulShutdownTimeout = 3 * time.Second
 type ServerConfig struct {
 	TLS                 *TLSServerConfig `yaml:"tls"`
 	MaxInflightRequests int              `yaml:"max_inflight_requests"`
+	RequestTimeoutSecs  int              `yaml:"request_timeout"`
 	TrustedForwarders   []string         `yaml:"trusted_forwarders"`
 }
 
@@ -60,11 +62,18 @@ func (config *ServerConfig) buildHTTPServer(h http.Handler) (*http.Server, error
 		}
 	}
 
+	// Wrap the handler with a TimeoutHandler if 'request_timeout'
+	// is set.
+	h = addDefaultHandlers(h)
+	if config.RequestTimeoutSecs > 0 {
+		h = http.TimeoutHandler(h, time.Duration(config.RequestTimeoutSecs)*time.Second, "")
+	}
+
 	// These are not meant to be external-facing servers, so we
 	// can be generous with the timeouts to keep the number of
 	// reconnections low.
 	return &http.Server{
-		Handler:      defaultHandler(h),
+		Handler:      h,
 		ReadTimeout:  30 * time.Second,
 		WriteTimeout: 30 * time.Second,
 		IdleTimeout:  600 * time.Second,
@@ -134,7 +143,7 @@ func Serve(h http.Handler, config *ServerConfig, addr string) error {
 	return nil
 }
 
-func defaultHandler(h http.Handler) http.Handler {
+func addDefaultHandlers(h http.Handler) http.Handler {
 	root := http.NewServeMux()
 
 	// Add an endpoint for HTTP health checking probes.
@@ -154,11 +163,30 @@ func defaultHandler(h http.Handler) http.Handler {
 	// Prometheus instrumentation (requests to /metrics and
 	// /health are not included).
 	root.Handle("/", promhttp.InstrumentHandlerInFlight(inFlightRequests,
-		promhttp.InstrumentHandlerCounter(totalRequests, h)))
+		promhttp.InstrumentHandlerCounter(totalRequests,
+			propagateDeadline(h))))
 
 	return root
 }
 
+const deadlineHeader = "X-RPC-Deadline"
+
+// Read an eventual deadline from the HTTP request, and set it as the
+// deadline of the request context.
+func propagateDeadline(h http.Handler) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+		if hdr := req.Header.Get(deadlineHeader); hdr != "" {
+			if deadlineNano, err := strconv.ParseInt(hdr, 10, 64); err == nil {
+				deadline := time.Unix(0, deadlineNano)
+				ctx, cancel := context.WithDeadline(req.Context(), deadline)
+				defer cancel()
+				req = req.WithContext(ctx)
+			}
+		}
+		h.ServeHTTP(w, req)
+	})
+}
+
 func guessEndpointName(addr string) string {
 	_, port, err := net.SplitHostPort(addr)
 	if err != nil {
diff --git a/vendor/vendor.json b/vendor/vendor.json
index b88602499fe680b5b43a9c7dba1a7378d8501016..d5ffb8fe8609cc009f967f880f0facb2ce4b5e27 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -5,50 +5,50 @@
 		{
 			"checksumSHA1": "oUOxU+Tw1/jOzWVP05HuGvVSC/A=",
 			"path": "git.autistici.org/ai3/go-common",
-			"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
-			"revisionTime": "2020-01-06T11:09:19Z"
+			"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
+			"revisionTime": "2020-02-06T11:03:59Z"
 		},
 		{
-			"checksumSHA1": "k/t0n698YTZJR6ncd9gzSvymXsE=",
+			"checksumSHA1": "/uo2RHmQ/sae2RMYKm81zb6OUn4=",
 			"path": "git.autistici.org/ai3/go-common/clientutil",
-			"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
-			"revisionTime": "2020-01-06T11:09:19Z"
+			"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
+			"revisionTime": "2020-02-06T11:03:59Z"
 		},
 		{
 			"checksumSHA1": "d8aQcSXveyjPfFJgfB8NnM+x8dg=",
 			"path": "git.autistici.org/ai3/go-common/ldap",
-			"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
-			"revisionTime": "2020-01-06T11:09:19Z"
+			"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
+			"revisionTime": "2020-02-06T11:03:59Z"
 		},
 		{
 			"checksumSHA1": "ETt1H7ZXeT+mOGVuWDvgGBVx98k=",
 			"path": "git.autistici.org/ai3/go-common/ldap/compositetypes",
-			"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
-			"revisionTime": "2020-01-06T11:09:19Z"
+			"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
+			"revisionTime": "2020-02-06T11:03:59Z"
 		},
 		{
-			"checksumSHA1": "Xm0ZN1urTQaagPJ5kJlCjeGONOU=",
+			"checksumSHA1": "xrew5jDNLDh5bhTZ4jgO0rX0N+4=",
 			"path": "git.autistici.org/ai3/go-common/serverutil",
-			"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
-			"revisionTime": "2020-01-06T11:09:19Z"
+			"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
+			"revisionTime": "2020-02-06T11:03:59Z"
 		},
 		{
 			"checksumSHA1": "y5pRYZ/NhfEOCFslPEuUZTYXcro=",
 			"path": "git.autistici.org/ai3/go-common/tracing",
-			"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
-			"revisionTime": "2020-01-06T11:09:19Z"
+			"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
+			"revisionTime": "2020-02-06T11:03:59Z"
 		},
 		{
 			"checksumSHA1": "jRc0JfRUtCr3xxkgwRDVppsSnl0=",
 			"path": "git.autistici.org/ai3/go-common/unix",
-			"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
-			"revisionTime": "2020-01-06T11:09:19Z"
+			"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
+			"revisionTime": "2020-02-06T11:03:59Z"
 		},
 		{
 			"checksumSHA1": "witSYnNsDhNaoA85UYilt17H+ng=",
 			"path": "git.autistici.org/ai3/go-common/userenckey",
-			"revision": "c165311f4270e8a2d75d9a610abdfb54d72ae4e5",
-			"revisionTime": "2020-01-06T11:09:19Z"
+			"revision": "d4396660b1f09d2d07a7271b8a480726c5d29a6e",
+			"revisionTime": "2020-02-06T11:03:59Z"
 		},
 		{
 			"checksumSHA1": "MszadHmYMr3JQMX2gRg7TfsQWVc=",