setting.go 20 KB

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