root.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // Copyright (C) 2019-2022 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. defaultConfigDir = "."
  51. defaultConfigFile = ""
  52. defaultLogFile = "sftpgo.log"
  53. defaultLogMaxSize = 10
  54. defaultLogMaxBackup = 5
  55. defaultLogMaxAge = 28
  56. defaultLogCompress = false
  57. defaultLogLevel = "debug"
  58. defaultLogUTCTime = false
  59. defaultLoadDataFrom = ""
  60. defaultLoadDataMode = 1
  61. defaultLoadDataQuotaScan = 0
  62. defaultLoadDataClean = false
  63. )
  64. var (
  65. configDir string
  66. configFile string
  67. logFilePath string
  68. logMaxSize int
  69. logMaxBackups int
  70. logMaxAge int
  71. logCompress bool
  72. logLevel string
  73. logUTCTime bool
  74. loadDataFrom string
  75. loadDataMode int
  76. loadDataQuotaScan int
  77. loadDataClean bool
  78. // used if awscontainer build tag is enabled
  79. disableAWSInstallationCode bool
  80. rootCmd = &cobra.Command{
  81. Use: "sftpgo",
  82. Short: "Fully featured and highly configurable SFTP server",
  83. }
  84. )
  85. func init() {
  86. rootCmd.CompletionOptions.DisableDefaultCmd = true
  87. rootCmd.Flags().BoolP("version", "v", false, "")
  88. rootCmd.Version = version.GetAsString()
  89. rootCmd.SetVersionTemplate(`{{printf "SFTPGo "}}{{printf "%s" .Version}}
  90. `)
  91. }
  92. // Execute adds all child commands to the root command and sets flags appropriately.
  93. // This is called by main.main(). It only needs to happen once to the rootCmd.
  94. func Execute() {
  95. if err := rootCmd.Execute(); err != nil {
  96. fmt.Println(err)
  97. os.Exit(1)
  98. }
  99. }
  100. func addConfigFlags(cmd *cobra.Command) {
  101. viper.SetDefault(configDirKey, defaultConfigDir)
  102. viper.BindEnv(configDirKey, "SFTPGO_CONFIG_DIR") //nolint:errcheck // err is not nil only if the key to bind is missing
  103. cmd.Flags().StringVarP(&configDir, configDirFlag, "c", viper.GetString(configDirKey),
  104. `Location for the config dir. This directory
  105. is used as the base for files with a relative
  106. path, eg. the private keys for the SFTP
  107. server or the SQLite database if you use
  108. SQLite as data provider.
  109. The configuration file, if not explicitly set,
  110. is looked for in this dir. We support reading
  111. from JSON, TOML, YAML, HCL, envfile and Java
  112. properties config files. The default config
  113. file name is "sftpgo" and therefore
  114. "sftpgo.json", "sftpgo.yaml" and so on are
  115. searched.
  116. This flag can be set using SFTPGO_CONFIG_DIR
  117. env var too.`)
  118. viper.BindPFlag(configDirKey, cmd.Flags().Lookup(configDirFlag)) //nolint:errcheck
  119. viper.SetDefault(configFileKey, defaultConfigFile)
  120. viper.BindEnv(configFileKey, "SFTPGO_CONFIG_FILE") //nolint:errcheck
  121. cmd.Flags().StringVar(&configFile, configFileFlag, viper.GetString(configFileKey),
  122. `Path to SFTPGo configuration file.
  123. This flag explicitly defines the path, name
  124. and extension of the config file. If must be
  125. an absolute path or a path relative to the
  126. configuration directory. The specified file
  127. name must have a supported extension (JSON,
  128. YAML, TOML, HCL or Java properties).
  129. This flag can be set using SFTPGO_CONFIG_FILE
  130. env var too.`)
  131. viper.BindPFlag(configFileKey, cmd.Flags().Lookup(configFileFlag)) //nolint:errcheck
  132. }
  133. func addBaseLoadDataFlags(cmd *cobra.Command) {
  134. viper.SetDefault(loadDataFromKey, defaultLoadDataFrom)
  135. viper.BindEnv(loadDataFromKey, "SFTPGO_LOADDATA_FROM") //nolint:errcheck
  136. cmd.Flags().StringVar(&loadDataFrom, loadDataFromFlag, viper.GetString(loadDataFromKey),
  137. `Load users and folders from this file.
  138. The file must be specified as absolute path
  139. and it must contain a backup obtained using
  140. the "dumpdata" REST API or compatible content.
  141. This flag can be set using SFTPGO_LOADDATA_FROM
  142. env var too.
  143. `)
  144. viper.BindPFlag(loadDataFromKey, cmd.Flags().Lookup(loadDataFromFlag)) //nolint:errcheck
  145. viper.SetDefault(loadDataModeKey, defaultLoadDataMode)
  146. viper.BindEnv(loadDataModeKey, "SFTPGO_LOADDATA_MODE") //nolint:errcheck
  147. cmd.Flags().IntVar(&loadDataMode, loadDataModeFlag, viper.GetInt(loadDataModeKey),
  148. `Restore mode for data to load:
  149. 0 - new users are added, existing users are
  150. updated
  151. 1 - New users are added, existing users are
  152. not modified
  153. This flag can be set using SFTPGO_LOADDATA_MODE
  154. env var too.
  155. `)
  156. viper.BindPFlag(loadDataModeKey, cmd.Flags().Lookup(loadDataModeFlag)) //nolint:errcheck
  157. viper.SetDefault(loadDataCleanKey, defaultLoadDataClean)
  158. viper.BindEnv(loadDataCleanKey, "SFTPGO_LOADDATA_CLEAN") //nolint:errcheck
  159. cmd.Flags().BoolVar(&loadDataClean, loadDataCleanFlag, viper.GetBool(loadDataCleanKey),
  160. `Determine if the loaddata-from file should
  161. be removed after a successful load. This flag
  162. can be set using SFTPGO_LOADDATA_CLEAN env var
  163. too. (default "false")
  164. `)
  165. viper.BindPFlag(loadDataCleanKey, cmd.Flags().Lookup(loadDataCleanFlag)) //nolint:errcheck
  166. }
  167. func addServeFlags(cmd *cobra.Command) {
  168. addConfigFlags(cmd)
  169. viper.SetDefault(logFilePathKey, defaultLogFile)
  170. viper.BindEnv(logFilePathKey, "SFTPGO_LOG_FILE_PATH") //nolint:errcheck
  171. cmd.Flags().StringVarP(&logFilePath, logFilePathFlag, "l", viper.GetString(logFilePathKey),
  172. `Location for the log file. Leave empty to write
  173. logs to the standard output. This flag can be
  174. set using SFTPGO_LOG_FILE_PATH env var too.
  175. `)
  176. viper.BindPFlag(logFilePathKey, cmd.Flags().Lookup(logFilePathFlag)) //nolint:errcheck
  177. viper.SetDefault(logMaxSizeKey, defaultLogMaxSize)
  178. viper.BindEnv(logMaxSizeKey, "SFTPGO_LOG_MAX_SIZE") //nolint:errcheck
  179. cmd.Flags().IntVarP(&logMaxSize, logMaxSizeFlag, "s", viper.GetInt(logMaxSizeKey),
  180. `Maximum size in megabytes of the log file
  181. before it gets rotated. This flag can be set
  182. using SFTPGO_LOG_MAX_SIZE env var too. It is
  183. unused if log-file-path is empty.
  184. `)
  185. viper.BindPFlag(logMaxSizeKey, cmd.Flags().Lookup(logMaxSizeFlag)) //nolint:errcheck
  186. viper.SetDefault(logMaxBackupKey, defaultLogMaxBackup)
  187. viper.BindEnv(logMaxBackupKey, "SFTPGO_LOG_MAX_BACKUPS") //nolint:errcheck
  188. cmd.Flags().IntVarP(&logMaxBackups, "log-max-backups", "b", viper.GetInt(logMaxBackupKey),
  189. `Maximum number of old log files to retain.
  190. This flag can be set using SFTPGO_LOG_MAX_BACKUPS
  191. env var too. It is unused if log-file-path is
  192. empty.`)
  193. viper.BindPFlag(logMaxBackupKey, cmd.Flags().Lookup(logMaxBackupFlag)) //nolint:errcheck
  194. viper.SetDefault(logMaxAgeKey, defaultLogMaxAge)
  195. viper.BindEnv(logMaxAgeKey, "SFTPGO_LOG_MAX_AGE") //nolint:errcheck
  196. cmd.Flags().IntVarP(&logMaxAge, "log-max-age", "a", viper.GetInt(logMaxAgeKey),
  197. `Maximum number of days to retain old log files.
  198. This flag can be set using SFTPGO_LOG_MAX_AGE env
  199. var too. It is unused if log-file-path is empty.
  200. `)
  201. viper.BindPFlag(logMaxAgeKey, cmd.Flags().Lookup(logMaxAgeFlag)) //nolint:errcheck
  202. viper.SetDefault(logCompressKey, defaultLogCompress)
  203. viper.BindEnv(logCompressKey, "SFTPGO_LOG_COMPRESS") //nolint:errcheck
  204. cmd.Flags().BoolVarP(&logCompress, logCompressFlag, "z", viper.GetBool(logCompressKey),
  205. `Determine if the rotated log files
  206. should be compressed using gzip. This flag can
  207. be set using SFTPGO_LOG_COMPRESS env var too.
  208. It is unused if log-file-path is empty.
  209. `)
  210. viper.BindPFlag(logCompressKey, cmd.Flags().Lookup(logCompressFlag)) //nolint:errcheck
  211. viper.SetDefault(logLevelKey, defaultLogLevel)
  212. viper.BindEnv(logLevelKey, "SFTPGO_LOG_LEVEL") //nolint:errcheck
  213. cmd.Flags().StringVar(&logLevel, logLevelFlag, viper.GetString(logLevelKey),
  214. `Set the log level. Supported values:
  215. debug, info, warn, error.
  216. This flag can be set
  217. using SFTPGO_LOG_LEVEL env var too.
  218. `)
  219. viper.BindPFlag(logLevelKey, cmd.Flags().Lookup(logLevelFlag)) //nolint:errcheck
  220. viper.SetDefault(logUTCTimeKey, defaultLogUTCTime)
  221. viper.BindEnv(logUTCTimeKey, "SFTPGO_LOG_UTC_TIME") //nolint:errcheck
  222. cmd.Flags().BoolVar(&logUTCTime, logUTCTimeFlag, viper.GetBool(logUTCTimeKey),
  223. `Use UTC time for logging. This flag can be set
  224. using SFTPGO_LOG_UTC_TIME env var too.
  225. `)
  226. viper.BindPFlag(logUTCTimeKey, cmd.Flags().Lookup(logUTCTimeFlag)) //nolint:errcheck
  227. addBaseLoadDataFlags(cmd)
  228. viper.SetDefault(loadDataQuotaScanKey, defaultLoadDataQuotaScan)
  229. viper.BindEnv(loadDataQuotaScanKey, "SFTPGO_LOADDATA_QUOTA_SCAN") //nolint:errcheck
  230. cmd.Flags().IntVar(&loadDataQuotaScan, loadDataQuotaScanFlag, viper.GetInt(loadDataQuotaScanKey),
  231. `Quota scan mode after data load:
  232. 0 - no quota scan
  233. 1 - scan quota
  234. 2 - scan quota if the user has quota restrictions
  235. This flag can be set using SFTPGO_LOADDATA_QUOTA_SCAN
  236. env var too.
  237. (default 0)`)
  238. viper.BindPFlag(loadDataQuotaScanKey, cmd.Flags().Lookup(loadDataQuotaScanFlag)) //nolint:errcheck
  239. }