setting.go 20 KB

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