diff --git a/build.go b/build.go index 5f22292ff5a..80ef6ec36d1 100644 --- a/build.go +++ b/build.go @@ -115,7 +115,7 @@ func createPackage(packageType string, defaultPath string) { configDir := "/etc/grafana" configFilePath := "/etc/grafana/grafana.ini" defaultFilePath := filepath.Join("/etc/", defaultPath, "grafana-server") - grafanaServerBinPath := "/usr/bin/" + serverBinaryName + grafanaServerBinPath := "/usr/sbin/" + serverBinaryName initdScriptPath := "/etc/init.d/grafana-server" systemdServiceFilePath := "/usr/lib/systemd/system/grafana-server.service" @@ -128,25 +128,25 @@ func createPackage(packageType string, defaultPath string) { systemdFileSrc := filepath.Join(packageConfDir, "systemd/grafana-server.service") // create directories - runError("mkdir", "-p", filepath.Join(packageRoot, homeDir)) - runError("mkdir", "-p", filepath.Join(packageRoot, configDir)) - runError("mkdir", "-p", filepath.Join(packageRoot, "/etc/init.d")) - runError("mkdir", "-p", filepath.Join(packageRoot, "/etc/", defaultPath)) - runError("mkdir", "-p", filepath.Join(packageRoot, "/usr/lib/systemd/system")) - runError("mkdir", "-p", filepath.Join(packageRoot, "/usr/bin")) + runPrint("mkdir", "-p", filepath.Join(packageRoot, homeDir)) + runPrint("mkdir", "-p", filepath.Join(packageRoot, configDir)) + runPrint("mkdir", "-p", filepath.Join(packageRoot, "/etc/init.d")) + runPrint("mkdir", "-p", filepath.Join(packageRoot, "/etc/", defaultPath)) + runPrint("mkdir", "-p", filepath.Join(packageRoot, "/usr/lib/systemd/system")) + runPrint("mkdir", "-p", filepath.Join(packageRoot, "/usr/sbin")) // copy binary - runError("cp", "-p", filepath.Join(workingDir, "tmp/bin/"+serverBinaryName), grafanaServerBinPath) + runPrint("cp", "-p", filepath.Join(workingDir, "tmp/bin/"+serverBinaryName), filepath.Join(packageRoot, grafanaServerBinPath)) // copy init.d script - runError("cp", "-p", initdScriptSrc, filepath.Join(packageRoot, initdScriptPath)) + runPrint("cp", "-p", initdScriptSrc, filepath.Join(packageRoot, initdScriptPath)) // copy environment var file - runError("cp", "-p", defaultFileSrc, filepath.Join(packageRoot, defaultFilePath)) + runPrint("cp", "-p", defaultFileSrc, filepath.Join(packageRoot, defaultFilePath)) // copy systemd file runPrint("cp", "-p", systemdFileSrc, filepath.Join(packageRoot, systemdServiceFilePath)) // copy release files - runError("cp", "-a", filepath.Join(workingDir, "tmp")+"/.", filepath.Join(packageRoot, homeDir)) + runPrint("cp", "-a", filepath.Join(workingDir, "tmp")+"/.", filepath.Join(packageRoot, homeDir)) // copy sample ini file to /etc/opt/grafana - runError("cp", "conf/sample.ini", filepath.Join(packageRoot, configFilePath)) + runPrint("cp", "conf/sample.ini", filepath.Join(packageRoot, configFilePath)) args := []string{ "-s", "dir", diff --git a/conf/defaults.ini b/conf/defaults.ini index dd14e2e387b..dd83d9aa190 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -96,10 +96,13 @@ google_analytics_ua_id = [security] # default admin user, created on startup admin_user = admin + # default admin password, can be changed before first start of grafana, or in profile settings admin_password = admin + # used for signing secret_key = SW2YcwTIb9zpOOhoPsMm + # Auto-login remember days login_remember_days = 7 cookie_username = grafana_user @@ -109,10 +112,13 @@ cookie_remember_name = grafana_remember [users] # disable user signup / registration allow_sign_up = true + # Allow non admin users to create organizations allow_org_create = true + # Set to true to automatically assign new users to the default organization (id 1) auto_assign_org = true + # Default role new users will be automatically assigned (if disabled above is set to true) auto_assign_org_role = Viewer @@ -120,8 +126,10 @@ auto_assign_org_role = Viewer [auth.anonymous] # enable anonymous access enabled = false + # specify organization name that should be used for unauthenticated users org_name = Main Org. + # specify role for unauthenticated users org_role = Viewer @@ -152,8 +160,10 @@ token_url = https://accounts.google.com/o/oauth2/token # Either "console", "file", default is "console" # Use comma to separate multiple modes, e.g. "console, file" mode = console, file + # Buffer length of channel, keep it as it is if you don't know what it is. buffer_len = 10000 + # Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace" level = Info @@ -164,15 +174,19 @@ level = # For "file" mode only [log.file] level = -; This enables automated log rotate(switch of following options), default is true +# This enables automated log rotate(switch of following options), default is true log_rotate = true -; Max line number of single file, default is 1000000 + +# Max line number of single file, default is 1000000 max_lines = 1000000 -; Max size shift of single file, default is 28 means 1 << 28, 256MB + +# Max size shift of single file, default is 28 means 1 << 28, 256MB max_lines_shift = 28 -; Segment log daily, default is true + +# Segment log daily, default is true daily_rotate = true -; Expired days of log file(delete after max days), default is 7 + +# Expired days of log file(delete after max days), default is 7 max_days = 7 #################################### AMPQ Event Publisher ########################## diff --git a/conf/sample.ini b/conf/sample.ini index 53164d29dbc..9a340c74975 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -1,7 +1,7 @@ ##################### Grafana Configuration Example ##################### - -# Sample grafana config for deb & rpm packages -# You only need to specify overrides here +# +# Everything has defaults so you only need to uncomment things you want to +# change ; app_mode = production @@ -15,24 +15,182 @@ # ;logs = /var/log/grafana +#################################### Server #################################### [server] -; protocol (http or https) +# Protocol (http or https) ;protocol = http -; the ip address to bind to, empty will bind to all interfaces + +# The ip address to bind to, empty will bind to all interfaces ;http_addr = -; the http port to use + +# The http port to use ;http_port = 3000 -; The public facing domain name used to access grafana from a browser + +# The public facing domain name used to access grafana from a browser ;domain = localhost -; the full public facing url + +# The full public facing url ;root_url = %(protocol)s://%(domain)s:%(http_port)s/ + +# Log web requests ;router_logging = false -; the path relative home path where frontend assets are located + +# the path relative working path ;static_root_path = public -; enable gzip + +# enable gzip ;enable_gzip = false -; https certs & key file + +# https certs & key file ;cert_file = ;cert_key = +#################################### Database #################################### +[database] +# Either "mysql", "postgres" or "sqlite3", it's your choice +;type = sqlite3 +;host = 127.0.0.1:3306 +;name = grafana +;user = root +;password = + +# For "postgres" only, either "disable", "require" or "verify-full" +;ssl_mode = disable + +# For "sqlite3" only, path relative to data_path setting +;path = grafana.db + +#################################### Session #################################### +[session] +# Either "memory", "file", "redis", "mysql", default is "memory" +;provider = file + +# Provider config options +# memory: not have any config yet +# file: session dir path, is relative to grafana data_path +# redis: config like redis server addr, poolSize, password, e.g. `127.0.0.1:6379,100,grafana` +# mysql: go-sql-driver/mysql dsn config string, e.g. `user:password@tcp(127.0.0.1)/database_name` +;provider_config = sessions + +# Session cookie name +;cookie_name = grafana_sess + +# If you use session in https only, default is false +;cookie_secure = false + +# Session life time, default is 86400 +;session_life_time = 86400 + +#################################### Analytics #################################### +[analytics] +# Server reporting, sends usage counters to stats.grafana.org every 24 hours. +# No ip addresses are being tracked, only simple counters to track +# running instances, dashboard and error counts. It is very helpful to us. +# Change this option to false to disable reporting. +;reporting_enabled = true + +# Google Analytics universal tracking code, only enabled if you specify an id here +;google_analytics_ua_id = + +#################################### Security #################################### +[security] +# default admin user, created on startup +;admin_user = admin + +# default admin password, can be changed before first start of grafana, or in profile settings +;admin_password = admin + +# used for signing +;secret_key = SW2YcwTIb9zpOOhoPsMm + +# Auto-login remember days +;login_remember_days = 7 +;cookie_username = grafana_user +;cookie_remember_name = grafana_remember + +#################################### Users #################################### +[users] +# disable user signup / registration +;allow_sign_up = true + +# Allow non admin users to create organizations +;allow_org_create = true + +# Set to true to automatically assign new users to the default organization (id 1) +;auto_assign_org = true + +# Default role new users will be automatically assigned (if disabled above is set to true) +;auto_assign_org_role = Viewer + +#################################### Anonymous Auth ########################## +[auth.anonymous] +# enable anonymous access +;enabled = false + +# specify organization name that should be used for unauthenticated users +;org_name = Main Org. + +# specify role for unauthenticated users +;org_role = Viewer + +#################################### Github Auth ########################## +[auth.github] +;enabled = false +;client_id = some_id +;client_secret = some_secret +;scopes = user:email +;auth_url = https://github.com/login/oauth/authorize +;token_url = https://github.com/login/oauth/access_token +# Uncomment bellow to only allow specific email domains +; allowed_domains = mycompany.com othercompany.com + +#################################### Google Auth ########################## +[auth.google] +;enabled = false +;client_id = some_client_id +;client_secret = some_client_secret +;scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email +;auth_url = https://accounts.google.com/o/oauth2/auth +;token_url = https://accounts.google.com/o/oauth2/token +# Uncomment bellow to only allow specific email domains +; allowed_domains = mycompany.com othercompany.com + +#################################### Logging ########################## +[log] +# Either "console", "file", default is "console" +# Use comma to separate multiple modes, e.g. "console, file" +;mode = console, file + +# Buffer length of channel, keep it as it is if you don't know what it is. +;buffer_len = 10000 + +# Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace" +;level = Info + +# For "console" mode only +[log.console] +;level = + +# For "file" mode only +[log.file] +;level = +# This enables automated log rotate(switch of following options), default is true +;log_rotate = true + +# Max line number of single file, default is 1000000 +;max_lines = 1000000 + +# Max size shift of single file, default is 28 means 1 << 28, 256MB +;max_lines_shift = 28 + +# Segment log daily, default is true +;daily_rotate = true + +# Expired days of log file(delete after max days), default is 7 +;max_days = 7 +#################################### AMPQ Event Publisher ########################## +[event_publisher] +;enabled = false +;rabbitmq_url = amqp://localhost/ +;exchange = grafana_events diff --git a/docker/debtest/Dockerfile b/docker/debtest/Dockerfile index 30c5f3d08c9..ee752c98e7d 100644 --- a/docker/debtest/Dockerfile +++ b/docker/debtest/Dockerfile @@ -1,4 +1,6 @@ FROM debian:jessie +RUN apt-get update && apt-get install -y vim + ADD *.deb /tmp/ diff --git a/packaging/deb/control/postinst b/packaging/deb/control/postinst index ba8b9fed6cf..84c6ff60906 100755 --- a/packaging/deb/control/postinst +++ b/packaging/deb/control/postinst @@ -49,15 +49,15 @@ case "$1" in if [ -x /bin/systemctl ] ; then echo "### NOT starting on installation, please execute the following statements to configure elasticsearch to start automatically using systemd" echo " sudo /bin/systemctl daemon-reload" - echo " sudo /bin/systemctl enable grafana.service" - echo "### You can start grafana by executing" - echo " sudo /bin/systemctl start grafana.service" + echo " sudo /bin/systemctl enable grafana-server.service" + echo "### You can start grafana-server by executing" + echo " sudo /bin/systemctl start grafana-server.service" elif [ -x /usr/sbin/update-rc.d ] ; then - echo "### NOT starting grafana by default on bootup, please execute" - echo " sudo update-rc.d grafana defaults 95 10" - echo "### In order to start grafana, execute" - echo " sudo /etc/init.d/grafana start" + echo "### NOT starting grafana-server by default on bootup, please execute" + echo " sudo update-rc.d grafana-server defaults 95 10" + echo "### In order to start grafana-server, execute" + echo " sudo service grafana-server start" fi fi ;; diff --git a/packaging/deb/init.d/grafana-server b/packaging/deb/init.d/grafana-server index 0233f02980a..1525a8ae543 100755 --- a/packaging/deb/init.d/grafana-server +++ b/packaging/deb/init.d/grafana-server @@ -22,7 +22,19 @@ PATH=/bin:/usr/bin:/sbin:/usr/sbin NAME=grafana-server DESC="Grafana Server" -DEFAULT=/etc/default/grafana-server +DEFAULT=/etc/default/$NAME + +GRAFANA_USER=grafana +GRAFANA_GROUP=grafana +GRAFANA_HOME=/usr/share/grafana +CONF_DIR=/etc/grafana +WORK_DIR=$GRAFANA_HOME +DATA_DIR=/var/lib/grafana +LOG_DIR=/var/log/grafana +CONF_FILE=$CONF_DIR/grafana.ini +MAX_OPEN_FILES=10000 +PID_FILE=/var/run/$NAME.pid +DAEMON=/usr/sbin/$NAME if [ `id -u` -ne 0 ]; then echo "You need root privileges to run this script" @@ -35,23 +47,11 @@ if [ -r /etc/default/rcS ]; then . /etc/default/rcS fi -GRAFANA_USER=grafana -GRAFANA_GROUP=grafana -GRAFANA_HOME=/usr/share/grafana -CONF_DIR=/etc/grafana -WORK_DIR=$GRAFANA_HOME -DATA_DIR=/var/lib/grafana -LOG_DIR=/var/log/grafana -CONF_FILE=$CONF_DIR/grafana.ini -MAX_OPEN_FILES=10000 - # overwrite settings from default file if [ -f "$DEFAULT" ]; then . "$DEFAULT" fi -PID_FILE=/var/run/$NAME.pid -DAEMON=/usr/bin/grafana-server DAEMON_OPTS="--pidfile=${PID_FILE} --config=${CONF_FILE} cfg:default.paths.data=${DATA_DIR} cfg:default.paths.logs=${LOG_DIR}" # Check DAEMON exists diff --git a/packaging/deb/systemd/grafana-server.service b/packaging/deb/systemd/grafana-server.service index 764de90d3fd..7f5b1427252 100644 --- a/packaging/deb/systemd/grafana-server.service +++ b/packaging/deb/systemd/grafana-server.service @@ -9,7 +9,7 @@ EnvironmentFile=/etc/default/grafana User=grafana Group=grafana Type=simple -ExecStart=/usr/bin/grafana-server \ +ExecStart=/usr/sbin/grafana-server \ --config=${CONF_FILE} \ cfg:default.paths.data=${LOG_DIR} \ cfg:default.paths.data=${DATA_DIR} \ diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index d6e6d0f4e64..61d3c483695 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -225,6 +225,33 @@ func evalConfigValues() { } } +func loadSpecifedConfigFile(configFile string) { + userConfig, err := ini.Load(configFile) + if err != nil { + log.Fatal(3, "Failed to parse %v, %v", configFile, err) + } + + for _, section := range userConfig.Sections() { + for _, key := range section.Keys() { + if key.Value() == "" { + continue + } + + defaultSec, err := Cfg.GetSection(section.Name()) + if err != nil { + log.Fatal(3, "Unknown config section %s defined in %s", section.Name(), configFile) + } + defaultKey, err := defaultSec.GetKey(key.Name()) + if err != nil { + log.Fatal(3, "Unknown config key %s defined in section %s, in file", key.Name(), section.Name(), configFile) + } + defaultKey.SetValue(key.Value()) + } + } + + configFiles = append(configFiles, configFile) +} + func loadConfiguration(args *CommandLineArgs) { var err error @@ -249,12 +276,7 @@ func loadConfiguration(args *CommandLineArgs) { // load specified config file if args.Config != "" { - err = Cfg.Append(args.Config) - if err != nil { - log.Fatal(3, "Failed to parse %v, %v", args.Config, err) - } - configFiles = append(configFiles, args.Config) - appliedCommandLineProperties = append(appliedCommandLineProperties, "config="+args.Config) + loadSpecifedConfigFile(args.Config) } // apply environment overrides diff --git a/pkg/setting/setting_test.go b/pkg/setting/setting_test.go index ad97939ca1b..1d0582a32cf 100644 --- a/pkg/setting/setting_test.go +++ b/pkg/setting/setting_test.go @@ -49,10 +49,13 @@ func TestLoadingSettings(t *testing.T) { Convey("Should be able to override defaults via command line", func() { NewConfigContext(&CommandLineArgs{ - Args: []string{"cfg:default.paths.data=/tmp/data"}, + Args: []string{ + "cfg:default.server.domain=test2", + }, + Config: filepath.Join(HomePath, "tests/config-files/override.ini"), }) - So(DataPath, ShouldEqual, "/tmp/data") + So(Domain, ShouldEqual, "test2") }) Convey("Defaults can be overriden in specified config file", func() { diff --git a/tests/config-files/override.ini b/tests/config-files/override.ini index 4bcb5574973..9cd79bb8a72 100644 --- a/tests/config-files/override.ini +++ b/tests/config-files/override.ini @@ -1,2 +1,3 @@ [paths] data = /tmp/override +