root.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // Copyright (C) 2019-2023 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. // Package cmd provides Command Line Interface support
  15. package cmd
  16. import (
  17. "fmt"
  18. "os"
  19. "github.com/spf13/cobra"
  20. "github.com/spf13/viper"
  21. "github.com/drakkan/sftpgo/v2/internal/version"
  22. )
  23. const (
  24. configDirFlag = "config-dir"
  25. configDirKey = "config_dir"
  26. configFileFlag = "config-file"
  27. configFileKey = "config_file"
  28. logFilePathFlag = "log-file-path"
  29. logFilePathKey = "log_file_path"
  30. logMaxSizeFlag = "log-max-size"
  31. logMaxSizeKey = "log_max_size"
  32. logMaxBackupFlag = "log-max-backups"
  33. logMaxBackupKey = "log_max_backups"
  34. logMaxAgeFlag = "log-max-age"
  35. logMaxAgeKey = "log_max_age"
  36. logCompressFlag = "log-compress"
  37. logCompressKey = "log_compress"
  38. logLevelFlag = "log-level"
  39. logLevelKey = "log_level"
  40. logUTCTimeFlag = "log-utc-time"
  41. logUTCTimeKey = "log_utc_time"
  42. loadDataFromFlag = "loaddata-from"
  43. loadDataFromKey = "loaddata_from"
  44. loadDataModeFlag = "loaddata-mode"
  45. loadDataModeKey = "loaddata_mode"
  46. loadDataQuotaScanFlag = "loaddata-scan"
  47. loadDataQuotaScanKey = "loaddata_scan"
  48. loadDataCleanFlag = "loaddata-clean"
  49. loadDataCleanKey = "loaddata_clean"
  50. graceTimeFlag = "grace-time"
  51. graceTimeKey = "grace_time"
  52. defaultConfigDir = "."
  53. defaultConfigFile = ""
  54. defaultLogFile = "sftpgo.log"
  55. defaultLogMaxSize = 10
  56. defaultLogMaxBackup = 5
  57. defaultLogMaxAge = 28
  58. defaultLogCompress = false
  59. defaultLogLevel = "debug"
  60. defaultLogUTCTime = false
  61. defaultLoadDataFrom = ""
  62. defaultLoadDataMode = 1
  63. defaultLoadDataQuotaScan = 0
  64. defaultLoadDataClean = false
  65. defaultGraceTime = 0
  66. )
  67. var (
  68. configDir string
  69. configFile string
  70. logFilePath string
  71. logMaxSize int
  72. logMaxBackups int
  73. logMaxAge int
  74. logCompress bool
  75. logLevel string
  76. logUTCTime bool
  77. loadDataFrom string
  78. loadDataMode int
  79. loadDataQuotaScan int
  80. loadDataClean bool
  81. graceTime int
  82. // used if awscontainer build tag is enabled
  83. disableAWSInstallationCode bool
  84. rootCmd = &cobra.Command{
  85. Use: "sftpgo",
  86. Short: "Fully featured and highly configurable SFTP server",
  87. }
  88. )
  89. func init() {
  90. rootCmd.CompletionOptions.DisableDefaultCmd = true
  91. rootCmd.Flags().BoolP("version", "v", false, "")
  92. rootCmd.Version = version.GetAsString()
  93. rootCmd.SetVersionTemplate(`{{printf "SFTPGo "}}{{printf "%s" .Version}}
  94. `)
  95. }
  96. // Execute adds all child commands to the root command and sets flags appropriately.
  97. // This is called by main.main(). It only needs to happen once to the rootCmd.
  98. func Execute() {
  99. if err := rootCmd.Execute(); err != nil {
  100. fmt.Println(err)
  101. os.Exit(1)
  102. }
  103. }
  104. func addConfigFlags(cmd *cobra.Command) {
  105. viper.SetDefault(configDirKey, defaultConfigDir)
  106. viper.BindEnv(configDirKey, "SFTPGO_CONFIG_DIR") //nolint:errcheck // err is not nil only if the key to bind is missing
  107. cmd.Flags().StringVarP(&configDir, configDirFlag, "c", viper.GetString(configDirKey),
  108. `Location for the config dir. This directory
  109. is used as the base for files with a relative
  110. path, eg. the private keys for the SFTP
  111. server or the SQLite database if you use
  112. SQLite as data provider.
  113. The configuration file, if not explicitly set,
  114. is looked for in this dir. We support reading
  115. from JSON, TOML, YAML, HCL, envfile and Java
  116. properties config files. The default config
  117. file name is "sftpgo" and therefore
  118. "sftpgo.json", "sftpgo.yaml" and so on are
  119. searched.
  120. This flag can be set using SFTPGO_CONFIG_DIR
  121. env var too.`)
  122. viper.BindPFlag(configDirKey, cmd.Flags().Lookup(configDirFlag)) //nolint:errcheck
  123. viper.SetDefault(configFileKey, defaultConfigFile)
  124. viper.BindEnv(configFileKey, "SFTPGO_CONFIG_FILE") //nolint:errcheck
  125. cmd.Flags().StringVar(&configFile, configFileFlag, viper.GetString(configFileKey),
  126. `Path to SFTPGo configuration file.
  127. This flag explicitly defines the path, name
  128. and extension of the config file. If must be
  129. an absolute path or a path relative to the
  130. configuration directory. The specified file
  131. name must have a supported extension (JSON,
  132. YAML, TOML, HCL or Java properties).
  133. This flag can be set using SFTPGO_CONFIG_FILE
  134. env var too.`)
  135. viper.BindPFlag(configFileKey, cmd.Flags().Lookup(configFileFlag)) //nolint:errcheck
  136. }
  137. func addBaseLoadDataFlags(cmd *cobra.Command) {
  138. viper.SetDefault(loadDataFromKey, defaultLoadDataFrom)
  139. viper.BindEnv(loadDataFromKey, "SFTPGO_LOADDATA_FROM") //nolint:errcheck
  140. cmd.Flags().StringVar(&loadDataFrom, loadDataFromFlag, viper.GetString(loadDataFromKey),
  141. `Load users and folders from this file.
  142. The file must be specified as absolute path
  143. and it must contain a backup obtained using
  144. the "dumpdata" REST API or compatible content.
  145. This flag can be set using SFTPGO_LOADDATA_FROM
  146. env var too.
  147. `)
  148. viper.BindPFlag(loadDataFromKey, cmd.Flags().Lookup(loadDataFromFlag)) //nolint:errcheck
  149. viper.SetDefault(loadDataModeKey, defaultLoadDataMode)
  150. viper.BindEnv(loadDataModeKey, "SFTPGO_LOADDATA_MODE") //nolint:errcheck
  151. cmd.Flags().IntVar(&loadDataMode, loadDataModeFlag, viper.GetInt(loadDataModeKey),
  152. `Restore mode for data to load:
  153. 0 - new users are added, existing users are
  154. updated
  155. 1 - New users are added, existing users are
  156. not modified
  157. This flag can be set using SFTPGO_LOADDATA_MODE
  158. env var too.
  159. `)
  160. viper.BindPFlag(loadDataModeKey, cmd.Flags().Lookup(loadDataModeFlag)) //nolint:errcheck
  161. viper.SetDefault(loadDataCleanKey, defaultLoadDataClean)
  162. viper.BindEnv(loadDataCleanKey, "SFTPGO_LOADDATA_CLEAN") //nolint:errcheck
  163. cmd.Flags().BoolVar(&loadDataClean, loadDataCleanFlag, viper.GetBool(loadDataCleanKey),
  164. `Determine if the loaddata-from file should
  165. be removed after a successful load. This flag
  166. can be set using SFTPGO_LOADDATA_CLEAN env var
  167. too. (default "false")
  168. `)
  169. viper.BindPFlag(loadDataCleanKey, cmd.Flags().Lookup(loadDataCleanFlag)) //nolint:errcheck
  170. }
  171. func addServeFlags(cmd *cobra.Command) {
  172. addConfigFlags(cmd)
  173. viper.SetDefault(logFilePathKey, defaultLogFile)
  174. viper.BindEnv(logFilePathKey, "SFTPGO_LOG_FILE_PATH") //nolint:errcheck
  175. cmd.Flags().StringVarP(&logFilePath, logFilePathFlag, "l", viper.GetString(logFilePathKey),
  176. `Location for the log file. Leave empty to write
  177. logs to the standard output. This flag can be
  178. set using SFTPGO_LOG_FILE_PATH env var too.
  179. `)
  180. viper.BindPFlag(logFilePathKey, cmd.Flags().Lookup(logFilePathFlag)) //nolint:errcheck
  181. viper.SetDefault(logMaxSizeKey, defaultLogMaxSize)
  182. viper.BindEnv(logMaxSizeKey, "SFTPGO_LOG_MAX_SIZE") //nolint:errcheck
  183. cmd.Flags().IntVarP(&logMaxSize, logMaxSizeFlag, "s", viper.GetInt(logMaxSizeKey),
  184. `Maximum size in megabytes of the log file
  185. before it gets rotated. This flag can be set
  186. using SFTPGO_LOG_MAX_SIZE env var too. It is
  187. unused if log-file-path is empty.
  188. `)
  189. viper.BindPFlag(logMaxSizeKey, cmd.Flags().Lookup(logMaxSizeFlag)) //nolint:errcheck
  190. viper.SetDefault(logMaxBackupKey, defaultLogMaxBackup)
  191. viper.BindEnv(logMaxBackupKey, "SFTPGO_LOG_MAX_BACKUPS") //nolint:errcheck
  192. cmd.Flags().IntVarP(&logMaxBackups, "log-max-backups", "b", viper.GetInt(logMaxBackupKey),
  193. `Maximum number of old log files to retain.
  194. This flag can be set using SFTPGO_LOG_MAX_BACKUPS
  195. env var too. It is unused if log-file-path is
  196. empty.`)
  197. viper.BindPFlag(logMaxBackupKey, cmd.Flags().Lookup(logMaxBackupFlag)) //nolint:errcheck
  198. viper.SetDefault(logMaxAgeKey, defaultLogMaxAge)
  199. viper.BindEnv(logMaxAgeKey, "SFTPGO_LOG_MAX_AGE") //nolint:errcheck
  200. cmd.Flags().IntVarP(&logMaxAge, "log-max-age", "a", viper.GetInt(logMaxAgeKey),
  201. `Maximum number of days to retain old log files.
  202. This flag can be set using SFTPGO_LOG_MAX_AGE env
  203. var too. It is unused if log-file-path is empty.
  204. `)
  205. viper.BindPFlag(logMaxAgeKey, cmd.Flags().Lookup(logMaxAgeFlag)) //nolint:errcheck
  206. viper.SetDefault(logCompressKey, defaultLogCompress)
  207. viper.BindEnv(logCompressKey, "SFTPGO_LOG_COMPRESS") //nolint:errcheck
  208. cmd.Flags().BoolVarP(&logCompress, logCompressFlag, "z", viper.GetBool(logCompressKey),
  209. `Determine if the rotated log files
  210. should be compressed using gzip. This flag can
  211. be set using SFTPGO_LOG_COMPRESS env var too.
  212. It is unused if log-file-path is empty.
  213. `)
  214. viper.BindPFlag(logCompressKey, cmd.Flags().Lookup(logCompressFlag)) //nolint:errcheck
  215. viper.SetDefault(logLevelKey, defaultLogLevel)
  216. viper.BindEnv(logLevelKey, "SFTPGO_LOG_LEVEL") //nolint:errcheck
  217. cmd.Flags().StringVar(&logLevel, logLevelFlag, viper.GetString(logLevelKey),
  218. `Set the log level. Supported values:
  219. debug, info, warn, error.
  220. This flag can be set
  221. using SFTPGO_LOG_LEVEL env var too.
  222. `)
  223. viper.BindPFlag(logLevelKey, cmd.Flags().Lookup(logLevelFlag)) //nolint:errcheck
  224. viper.SetDefault(logUTCTimeKey, defaultLogUTCTime)
  225. viper.BindEnv(logUTCTimeKey, "SFTPGO_LOG_UTC_TIME") //nolint:errcheck
  226. cmd.Flags().BoolVar(&logUTCTime, logUTCTimeFlag, viper.GetBool(logUTCTimeKey),
  227. `Use UTC time for logging. This flag can be set
  228. using SFTPGO_LOG_UTC_TIME env var too.
  229. `)
  230. viper.BindPFlag(logUTCTimeKey, cmd.Flags().Lookup(logUTCTimeFlag)) //nolint:errcheck
  231. addBaseLoadDataFlags(cmd)
  232. viper.SetDefault(loadDataQuotaScanKey, defaultLoadDataQuotaScan)
  233. viper.BindEnv(loadDataQuotaScanKey, "SFTPGO_LOADDATA_QUOTA_SCAN") //nolint:errcheck
  234. cmd.Flags().IntVar(&loadDataQuotaScan, loadDataQuotaScanFlag, viper.GetInt(loadDataQuotaScanKey),
  235. `Quota scan mode after data load:
  236. 0 - no quota scan
  237. 1 - scan quota
  238. 2 - scan quota if the user has quota restrictions
  239. This flag can be set using SFTPGO_LOADDATA_QUOTA_SCAN
  240. env var too.
  241. (default 0)`)
  242. viper.BindPFlag(loadDataQuotaScanKey, cmd.Flags().Lookup(loadDataQuotaScanFlag)) //nolint:errcheck
  243. viper.SetDefault(graceTimeKey, defaultGraceTime)
  244. viper.BindEnv(graceTimeKey, "SFTPGO_GRACE_TIME") //nolint:errcheck
  245. cmd.Flags().IntVar(&graceTime, graceTimeFlag, viper.GetInt(graceTimeKey),
  246. `Graceful shutdown is an option to initiate a
  247. shutdown without abrupt cancellation of the
  248. currently ongoing client-initiated transfer
  249. sessions.
  250. This grace time defines the number of seconds
  251. allowed for existing transfers to get
  252. completed before shutting down.
  253. A graceful shutdown is triggered by an
  254. interrupt signal.
  255. This flag can be set using SFTPGO_GRACE_TIME env
  256. var too. 0 means disabled. (default 0)`)
  257. viper.BindPFlag(graceTimeKey, cmd.Flags().Lookup(graceTimeFlag)) //nolint:errcheck
  258. }