setting.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. // Copyright 2014 Unknwon
  2. // Copyright 2014 Torkel Ödegaard
  3. package setting
  4. import (
  5. "bytes"
  6. "fmt"
  7. "net/url"
  8. "os"
  9. "path"
  10. "path/filepath"
  11. "regexp"
  12. "runtime"
  13. "strings"
  14. "gopkg.in/ini.v1"
  15. "github.com/go-macaron/session"
  16. "github.com/grafana/grafana/pkg/log"
  17. "github.com/grafana/grafana/pkg/util"
  18. "time"
  19. )
  20. type Scheme string
  21. const (
  22. HTTP Scheme = "http"
  23. HTTPS Scheme = "https"
  24. SOCKET Scheme = "socket"
  25. DEFAULT_HTTP_ADDR string = "0.0.0.0"
  26. )
  27. const (
  28. DEV string = "development"
  29. PROD string = "production"
  30. TEST string = "test"
  31. )
  32. var (
  33. // App settings.
  34. Env = DEV
  35. AppUrl string
  36. AppSubUrl string
  37. InstanceName string
  38. // build
  39. BuildVersion string
  40. BuildCommit string
  41. BuildStamp int64
  42. Enterprise bool
  43. ApplicationName string
  44. // Paths
  45. LogsPath string
  46. HomePath string
  47. DataPath string
  48. PluginsPath string
  49. CustomInitPath = "conf/custom.ini"
  50. // Log settings.
  51. LogModes []string
  52. LogConfigs []util.DynMap
  53. // Http server options
  54. Protocol Scheme
  55. Domain string
  56. HttpAddr, HttpPort string
  57. SshPort int
  58. CertFile, KeyFile string
  59. SocketPath string
  60. RouterLogging bool
  61. DataProxyLogging bool
  62. StaticRootPath string
  63. EnableGzip bool
  64. EnforceDomain bool
  65. // Security settings.
  66. SecretKey string
  67. LogInRememberDays int
  68. CookieUserName string
  69. CookieRememberName string
  70. DisableGravatar bool
  71. EmailCodeValidMinutes int
  72. DataProxyWhiteList map[string]bool
  73. DisableBruteForceLoginProtection bool
  74. // Snapshots
  75. ExternalSnapshotUrl string
  76. ExternalSnapshotName string
  77. ExternalEnabled bool
  78. SnapShotRemoveExpired bool
  79. // Dashboard history
  80. DashboardVersionsToKeep int
  81. // User settings
  82. AllowUserSignUp bool
  83. AllowUserOrgCreate bool
  84. AutoAssignOrg bool
  85. AutoAssignOrgRole string
  86. VerifyEmailEnabled bool
  87. LoginHint string
  88. DefaultTheme string
  89. DisableLoginForm bool
  90. DisableSignoutMenu bool
  91. SignoutRedirectUrl string
  92. ExternalUserMngLinkUrl string
  93. ExternalUserMngLinkName string
  94. ExternalUserMngInfo string
  95. ViewersCanEdit bool
  96. // Http auth
  97. AdminUser string
  98. AdminPassword string
  99. AnonymousEnabled bool
  100. AnonymousOrgName string
  101. AnonymousOrgRole string
  102. // Auth proxy settings
  103. AuthProxyEnabled bool
  104. AuthProxyHeaderName string
  105. AuthProxyHeaderProperty string
  106. AuthProxyAutoSignUp bool
  107. AuthProxyLdapSyncTtl int
  108. AuthProxyWhitelist string
  109. AuthProxyHeaders map[string]string
  110. // Basic Auth
  111. BasicAuthEnabled bool
  112. // Plugin settings
  113. PluginAppsSkipVerifyTLS bool
  114. // Session settings.
  115. SessionOptions session.Options
  116. SessionConnMaxLifetime int64
  117. // Global setting objects.
  118. Raw *ini.File
  119. ConfRootPath string
  120. IsWindows bool
  121. // for logging purposes
  122. configFiles []string
  123. appliedCommandLineProperties []string
  124. appliedEnvOverrides []string
  125. ReportingEnabled bool
  126. CheckForUpdates bool
  127. GoogleAnalyticsId string
  128. GoogleTagManagerId string
  129. // LDAP
  130. LdapEnabled bool
  131. LdapConfigFile string
  132. LdapAllowSignup = true
  133. // QUOTA
  134. Quota QuotaSettings
  135. // Alerting
  136. AlertingEnabled bool
  137. ExecuteAlerts bool
  138. // Explore UI
  139. ExploreEnabled bool
  140. // logger
  141. logger log.Logger
  142. // Grafana.NET URL
  143. GrafanaComUrl string
  144. // S3 temp image store
  145. S3TempImageStoreBucketUrl string
  146. S3TempImageStoreAccessKey string
  147. S3TempImageStoreSecretKey string
  148. ImageUploadProvider string
  149. )
  150. type Cfg struct {
  151. Raw *ini.File
  152. // Paths
  153. ProvisioningPath string
  154. // SMTP email settings
  155. Smtp SmtpSettings
  156. // Rendering
  157. ImagesDir string
  158. PhantomDir string
  159. RendererUrl string
  160. DisableBruteForceLoginProtection bool
  161. TempDataLifetime time.Duration
  162. }
  163. type CommandLineArgs struct {
  164. Config string
  165. HomePath string
  166. Args []string
  167. }
  168. func init() {
  169. IsWindows = runtime.GOOS == "windows"
  170. logger = log.New("settings")
  171. }
  172. func parseAppUrlAndSubUrl(section *ini.Section) (string, string) {
  173. appUrl := section.Key("root_url").MustString("http://localhost:3000/")
  174. if appUrl[len(appUrl)-1] != '/' {
  175. appUrl += "/"
  176. }
  177. // Check if has app suburl.
  178. url, err := url.Parse(appUrl)
  179. if err != nil {
  180. log.Fatal(4, "Invalid root_url(%s): %s", appUrl, err)
  181. }
  182. appSubUrl := strings.TrimSuffix(url.Path, "/")
  183. return appUrl, appSubUrl
  184. }
  185. func ToAbsUrl(relativeUrl string) string {
  186. return AppUrl + relativeUrl
  187. }
  188. func shouldRedactKey(s string) bool {
  189. uppercased := strings.ToUpper(s)
  190. return strings.Contains(uppercased, "PASSWORD") || strings.Contains(uppercased, "SECRET") || strings.Contains(uppercased, "PROVIDER_CONFIG")
  191. }
  192. func shouldRedactURLKey(s string) bool {
  193. uppercased := strings.ToUpper(s)
  194. return strings.Contains(uppercased, "DATABASE_URL")
  195. }
  196. func applyEnvVariableOverrides(file *ini.File) error {
  197. appliedEnvOverrides = make([]string, 0)
  198. for _, section := range file.Sections() {
  199. for _, key := range section.Keys() {
  200. sectionName := strings.ToUpper(strings.Replace(section.Name(), ".", "_", -1))
  201. keyName := strings.ToUpper(strings.Replace(key.Name(), ".", "_", -1))
  202. envKey := fmt.Sprintf("GF_%s_%s", sectionName, keyName)
  203. envValue := os.Getenv(envKey)
  204. if len(envValue) > 0 {
  205. key.SetValue(envValue)
  206. if shouldRedactKey(envKey) {
  207. envValue = "*********"
  208. }
  209. if shouldRedactURLKey(envKey) {
  210. u, err := url.Parse(envValue)
  211. if err != nil {
  212. return fmt.Errorf("could not parse environment variable. key: %s, value: %s. error: %v", envKey, envValue, err)
  213. }
  214. ui := u.User
  215. if ui != nil {
  216. _, exists := ui.Password()
  217. if exists {
  218. u.User = url.UserPassword(ui.Username(), "-redacted-")
  219. envValue = u.String()
  220. }
  221. }
  222. }
  223. appliedEnvOverrides = append(appliedEnvOverrides, fmt.Sprintf("%s=%s", envKey, envValue))
  224. }
  225. }
  226. }
  227. return nil
  228. }
  229. func applyCommandLineDefaultProperties(props map[string]string, file *ini.File) {
  230. appliedCommandLineProperties = make([]string, 0)
  231. for _, section := range file.Sections() {
  232. for _, key := range section.Keys() {
  233. keyString := fmt.Sprintf("default.%s.%s", section.Name(), key.Name())
  234. value, exists := props[keyString]
  235. if exists {
  236. key.SetValue(value)
  237. if shouldRedactKey(keyString) {
  238. value = "*********"
  239. }
  240. appliedCommandLineProperties = append(appliedCommandLineProperties, fmt.Sprintf("%s=%s", keyString, value))
  241. }
  242. }
  243. }
  244. }
  245. func applyCommandLineProperties(props map[string]string, file *ini.File) {
  246. for _, section := range file.Sections() {
  247. sectionName := section.Name() + "."
  248. if section.Name() == ini.DEFAULT_SECTION {
  249. sectionName = ""
  250. }
  251. for _, key := range section.Keys() {
  252. keyString := sectionName + key.Name()
  253. value, exists := props[keyString]
  254. if exists {
  255. appliedCommandLineProperties = append(appliedCommandLineProperties, fmt.Sprintf("%s=%s", keyString, value))
  256. key.SetValue(value)
  257. }
  258. }
  259. }
  260. }
  261. func getCommandLineProperties(args []string) map[string]string {
  262. props := make(map[string]string)
  263. for _, arg := range args {
  264. if !strings.HasPrefix(arg, "cfg:") {
  265. continue
  266. }
  267. trimmed := strings.TrimPrefix(arg, "cfg:")
  268. parts := strings.Split(trimmed, "=")
  269. if len(parts) != 2 {
  270. log.Fatal(3, "Invalid command line argument", arg)
  271. return nil
  272. }
  273. props[parts[0]] = parts[1]
  274. }
  275. return props
  276. }
  277. func makeAbsolute(path string, root string) string {
  278. if filepath.IsAbs(path) {
  279. return path
  280. }
  281. return filepath.Join(root, path)
  282. }
  283. func evalEnvVarExpression(value string) string {
  284. regex := regexp.MustCompile(`\${(\w+)}`)
  285. return regex.ReplaceAllStringFunc(value, func(envVar string) string {
  286. envVar = strings.TrimPrefix(envVar, "${")
  287. envVar = strings.TrimSuffix(envVar, "}")
  288. envValue := os.Getenv(envVar)
  289. // if env variable is hostname and it is empty use os.Hostname as default
  290. if envVar == "HOSTNAME" && envValue == "" {
  291. envValue, _ = os.Hostname()
  292. }
  293. return envValue
  294. })
  295. }
  296. func evalConfigValues(file *ini.File) {
  297. for _, section := range file.Sections() {
  298. for _, key := range section.Keys() {
  299. key.SetValue(evalEnvVarExpression(key.Value()))
  300. }
  301. }
  302. }
  303. func loadSpecifedConfigFile(configFile string, masterFile *ini.File) error {
  304. if configFile == "" {
  305. configFile = filepath.Join(HomePath, CustomInitPath)
  306. // return without error if custom file does not exist
  307. if !pathExists(configFile) {
  308. return nil
  309. }
  310. }
  311. userConfig, err := ini.Load(configFile)
  312. if err != nil {
  313. return fmt.Errorf("Failed to parse %v, %v", configFile, err)
  314. }
  315. userConfig.BlockMode = false
  316. for _, section := range userConfig.Sections() {
  317. for _, key := range section.Keys() {
  318. if key.Value() == "" {
  319. continue
  320. }
  321. defaultSec, err := masterFile.GetSection(section.Name())
  322. if err != nil {
  323. defaultSec, _ = masterFile.NewSection(section.Name())
  324. }
  325. defaultKey, err := defaultSec.GetKey(key.Name())
  326. if err != nil {
  327. defaultKey, _ = defaultSec.NewKey(key.Name(), key.Value())
  328. }
  329. defaultKey.SetValue(key.Value())
  330. }
  331. }
  332. configFiles = append(configFiles, configFile)
  333. return nil
  334. }
  335. func loadConfiguration(args *CommandLineArgs) (*ini.File, error) {
  336. var err error
  337. // load config defaults
  338. defaultConfigFile := path.Join(HomePath, "conf/defaults.ini")
  339. configFiles = append(configFiles, defaultConfigFile)
  340. // check if config file exists
  341. if _, err := os.Stat(defaultConfigFile); os.IsNotExist(err) {
  342. fmt.Println("Grafana-server Init Failed: Could not find config defaults, make sure homepath command line parameter is set or working directory is homepath")
  343. os.Exit(1)
  344. }
  345. // load defaults
  346. parsedFile, err := ini.Load(defaultConfigFile)
  347. if err != nil {
  348. fmt.Println(fmt.Sprintf("Failed to parse defaults.ini, %v", err))
  349. os.Exit(1)
  350. return nil, err
  351. }
  352. parsedFile.BlockMode = false
  353. // command line props
  354. commandLineProps := getCommandLineProperties(args.Args)
  355. // load default overrides
  356. applyCommandLineDefaultProperties(commandLineProps, parsedFile)
  357. // load specified config file
  358. err = loadSpecifedConfigFile(args.Config, parsedFile)
  359. if err != nil {
  360. initLogging(parsedFile)
  361. log.Fatal(3, err.Error())
  362. }
  363. // apply environment overrides
  364. err = applyEnvVariableOverrides(parsedFile)
  365. if err != nil {
  366. return nil, err
  367. }
  368. // apply command line overrides
  369. applyCommandLineProperties(commandLineProps, parsedFile)
  370. // evaluate config values containing environment variables
  371. evalConfigValues(parsedFile)
  372. // update data path and logging config
  373. DataPath = makeAbsolute(parsedFile.Section("paths").Key("data").String(), HomePath)
  374. initLogging(parsedFile)
  375. return parsedFile, err
  376. }
  377. func pathExists(path string) bool {
  378. _, err := os.Stat(path)
  379. if err == nil {
  380. return true
  381. }
  382. if os.IsNotExist(err) {
  383. return false
  384. }
  385. return false
  386. }
  387. func setHomePath(args *CommandLineArgs) {
  388. if args.HomePath != "" {
  389. HomePath = args.HomePath
  390. return
  391. }
  392. HomePath, _ = filepath.Abs(".")
  393. // check if homepath is correct
  394. if pathExists(filepath.Join(HomePath, "conf/defaults.ini")) {
  395. return
  396. }
  397. // try down one path
  398. if pathExists(filepath.Join(HomePath, "../conf/defaults.ini")) {
  399. HomePath = filepath.Join(HomePath, "../")
  400. }
  401. }
  402. var skipStaticRootValidation = false
  403. func validateStaticRootPath() error {
  404. if skipStaticRootValidation {
  405. return nil
  406. }
  407. if _, err := os.Stat(path.Join(StaticRootPath, "build")); err != nil {
  408. logger.Error("Failed to detect generated javascript files in public/build")
  409. }
  410. return nil
  411. }
  412. func NewCfg() *Cfg {
  413. return &Cfg{
  414. Raw: ini.Empty(),
  415. }
  416. }
  417. func (cfg *Cfg) Load(args *CommandLineArgs) error {
  418. setHomePath(args)
  419. iniFile, err := loadConfiguration(args)
  420. if err != nil {
  421. return err
  422. }
  423. cfg.Raw = iniFile
  424. // Temporary keep global, to make refactor in steps
  425. Raw = cfg.Raw
  426. ApplicationName = "Grafana"
  427. if Enterprise {
  428. ApplicationName += " Enterprise"
  429. }
  430. Env = iniFile.Section("").Key("app_mode").MustString("development")
  431. InstanceName = iniFile.Section("").Key("instance_name").MustString("unknown_instance_name")
  432. PluginsPath = makeAbsolute(iniFile.Section("paths").Key("plugins").String(), HomePath)
  433. cfg.ProvisioningPath = makeAbsolute(iniFile.Section("paths").Key("provisioning").String(), HomePath)
  434. server := iniFile.Section("server")
  435. AppUrl, AppSubUrl = parseAppUrlAndSubUrl(server)
  436. Protocol = HTTP
  437. if server.Key("protocol").MustString("http") == "https" {
  438. Protocol = HTTPS
  439. CertFile = server.Key("cert_file").String()
  440. KeyFile = server.Key("cert_key").String()
  441. }
  442. if server.Key("protocol").MustString("http") == "socket" {
  443. Protocol = SOCKET
  444. SocketPath = server.Key("socket").String()
  445. }
  446. Domain = server.Key("domain").MustString("localhost")
  447. HttpAddr = server.Key("http_addr").MustString(DEFAULT_HTTP_ADDR)
  448. HttpPort = server.Key("http_port").MustString("3000")
  449. RouterLogging = server.Key("router_logging").MustBool(false)
  450. EnableGzip = server.Key("enable_gzip").MustBool(false)
  451. EnforceDomain = server.Key("enforce_domain").MustBool(false)
  452. StaticRootPath = makeAbsolute(server.Key("static_root_path").String(), HomePath)
  453. if err := validateStaticRootPath(); err != nil {
  454. return err
  455. }
  456. // read data proxy settings
  457. dataproxy := iniFile.Section("dataproxy")
  458. DataProxyLogging = dataproxy.Key("logging").MustBool(false)
  459. // read security settings
  460. security := iniFile.Section("security")
  461. SecretKey = security.Key("secret_key").String()
  462. LogInRememberDays = security.Key("login_remember_days").MustInt()
  463. CookieUserName = security.Key("cookie_username").String()
  464. CookieRememberName = security.Key("cookie_remember_name").String()
  465. DisableGravatar = security.Key("disable_gravatar").MustBool(true)
  466. cfg.DisableBruteForceLoginProtection = security.Key("disable_brute_force_login_protection").MustBool(false)
  467. DisableBruteForceLoginProtection = cfg.DisableBruteForceLoginProtection
  468. // read snapshots settings
  469. snapshots := iniFile.Section("snapshots")
  470. ExternalSnapshotUrl = snapshots.Key("external_snapshot_url").String()
  471. ExternalSnapshotName = snapshots.Key("external_snapshot_name").String()
  472. ExternalEnabled = snapshots.Key("external_enabled").MustBool(true)
  473. SnapShotRemoveExpired = snapshots.Key("snapshot_remove_expired").MustBool(true)
  474. // read dashboard settings
  475. dashboards := iniFile.Section("dashboards")
  476. DashboardVersionsToKeep = dashboards.Key("versions_to_keep").MustInt(20)
  477. // read data source proxy white list
  478. DataProxyWhiteList = make(map[string]bool)
  479. for _, hostAndIp := range util.SplitString(security.Key("data_source_proxy_whitelist").String()) {
  480. DataProxyWhiteList[hostAndIp] = true
  481. }
  482. // admin
  483. AdminUser = security.Key("admin_user").String()
  484. AdminPassword = security.Key("admin_password").String()
  485. users := iniFile.Section("users")
  486. AllowUserSignUp = users.Key("allow_sign_up").MustBool(true)
  487. AllowUserOrgCreate = users.Key("allow_org_create").MustBool(true)
  488. AutoAssignOrg = users.Key("auto_assign_org").MustBool(true)
  489. AutoAssignOrgRole = users.Key("auto_assign_org_role").In("Editor", []string{"Editor", "Admin", "Viewer"})
  490. VerifyEmailEnabled = users.Key("verify_email_enabled").MustBool(false)
  491. LoginHint = users.Key("login_hint").String()
  492. DefaultTheme = users.Key("default_theme").String()
  493. ExternalUserMngLinkUrl = users.Key("external_manage_link_url").String()
  494. ExternalUserMngLinkName = users.Key("external_manage_link_name").String()
  495. ExternalUserMngInfo = users.Key("external_manage_info").String()
  496. ViewersCanEdit = users.Key("viewers_can_edit").MustBool(false)
  497. // auth
  498. auth := iniFile.Section("auth")
  499. DisableLoginForm = auth.Key("disable_login_form").MustBool(false)
  500. DisableSignoutMenu = auth.Key("disable_signout_menu").MustBool(false)
  501. SignoutRedirectUrl = auth.Key("signout_redirect_url").String()
  502. // anonymous access
  503. AnonymousEnabled = iniFile.Section("auth.anonymous").Key("enabled").MustBool(false)
  504. AnonymousOrgName = iniFile.Section("auth.anonymous").Key("org_name").String()
  505. AnonymousOrgRole = iniFile.Section("auth.anonymous").Key("org_role").String()
  506. // auth proxy
  507. authProxy := iniFile.Section("auth.proxy")
  508. AuthProxyEnabled = authProxy.Key("enabled").MustBool(false)
  509. AuthProxyHeaderName = authProxy.Key("header_name").String()
  510. AuthProxyHeaderProperty = authProxy.Key("header_property").String()
  511. AuthProxyAutoSignUp = authProxy.Key("auto_sign_up").MustBool(true)
  512. AuthProxyLdapSyncTtl = authProxy.Key("ldap_sync_ttl").MustInt()
  513. AuthProxyWhitelist = authProxy.Key("whitelist").String()
  514. AuthProxyHeaders = make(map[string]string)
  515. for _, propertyAndHeader := range util.SplitString(authProxy.Key("headers").String()) {
  516. split := strings.SplitN(propertyAndHeader, ":", 2)
  517. if len(split) == 2 {
  518. AuthProxyHeaders[split[0]] = split[1]
  519. }
  520. }
  521. // basic auth
  522. authBasic := iniFile.Section("auth.basic")
  523. BasicAuthEnabled = authBasic.Key("enabled").MustBool(true)
  524. // global plugin settings
  525. PluginAppsSkipVerifyTLS = iniFile.Section("plugins").Key("app_tls_skip_verify_insecure").MustBool(false)
  526. // Rendering
  527. renderSec := iniFile.Section("rendering")
  528. cfg.RendererUrl = renderSec.Key("server_url").String()
  529. cfg.ImagesDir = filepath.Join(DataPath, "png")
  530. cfg.PhantomDir = filepath.Join(HomePath, "tools/phantomjs")
  531. cfg.TempDataLifetime = iniFile.Section("paths").Key("temp_data_lifetime").MustDuration(
  532. time.Duration(time.Second * 3600 * 24),
  533. )
  534. analytics := iniFile.Section("analytics")
  535. ReportingEnabled = analytics.Key("reporting_enabled").MustBool(true)
  536. CheckForUpdates = analytics.Key("check_for_updates").MustBool(true)
  537. GoogleAnalyticsId = analytics.Key("google_analytics_ua_id").String()
  538. GoogleTagManagerId = analytics.Key("google_tag_manager_id").String()
  539. ldapSec := iniFile.Section("auth.ldap")
  540. LdapEnabled = ldapSec.Key("enabled").MustBool(false)
  541. LdapConfigFile = ldapSec.Key("config_file").String()
  542. LdapAllowSignup = ldapSec.Key("allow_sign_up").MustBool(true)
  543. alerting := iniFile.Section("alerting")
  544. AlertingEnabled = alerting.Key("enabled").MustBool(true)
  545. ExecuteAlerts = alerting.Key("execute_alerts").MustBool(true)
  546. explore := iniFile.Section("explore")
  547. ExploreEnabled = explore.Key("enabled").MustBool(false)
  548. cfg.readSessionConfig()
  549. cfg.readSmtpSettings()
  550. cfg.readQuotaSettings()
  551. if VerifyEmailEnabled && !cfg.Smtp.Enabled {
  552. log.Warn("require_email_validation is enabled but smtp is disabled")
  553. }
  554. // check old key name
  555. GrafanaComUrl = iniFile.Section("grafana_net").Key("url").MustString("")
  556. if GrafanaComUrl == "" {
  557. GrafanaComUrl = iniFile.Section("grafana_com").Key("url").MustString("https://grafana.com")
  558. }
  559. imageUploadingSection := iniFile.Section("external_image_storage")
  560. ImageUploadProvider = imageUploadingSection.Key("provider").MustString("")
  561. return nil
  562. }
  563. func (cfg *Cfg) readSessionConfig() {
  564. sec := cfg.Raw.Section("session")
  565. SessionOptions = session.Options{}
  566. SessionOptions.Provider = sec.Key("provider").In("memory", []string{"memory", "file", "redis", "mysql", "postgres", "memcache"})
  567. SessionOptions.ProviderConfig = strings.Trim(sec.Key("provider_config").String(), "\" ")
  568. SessionOptions.CookieName = sec.Key("cookie_name").MustString("grafana_sess")
  569. SessionOptions.CookiePath = AppSubUrl
  570. SessionOptions.Secure = sec.Key("cookie_secure").MustBool()
  571. SessionOptions.Gclifetime = cfg.Raw.Section("session").Key("gc_interval_time").MustInt64(86400)
  572. SessionOptions.Maxlifetime = cfg.Raw.Section("session").Key("session_life_time").MustInt64(86400)
  573. SessionOptions.IDLength = 16
  574. if SessionOptions.Provider == "file" {
  575. SessionOptions.ProviderConfig = makeAbsolute(SessionOptions.ProviderConfig, DataPath)
  576. os.MkdirAll(path.Dir(SessionOptions.ProviderConfig), os.ModePerm)
  577. }
  578. if SessionOptions.CookiePath == "" {
  579. SessionOptions.CookiePath = "/"
  580. }
  581. SessionConnMaxLifetime = cfg.Raw.Section("session").Key("conn_max_lifetime").MustInt64(14400)
  582. }
  583. func initLogging(file *ini.File) {
  584. // split on comma
  585. LogModes = strings.Split(file.Section("log").Key("mode").MustString("console"), ",")
  586. // also try space
  587. if len(LogModes) == 1 {
  588. LogModes = strings.Split(file.Section("log").Key("mode").MustString("console"), " ")
  589. }
  590. LogsPath = makeAbsolute(file.Section("paths").Key("logs").String(), HomePath)
  591. log.ReadLoggingConfig(LogModes, LogsPath, file)
  592. }
  593. func (cfg *Cfg) LogConfigSources() {
  594. var text bytes.Buffer
  595. for _, file := range configFiles {
  596. logger.Info("Config loaded from", "file", file)
  597. }
  598. if len(appliedCommandLineProperties) > 0 {
  599. for _, prop := range appliedCommandLineProperties {
  600. logger.Info("Config overridden from command line", "arg", prop)
  601. }
  602. }
  603. if len(appliedEnvOverrides) > 0 {
  604. text.WriteString("\tEnvironment variables used:\n")
  605. for _, prop := range appliedEnvOverrides {
  606. logger.Info("Config overridden from Environment variable", "var", prop)
  607. }
  608. }
  609. logger.Info("Path Home", "path", HomePath)
  610. logger.Info("Path Data", "path", DataPath)
  611. logger.Info("Path Logs", "path", LogsPath)
  612. logger.Info("Path Plugins", "path", PluginsPath)
  613. logger.Info("Path Provisioning", "path", cfg.ProvisioningPath)
  614. logger.Info("App mode " + Env)
  615. }