cat / 012
clone

a spreadsheet for the terminal: lotus 1-2-3 looks, google sheets keys and formulas, one go binary

main
012 / internal / serve / options.go
options.go 2.8K
1// Package serve runs 012 as an SSH server: each session gets its own2// spreadsheet over its own terminal, confined to one directory.3//4// It is built for one person reaching their own files from elsewhere,5// not for sharing: public-key auth against an authorized_keys file only,6// on the loopback address unless told otherwise, with no port7// forwarding, no subsystems, and no commands: an exec request is only8// ever a file name to open. See docs/terminal/ssh.md.9package serve1011import (12 "src.rest/cat/012/internal/config"1314 "errors"15 "fmt"16 "os"17 "path/filepath"18 "time"19)2021// Options are 012 serve's settings, one field per flag. Defaults gives22// their default values; cmd/012 parses flags into them.23type Options struct {24 // Dir is the served directory: sessions open, save, import and25 // download only inside it.26 Dir string27 // Listen is the TCP address to listen on.28 Listen string29 // AuthorizedKeys is the file of public keys allowed to connect, in30 // OpenSSH's authorized_keys format. It is read again on every login.31 AuthorizedKeys string32 // HostKey is the server's private key file, an ed25519 key generated33 // there (0600, in a 0700 directory) when missing.34 HostKey string35 // IdleTimeout ends a session that has had no input for this long; 036 // never does.37 IdleTimeout time.Duration38 // MaxSessions is how many sessions may run at once; more are turned39 // away.40 MaxSessions int41 // Share is whether sessions opening the same file share its42 // workbook: "edit" (everyone edits), "view" (one writes, the others43 // follow) or "off" (a copy each); "" is off.44 Share string45}4647// Default values.48const (49 DefaultListen = "127.0.0.1:2312"50 DefaultIdleTimeout = 30 * time.Minute51 DefaultMaxSessions = 852)5354// Defaults returns the default options: the current directory, served on55// the loopback address, keys from ~/.ssh/authorized_keys and the host key56// in 012's config directory.57func Defaults() Options {58 o := Options{Dir: ".", Listen: DefaultListen, IdleTimeout: DefaultIdleTimeout, MaxSessions: DefaultMaxSessions, Share: "edit"}59 if home, err := os.UserHomeDir(); err == nil {60 o.AuthorizedKeys = filepath.Join(home, ".ssh", "authorized_keys")61 }62 if dir, err := config.Dir(); err == nil {63 o.HostKey = filepath.Join(dir, "ssh_host_ed25519_key")64 }65 return o66}6768func (o Options) validate() error {69 switch {70 case o.Listen == "":71 return errors.New("no address to listen on")72 case o.AuthorizedKeys == "":73 return errors.New("no authorized_keys file")74 case o.HostKey == "":75 return errors.New("no host key file")76 case o.MaxSessions < 1:77 return fmt.Errorf("max sessions is %d, it must be at least 1", o.MaxSessions)78 case o.IdleTimeout < 0:79 return errors.New("the idle timeout can't be negative")80 case o.Share != "" && o.Share != "edit" && o.Share != "view" && o.Share != "off":81 return fmt.Errorf("share is %q: edit, view or off", o.Share)82 }83 return nil84}