wborn / openhab-grafana

JavaScript utilities and examples for using Grafana with openHAB
MIT License
46 stars 12 forks source link

Connection problem in Basic UI on pages with embedded grafana panels and NGINX in place #18

Closed HKN007 closed 5 years ago

HKN007 commented 5 years ago

Hi wborn, Hi All,

after having problems with openHAB pages not reloading with parameter change, i installed a reverse proxy to solve the Same-origin policy issue. Now on IE, Chrome, Firefox and Android App, everything works fine.

The downside is that with the reverse proxy enabled, i receive approx. every minute a message in Basic UI saying "Offline: Waiting for connection".

I'm running everyhting inside a local network with openHABian on Pi3B. My versions are: openHab 2.5.0 M1 grafana 5.1.4 nginx 1.10.3

Can you please have a look on my configs below? Might be that i have missed something or you have a clever idea which can help me. I'm stuck.

Thanks a lot BR Henning

NGINX:

#################################
# openHABian NGINX Confiuration #
#################################

## Redirection
server {
        listen                          80;
        server_name                     192.168.2.55;
        return 301                      https://$server_name$request_uri;
}

## Reverse Proxy to openHAB
server {
        listen                          443 ssl;
        server_name                     192.168.2.55;

        ## Secure Certificate Locations
        ssl_certificate                 /etc/ssl/certs/openhab.crt;
        ssl_certificate_key             /etc/ssl/certs/openhab.key;
        add_header                      Strict-Transport-Security "max-age=31536000; includeSubDomains";

        # Cross-Origin Resource Sharing.
        add_header 'Access-Control-Allow-Origin' 'http://localhost:8080/rest';
        add_header 'Access-Control-Allow_Credentials' 'true';
        add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
        add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';

        location / {
                proxy_pass                              http://localhost:8080/;
                # proxy_buffering                         off;  # openHAB supports non-buffering specifically for SSEs now
                proxy_set_header Host                   $http_host;
                proxy_set_header X-Real-IP              $remote_addr;
                proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto      $scheme;

                ## Password Protection
                auth_basic                              "Username and Password Required";
                auth_basic_user_file                    /etc/nginx/.htpasswd;
        }

        location /grafana/ {
                proxy_pass                              http://localhost:3000/;
        }
}

Grafana.ini:

##################### Grafana Configuration Example #####################
#
# Everything has defaults so you only need to uncomment things you want to
# change

# possible values : production, development
;app_mode = production

# instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty
;instance_name = ${HOSTNAME}

#################################### Paths ####################################
[paths]
# Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used)
;data = /var/lib/grafana

# Directory where grafana can store logs
;logs = /var/log/grafana

# Directory where grafana will automatically scan and look for plugins
;plugins = /var/lib/grafana/plugins

# folder that contains provisioning config files that grafana will apply on startup and while running.
;provisioning = conf/provisioning

#################################### Server ####################################
[server]
# Protocol (http, https, socket)
#protocol = http

# The ip address to bind to, empty will bind to all interfaces
#http_addr = 192.168.2.55

# The http port  to use
# http_port = 3000

# The public facing domain name used to access grafana from a browser
#domain = 192.168.2.55

# Redirect to correct domain if host header does not match domain
# Prevents DNS rebinding attacks
;enforce_domain = false

# The full public facing url you use in browser, used for redirects and emails
# If you use reverse proxy and sub path specify full url (with sub path)
# NGINX reverse proxy host e.g. port config:
root_url = %(protocol)s://%(domain)s/grafana/
# Normal host e.g. port config:
#root_url = http://localhost/grafana/

# Log web requests
;router_logging = false

# the path relative working path
;static_root_path = public

# enable gzip
;enable_gzip = false

# https certs & key file
;cert_file =
;cert_key =

# Unix socket path
;socket =

#################################### Database ####################################
[database]
# You can configure the database connection by specifying type, host, name, user and password
# as separate properties or as on string using the url properties.

# Either "mysql", "postgres" or "sqlite3", it's your choice
;type = sqlite3
;host = 127.0.0.1:3306
;name = grafana
;user = root
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
;password =

# Use either URL or the previous fields to configure the database
# Example: mysql://user:secret@host:port/database
;url =

# For "postgres" only, either "disable", "require" or "verify-full"
;ssl_mode = disable

# For "sqlite3" only, path relative to data_path setting
;path = grafana.db

# Max idle conn setting default is 2
;max_idle_conn = 2

# Max conn setting default is 0 (mean not set)
;max_open_conn =

# Connection Max Lifetime default is 14400 (means 14400 seconds or 4 hours)
;conn_max_lifetime = 14400

# Set to true to log the sql calls and execution times.
log_queries =

#################################### Session ####################################
[session]
# Either "memory", "file", "redis", "mysql", "postgres", default is "file"
;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 e.g. `addr=127.0.0.1:6379,pool_size=100,db=grafana`
# mysql: go-sql-driver/mysql dsn config string, e.g. `user:password@tcp(127.0.0.1:3306)/database_name`
# postgres: user=a password=b host=localhost port=5432 dbname=c sslmode=disable
;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

#################################### Data proxy ###########################
[dataproxy]

# This enables data proxy logging, default is false
;logging = false

#################################### 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

# Set to false to disable all checks to https://grafana.net
# for new vesions (grafana itself and plugins), check is used
# in some UI views to notify that grafana or plugin update exists
# This option does not cause any auto updates, nor send any information
# only a GET request to http://grafana.com to get latest versions
;check_for_updates = 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

# disable gravatar profile images
;disable_gravatar = false

# data source proxy whitelist (ip_or_domain:port separated by spaces)
;data_source_proxy_whitelist =

# disable protection against brute force login attempts
;disable_brute_force_login_protection = false

#################################### Snapshots ###########################
[snapshots]
# snapshot sharing options
;external_enabled = true
;external_snapshot_url = https://snapshots-origin.raintank.io
;external_snapshot_name = Publish to snapshot.raintank.io

# remove expired snapshot
;snapshot_remove_expired = true

#################################### Dashboards History ##################
[dashboards]
# Number dashboard versions to keep (per dashboard). Default: 20, Minimum: 1
;versions_to_keep = 20

#################################### Users ###############################
[users]
# disable user signup / registration
allow_sign_up = false

# 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

# Background text for the user field on the login page
;login_hint = email or username

# Default UI theme ("dark" or "light")
;default_theme = dark

# External user management, these options affect the organization users view
;external_manage_link_url =
;external_manage_link_name =
;external_manage_info =

# Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
;viewers_can_edit = false

[auth]
# Set to true to disable (hide) the login form, useful if you use OAuth, defaults to false
;disable_login_form = false

# Set to true to disable the signout link in the side menu. useful if you use auth.proxy, defaults to false
;disable_signout_menu = false

#################################### Anonymous Auth ##########################
[auth.anonymous]
# enable anonymous access
enabled = true

# 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
;allow_sign_up = true
;client_id = some_id
;client_secret = some_secret
;scopes = user:email,read:org
;auth_url = https://github.com/login/oauth/authorize
;token_url = https://github.com/login/oauth/access_token
;api_url = https://api.github.com/user
;team_ids =
;allowed_organizations =

#################################### Google Auth ##########################
[auth.google]
;enabled = false
;allow_sign_up = true
;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
;api_url = https://www.googleapis.com/oauth2/v1/userinfo
;allowed_domains =

#################################### Generic OAuth ##########################
[auth.generic_oauth]
;enabled = false
;name = OAuth
;allow_sign_up = true
;client_id = some_id
;client_secret = some_secret
;scopes = user:email,read:org
;auth_url = https://foo.bar/login/oauth/authorize
;token_url = https://foo.bar/login/oauth/access_token
;api_url = https://foo.bar/user
;team_ids =
;allowed_organizations =

#################################### Grafana.com Auth ####################
[auth.grafana_com]
;enabled = false
;allow_sign_up = true
;client_id = some_id
;client_secret = some_secret
;scopes = user:email
;allowed_organizations =

#################################### Auth Proxy ##########################
[auth.proxy]
;enabled = false
;header_name = X-WEBAUTH-USER
;header_property = username
;auto_sign_up = true
;ldap_sync_ttl = 60
;whitelist = 192.168.1.1, 192.168.2.1

#################################### Basic Auth ##########################
[auth.basic]
enabled = false

#################################### Auth LDAP ##########################
[auth.ldap]
;enabled = false
;config_file = /etc/grafana/ldap.toml
;allow_sign_up = true

#################################### SMTP / Emailing ##########################
[smtp]
;enabled = false
;host = localhost:25
;user =
# If the password contains # or ; you have to wrap it with trippel quotes. Ex """#password;"""
;password =
;cert_file =
;key_file =
;skip_verify = false
;from_address = admin@grafana.localhost
;from_name = Grafana
# EHLO identity in SMTP dialog (defaults to instance_name)
;ehlo_identity = dashboard.example.com

[emails]
;welcome_email_on_sign_up = false

#################################### Logging ##########################
[log]
# Either "console", "file", "syslog". Default is console and  file
# Use space to separate multiple modes, e.g. "console file"
;mode = console file

# Either "debug", "info", "warn", "error", "critical", default is "info"
;level = info

# optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug
;filters =

# For "console" mode only
[log.console]
;level =

# log line format, valid options are text, console and json
;format = console

# For "file" mode only
[log.file]
;level =

# log line format, valid options are text, console and json
;format = text

# 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_size_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

[log.syslog]
;level =

# log line format, valid options are text, console and json
;format = text

# Syslog network type and address. This can be udp, tcp, or unix. If left blank, the default unix endpoints will be used.
;network =
;address =

# Syslog facility. user, daemon and local0 through local7 are valid.
;facility =

# Syslog tag. By default, the process' argv[0] is used.
;tag =

#################################### Alerting ############################
[alerting]
# Disable alerting engine & UI features
;enabled = true
# Makes it possible to turn off alert rule execution but alerting UI is visible
;execute_alerts = true

#################################### Internal Grafana Metrics ##########################
# Metrics available at HTTP API Url /metrics
[metrics]
# Disable / Enable internal metrics
;enabled           = true

# Publish interval
;interval_seconds  = 10

# Send internal metrics to Graphite
[metrics.graphite]
# Enable by setting the address setting (ex localhost:2003)
;address =
;prefix = prod.grafana.%(instance_name)s.

#################################### Distributed tracing ############
[tracing.jaeger]
# Enable by setting the address sending traces to jaeger (ex localhost:6831)
;address = localhost:6831
# Tag that will always be included in when creating new spans. ex (tag1:value1,tag2:value2)
;always_included_tag = tag1:value1
# Type specifies the type of the sampler: const, probabilistic, rateLimiting, or remote
;sampler_type = const
# jaeger samplerconfig param
# for "const" sampler, 0 or 1 for always false/true respectively
# for "probabilistic" sampler, a probability between 0 and 1
# for "rateLimiting" sampler, the number of spans per second
# for "remote" sampler, param is the same as for "probabilistic"
# and indicates the initial sampling rate before the actual one
# is received from the mothership
;sampler_param = 1

#################################### Grafana.com integration  ##########################
# Url used to to import dashboards directly from Grafana.com
[grafana_com]
;url = https://grafana.com

#################################### External image storage ##########################
[external_image_storage]
# Used for uploading images to public servers so they can be included in slack/email messages.
# you can choose between (s3, webdav, gcs, azure_blob, local)
;provider =

[external_image_storage.s3]
;bucket =
;region =
;path =
;access_key =
;secret_key =

[external_image_storage.webdav]
;url =
;public_url =
;username =
;password =

[external_image_storage.gcs]
;key_file =
;bucket =
;path =

[external_image_storage.azure_blob]
;account_name =
;account_key =
;container_name =

[external_image_storage.local]
# does not require any configuration

openhab-grafana-user-defaults.js:

// the prefix that is used for each Grafana panel URL
OHG_DEFAULTS["urlPrefix"] = "https://192.168.2.55/grafana";

// use "false" so actual pages are loaded (or comment the line)
OHG_DEFAULTS["debug"] = "false";

// use "default" for the default openHAB sitemap (or comment the line)
OHG_DEFAULTS["sitemap"] = "home";

if (OHG_DEFAULTS["debug"] === "true") {
    console.log("Using OHG_DEFAULTS = " + JSON.stringify(OHG_DEFAULTS));
}

openHAB Sitemap URL:

Webview url="https://192.168.2.55/static/demo.html?dashboard=openhab2_roomba&fromItem=ROOMBA_HISTORY_START_TIME&toItem=ROOMBA_HISTORY_STOP_TIME&panel=2&theme=light&w=0301000311&sitemap=home" height=20 icon="none"

wborn commented 5 years ago

I think you can prevent that by adding some extra configuration parameters to your NGINX configuration file (e.g. below the add_header lines):

proxy_set_header Connection keep-alive;
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
keepalive_timeout 3600;
HKN007 commented 5 years ago

meanwhile i came to a similar conclusion. I found in the nginx log the below error entries about the timed out SSE connections. Adding only the line proxy_read_timeout 3600; to the nginx configuration solved the problem.

Anyhow i keep your suggestion, since i'm new to nginx and likely have not seen all issues. Out of curiosity, do you have for each line a explanation why we would need it?

2019/11/08 07:23:03 [error] 598#598: *4 upstream timed out (110: Connection timed out) while reading upstream, client: 192.168.2.109, server: localhost, request: "GET /rest/sitemaps/events/bbff6b50-b65d-4a37-8bad-9e438aa393ea?sitemap=home&pageid=home HTTP/1.1", upstream: "http://127.0.0.1:8080/rest/sitemaps/events/bbff6b50-b65d-4a37-8bad-9e438aa393ea?sitemap=home&pageid=home", host: "192.168.2.55", referrer: "http://1
92.168.2.55/basicui/app"
2019/11/08 07:23:03 [error] 598#598: *1 upstream timed out (110: Connection timed out) while reading upstream, client: 192.168.2.109, server: localhost, request: "GET /rest/sitemaps/events/63c73c97-f0c9-48d1-99ec-d0d833a3ccb2?sitemap=home&pageid=0301000311 HTTP/1.1", upstream: "http://127.0.0.1:8080/rest/sitemaps/events/63c73c97-f0c9-48d1-99ec-d0d833a3ccb2?sitemap=home&pageid=0301000311", host: "192.168.2.55", referrer: "
http://192.168.2.55/static/demo.html?dashboard=openhab2_roomba&fromItem=ROOMBA_HISTORY_START_TIME&toItem=ROOMBA_HISTORY_STOP_TIME&panel=2&theme=light"
wborn commented 5 years ago

It's been a while since I've touched these values. ;-) I think I got these after searching for SSE timeout issues on the web. Using all of them could be overkill.

HKN007 commented 5 years ago

ok - thanks. Closed.