github.com/artpar/rclone@v1.67.3/cmd/serve/sftp/sftp.go (about) 1 //go:build !plan9 2 3 // Package sftp implements an SFTP server to serve an rclone VFS 4 package sftp 5 6 import ( 7 "context" 8 9 "github.com/artpar/rclone/cmd" 10 "github.com/artpar/rclone/cmd/serve/proxy" 11 "github.com/artpar/rclone/cmd/serve/proxy/proxyflags" 12 "github.com/artpar/rclone/fs" 13 "github.com/artpar/rclone/fs/config/flags" 14 "github.com/artpar/rclone/fs/rc" 15 "github.com/artpar/rclone/lib/systemd" 16 "github.com/artpar/rclone/vfs" 17 "github.com/artpar/rclone/vfs/vfsflags" 18 "github.com/spf13/cobra" 19 "github.com/spf13/pflag" 20 ) 21 22 // Options contains options for the http Server 23 type Options struct { 24 ListenAddr string // Port to listen on 25 HostKeys []string // Paths to private host keys 26 AuthorizedKeys string // Path to authorized keys file 27 User string // single username 28 Pass string // password for user 29 NoAuth bool // allow no authentication on connections 30 Stdio bool // serve on stdio 31 } 32 33 // DefaultOpt is the default values used for Options 34 var DefaultOpt = Options{ 35 ListenAddr: "localhost:2022", 36 AuthorizedKeys: "~/.ssh/authorized_keys", 37 } 38 39 // Opt is options set by command line flags 40 var Opt = DefaultOpt 41 42 // AddFlags adds flags for the sftp 43 func AddFlags(flagSet *pflag.FlagSet, Opt *Options) { 44 rc.AddOption("sftp", &Opt) 45 flags.StringVarP(flagSet, &Opt.ListenAddr, "addr", "", Opt.ListenAddr, "IPaddress:Port or :Port to bind server to", "") 46 flags.StringArrayVarP(flagSet, &Opt.HostKeys, "key", "", Opt.HostKeys, "SSH private host key file (Can be multi-valued, leave blank to auto generate)", "") 47 flags.StringVarP(flagSet, &Opt.AuthorizedKeys, "authorized-keys", "", Opt.AuthorizedKeys, "Authorized keys file", "") 48 flags.StringVarP(flagSet, &Opt.User, "user", "", Opt.User, "User name for authentication", "") 49 flags.StringVarP(flagSet, &Opt.Pass, "pass", "", Opt.Pass, "Password for authentication", "") 50 flags.BoolVarP(flagSet, &Opt.NoAuth, "no-auth", "", Opt.NoAuth, "Allow connections with no authentication if set", "") 51 flags.BoolVarP(flagSet, &Opt.Stdio, "stdio", "", Opt.Stdio, "Run an sftp server on stdin/stdout", "") 52 } 53 54 func init() { 55 vfsflags.AddFlags(Command.Flags()) 56 proxyflags.AddFlags(Command.Flags()) 57 AddFlags(Command.Flags(), &Opt) 58 } 59 60 // Command definition for cobra 61 var Command = &cobra.Command{ 62 Use: "sftp remote:path", 63 Short: `Serve the remote over SFTP.`, 64 Long: `Run an SFTP server to serve a remote over SFTP. This can be used 65 with an SFTP client or you can make a remote of type [sftp](/sftp) to use with it. 66 67 You can use the [filter](/filtering) flags (e.g. ` + "`--include`, `--exclude`" + `) 68 to control what is served. 69 70 The server will respond to a small number of shell commands, mainly 71 md5sum, sha1sum and df, which enable it to provide support for checksums 72 and the about feature when accessed from an sftp remote. 73 74 Note that this server uses standard 32 KiB packet payload size, which 75 means you must not configure the client to expect anything else, e.g. 76 with the [chunk_size](/sftp/#sftp-chunk-size) option on an sftp remote. 77 78 The server will log errors. Use ` + "`-v`" + ` to see access logs. 79 80 ` + "`--bwlimit`" + ` will be respected for file transfers. 81 Use ` + "`--stats`" + ` to control the stats printing. 82 83 You must provide some means of authentication, either with 84 ` + "`--user`/`--pass`" + `, an authorized keys file (specify location with 85 ` + "`--authorized-keys`" + ` - the default is the same as ssh), an 86 ` + "`--auth-proxy`" + `, or set the ` + "`--no-auth`" + ` flag for no 87 authentication when logging in. 88 89 If you don't supply a host ` + "`--key`" + ` then rclone will generate rsa, ecdsa 90 and ed25519 variants, and cache them for later use in rclone's cache 91 directory (see ` + "`rclone help flags cache-dir`" + `) in the "serve-sftp" 92 directory. 93 94 By default the server binds to localhost:2022 - if you want it to be 95 reachable externally then supply ` + "`--addr :2022`" + ` for example. 96 97 Note that the default of ` + "`--vfs-cache-mode off`" + ` is fine for the rclone 98 sftp backend, but it may not be with other SFTP clients. 99 100 If ` + "`--stdio`" + ` is specified, rclone will serve SFTP over stdio, which can 101 be used with sshd via ~/.ssh/authorized_keys, for example: 102 103 restrict,command="rclone serve sftp --stdio ./photos" ssh-rsa ... 104 105 On the client you need to set ` + "`--transfers 1`" + ` when using ` + "`--stdio`" + `. 106 Otherwise multiple instances of the rclone server are started by OpenSSH 107 which can lead to "corrupted on transfer" errors. This is the case because 108 the client chooses indiscriminately which server to send commands to while 109 the servers all have different views of the state of the filing system. 110 111 The "restrict" in authorized_keys prevents SHA1SUMs and MD5SUMs from being 112 used. Omitting "restrict" and using ` + "`--sftp-path-override`" + ` to enable 113 checksumming is possible but less secure and you could use the SFTP server 114 provided by OpenSSH in this case. 115 116 ` + vfs.Help() + proxy.Help, 117 Annotations: map[string]string{ 118 "versionIntroduced": "v1.48", 119 "groups": "Filter", 120 }, 121 Run: func(command *cobra.Command, args []string) { 122 var f fs.Fs 123 if proxyflags.Opt.AuthProxy == "" { 124 cmd.CheckArgs(1, 1, command, args) 125 f = cmd.NewFsSrc(args) 126 } else { 127 cmd.CheckArgs(0, 0, command, args) 128 } 129 cmd.Run(false, true, command, func() error { 130 if Opt.Stdio { 131 return serveStdio(f) 132 } 133 s := newServer(context.Background(), f, &Opt) 134 err := s.Serve() 135 if err != nil { 136 return err 137 } 138 defer systemd.Notify()() 139 s.Wait() 140 return nil 141 }) 142 }, 143 }