Subject: [PATCH] gnu: Add tmate-ssh-server service.

From: itd <[email-masked]>
Date: Sun, 17 Oct 2021 14:42:25 +0200

>From d854af8a68f47439650956505c0129196ed9c7ba Mon Sep 17 00:00:00 2001

* doc/guix.texi: Add tmate-ssh-server documentation.
* gnu/packages/ssh.scm (tmate-ssh-server): New variable.
* gnu/services/ssh.scm (<tmate-ssh-server-configuration>): New record type.
(tmate-ssh-server-service, tmate-ssh-server-service-type): New variable.
---
Hi,

this adds tmate's server counterpart: tmate-ssh-server.
Feedback would be appreciated.

Thanks.

Best regards
itd

 doc/guix.texi        |  58 ++++++++++++++++++++
 gnu/packages/ssh.scm |  39 ++++++++++++++
 gnu/services/ssh.scm | 123 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 219 insertions(+), 1 deletion(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index a49abc0554..eec9a9e9bb 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -17664,6 +17664,64 @@ Logging level.
 @end table
 @end deftp
 
+@cindex tmate-ssh-server
+@deffn {Scheme Variable} tmate-ssh-server-service-type
+This is the type for the @uref{https://tmate.io, tmate-ssh-server} program that
+runs a @command{tmate} compatible server.  @command{tmate-ssh-server} can be run
+manually from the command-line by passing arguments to the binary
+@command{tmate-ssh-server} from the package @code{tmate-ssh-server}, but it can
+also be run as a Guix service.  This latter use case is documented here.
+
+For example, to specify a service running @command{tmate-ssh-server} listening
+on IP address 192.0.0.11 and port @code{1022}, add this call to the operating
+system's @code{services} field:
+
+@lisp
+(service tmate-ssh-server-service-type
+  (tmate-ssh-server-configuration (bind-ip "192.0.0.11") (port-number 1022)))
+@end lisp
+@end deffn
+
+@deftp {Data Type} tmate-ssh-server-configuration
+Data type representing the configuration for @code{tmate-ssh-server-service}.
+
+@table @asis
+@item @code{bind-ip} (default: @var{#f})
+IP address the server should bind to, if any.
+
+@item @code{hostname} (default: @var{#f})
+Hostname to advertise to clients.  If unspecified, defaults to the system's
+hostname.
+
+@item @code{keydir} (default: @var{"/etc/tmate-ssh-server/"})
+Directory in which tmux-ssh-server expects the SSH keys "ssh_host_rsa_key" and
+"ssh_host_ed25519_key" with their public counterparts.
+
+@item @code{port-number} (default: @var{22})
+Port on which @command{tmate-ssh-server} will listen for new connections.
+
+@item @code{proxy-port-number} (default: @var{#f})
+Port to advertise to clients.
+
+@item @code{websocket-hostname} (default: @var{#f})
+Hostname to advertise in WebSocket connections.
+
+@item @code{websocket-port-number} (default: @var{#f})
+Port on which @command{tmate-ssh-server} should accept WebSocket connections.
+If unspecified and WebSocket support is enabled, defaults to 4002.
+
+@item @code{use-websocket?} (default: @var{#f})
+Enable support for WebSocket connections.  WebSocket connections are required
+for named @command{tmate} sessions.
+
+@item @code{verbose-output?} (default: @var{#f})
+If set, increases the output verbosity of @command{tmux-ssh-server}.
+@command{tmate-ssh-server}'s output will be logged in
+"/var/log/tmate-ssh-server.log".
+
+@end table
+@end deftp
+
 @defvr {Scheme Variable} %facebook-host-aliases
 This variable contains a string for use in @file{/etc/hosts}
 (@pxref{Host Names,,, libc, The GNU C Library Reference Manual}).  Each
diff --git a/gnu/packages/ssh.scm b/gnu/packages/ssh.scm
index 4e217888fd..c66e3e3e83 100644
--- a/gnu/packages/ssh.scm
+++ b/gnu/packages/ssh.scm
@@ -47,6 +47,7 @@
   #:use-module (gnu packages guile)
   #:use-module (gnu packages hurd)
   #:use-module (gnu packages libedit)
+  #:use-module (gnu packages libevent)
   #:use-module (gnu packages linux)
   #:use-module (gnu packages logging)
   #:use-module (gnu packages m4)
@@ -63,6 +64,8 @@
   #:use-module (gnu packages python-web)
   #:use-module (gnu packages python-xyz)
   #:use-module (gnu packages readline)
+  #:use-module (gnu packages serialization)
+  #:use-module (gnu packages ssh)
   #:use-module (gnu packages texinfo)
   #:use-module (gnu packages tls)
   #:use-module (gnu packages xorg)
@@ -931,3 +934,39 @@ Ed25519 keys.
 @item Modern browsers are supported.
 @end itemize")
     (license license:expat)))
+
+(define-public tmate-ssh-server
+  ;; Last tag is a bit dated and appeared to be incompatible with Guix's tmate.
+  ;; See also: https://github.com/tmate-io/tmate-ssh-server/issues/89
+  (let ((commit "befd49f4e8dbf43b5e80d515727a27bb67b38d56")
+        (revision "0"))
+    (package
+      (name "tmate-ssh-server")
+      (version (git-version "2.3.0" revision commit))
+      (source
+       (origin
+         (method git-fetch)
+         (uri (git-reference
+               (url "https://github.com/tmate-io/tmate-ssh-server")
+               (commit commit)))
+         (file-name (git-file-name name version))
+         (sha256
+          (base32 "0v2kxi9nqga9w8qwc3s2miix304dxgi5ima0zmn2w6fjzz2x84jd"))))
+      (build-system gnu-build-system)
+      (native-inputs `(("autoconf" ,autoconf)
+                       ("automake" ,automake)
+                       ("libevent" ,libevent)
+                       ("libssh" ,libssh)
+                       ("msgpack" ,msgpack)
+                       ("ncurses" ,ncurses)
+                       ("pkg-config" ,%pkg-config)))
+      (home-page "https://tmate.io/")
+      ;; TRANSLATORS: synopsis and description are similar to tmate's.  It might
+      ;;              make sense to reuse that translation.
+      (synopsis "Server part for @command{tmate}, a terminal sharing application")
+      (description "@command{tmate-ssh-server} provides the server part of
+@command{tmate}.  @command{tmate} is a terminal sharing application that allows
+you to share your terminal with other users over the Internet.  @command{tmate}
+is a fork of @command{tmux}.")
+      (license ;; COPYING: ISC for README/CHANGES/FAQ/TODO; README: project is MIT
+        (list license:expat license:isc)))))
diff --git a/gnu/services/ssh.scm b/gnu/services/ssh.scm
index a018052eeb..5c7ce20c43 100644
--- a/gnu/services/ssh.scm
+++ b/gnu/services/ssh.scm
@@ -60,7 +60,12 @@
             webssh-configuration
             webssh-configuration?
             webssh-service-type
-            %webssh-configuration-nginx))
+            %webssh-configuration-nginx
+
+            tmate-ssh-server-configuration
+            tmate-ssh-server-configuration?
+            tmate-ssh-server-service-type
+            tmate-ssh-server-service))
 
 ;;; Commentary:
 ;;;
@@ -868,4 +873,120 @@ object."
    (description
     "Run the webssh.")))
 
+
+;;;
+;;; tmate-ssh-server
+;;;
+
+(define-record-type* <tmate-ssh-server-configuration>
+  tmate-ssh-server-configuration make-tmate-ssh-server-configuration
+  tmate-ssh-server-configuration?
+  (tmate-ssh-server      tmate-ssh-server-configuration-tmate-ssh-server
+                         (default tmate-ssh-server))
+  ;; String
+  ;; IP to bind to.
+  (bind-ip               tmate-ssh-server-configuration-bind-ip
+                         (default #f))
+  ;; String
+  ;; Hostname.
+  (hostname              tmate-ssh-server-configuration-hostname
+                         (default #f))
+  ;; String
+  ;; Directory containing the SSH keys.
+  (keydir                tmate-ssh-server-configuration-keydir
+                         (default "/etc/tmate-ssh-server/"))
+  ;; Integer
+  ;; Port to listen on.
+  (port-number           tmate-ssh-server-configuration-port-number
+                         (default 22))
+  ;; Integer
+  ;; Proxy port to listen on.
+  (proxy-port-number     tmate-ssh-server-configuration-proxy-port-number
+                         (default #f))
+  ;; String
+  ;; Websocket hostname.
+  (websocket-hostname    tmate-ssh-server-configuration-websocket-hostname
+                         (default #f))
+  ;; Integer
+  ;; Websocket port to listen on.
+  (websocket-port-number tmate-ssh-server-configuration-websocket-port-number
+                         (default #f))
+  ;; Boolean
+  ;; Use websocket.
+  (use-websocket?        tmate-ssh-server-configuration-use-websocket?
+                         (default #f))
+  ;; Boolean
+  ;; Increase output verbosity.
+  (verbose-output?       tmate-ssh-server-configuration-verbose-output?
+                         (default #f)))
+
+(define (tmate-ssh-server-activation config)
+  "Return the activation gexp for CONFIG."
+  #~(begin
+      (use-modules (guix build utils))
+      (mkdir-p "/etc/tmate-ssh-server")))
+
+(define (tmate-ssh-server-shepherd-service config)
+  "Return a <shepherd-service> for tmate-ssh-server with CONFIG."
+  (define tmate-ssh-server
+    (tmate-ssh-server-configuration-tmate-ssh-server config))
+
+  (define tmate-ssh-server-command
+    #~(list (string-append #$tmate-ssh-server "/bin/tmate-ssh-server")
+            #$@(if (tmate-ssh-server-configuration-bind-ip config)
+                   (list "-b" (tmate-ssh-server-configuration-bind-ip config))
+                   '())
+            #$@(if (tmate-ssh-server-configuration-hostname config)
+                   (list "-h" (tmate-ssh-server-configuration-hostname config))
+                   '())
+            "-k" #$(tmate-ssh-server-configuration-keydir config)
+            #$@(if (tmate-ssh-server-configuration-port-number config)
+                   (list "-p" (number->string
+                               (tmate-ssh-server-configuration-port-number config)))
+                   '())
+            #$@(if (tmate-ssh-server-configuration-proxy-port-number config)
+                   (list "-q" (number->string
+                               (tmate-ssh-server-configuration-proxy-port-number config)))
+                   '())
+            #$@(if (tmate-ssh-server-configuration-websocket-hostname config)
+                   (list "-w" (tmate-ssh-server-configuration-websocket-hostname config))
+                   '())
+            #$@(if (tmate-ssh-server-configuration-websocket-port-number config)
+                   (list "-z" (number->string
+                               (tmate-ssh-server-configuration-websocket-port-number config)))
+                   '())
+            #$@(if (tmate-ssh-server-configuration-use-websocket? config)
+                   '("-x")
+                   '())
+            #$@(if (tmate-ssh-server-configuration-verbose-output? config)
+                   '("-v")
+                   '())))
+
+  (define requires
+    '(networking))
+
+  (list (shepherd-service
+         (documentation "tmate SSH server.")
+         (requirement requires)
+         (provision '(tmate-daemon))
+         (start #~(make-forkexec-constructor #$tmate-ssh-server-command
+                                             #:log-file "/var/log/tmate-ssh-server.log"))
+         (stop #~(make-kill-destructor)))))
+
+(define tmate-ssh-server-service-type
+  (service-type (name 'tmate-ssh-server)
+                (description
+                 "Run the tmate secure shell (SSH) server.")
+                (extensions
+                 (list (service-extension shepherd-root-service-type
+                                          tmate-ssh-server-shepherd-service)
+                       (service-extension activation-service-type
+                                          tmate-ssh-server-activation)))
+                (default-value (tmate-ssh-server-configuration))))
+
+(define* (tmate-ssh-server-service #:optional (config (tmate-ssh-server-configuration)))
+  "Run the @uref{https://tmate.io/,tmate SSH daemon} with the given @var{config},
+a @code{<tmate-ssh-server-configuration>} object."
+  (service tmate-ssh-server-service-type config))
+
 ;;; ssh.scm ends here

base-commit: 258a27eea9aab4f8af995f95743ccd264b5efcb5
-- 
2.30.2