Nginx config for proxy redirect, port forwarding

Hello,
I’m just starting with Grafana.
The 7.0.3 installation, configuration and creation of first panels were
successful :-), working in a local environment without NAT IPs and
nginx configs.

My grafana default configuration changes just are:

instance_name = my_hostname.domain.xx
http_addr = my_hostname.domain.xx
domain = my_hostname.domain.xx
root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana/
serve_from_sub_path = true
host = my_hostname.domain.xx:3306
;Default Port 3000
;Protocol http
;no change in [auth.proxy], etc.

Now in my production environment I have to access the server via a NAT
IP and have to “forward” the default port 3000 via nginx.

I tried several nginx.conf configs, but it does not work.

Content of simple nginx.conf (which I found in forums many times):
server {
listen 443;
server_name xxxx.de;

location /grafana/ {
proxy_pass http://my_hostname.domain.xx:3000/;
}

The web page always returns to the login page with message “Unauthorized” after changing the password at first login.
Any idea or even a solution for me would be great.

Regards,

Roland

You are aware of this document?

From what I see at a quick glance: you have to set your Grafana config to the “external” URL, i.e. the proxied one. Grafana supports only a single “one true URL” …
At least that’s the case up until 6.7.x which is what I am running.

HTH,
Patrick

Hello Patrick,
thanks for your answer!
Yes, I’m aware of this document. My nginx and also apache2 are not working nevertheless. It seems to be a very special NAT / proxy pass / routing problem in my company’s network.
Or: Additionally I found this link https://github.com/grafana/grafana/issues/16319, where on 15th April 2019 a “bug” (!?) with “x-webauth-header” is described.

In any case I do not use “auth.proxy” at the moment and only wants to forward port 3000 (working, because I get the login page) and a correct (proxy) redirect (not working, because I always get the login page :wink: )
Any idea for an apache2 or nginx config would be great.

Regards,
Roland

Then please post our complete Nginx config for that vhost and your Grafana config - unchanged. There should not be ciritical information in there, anyway.

Thanks,
Patrick

[spoiler]

Summary

This text will be hidden

Here we go:

Summary

This text will be hidden

nginx.conf

server {
listen 443;
server_name something.de;

    root /opt/app/nginx/html/;

    ssl on;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_certificate      /etc/nginx/ssl/nginx.pem;
    ssl_certificate_key  /etc/nginx/ssl/nginx.key;

    location / {
        proxy_pass https://10.10.10.10:5707/;
        proxy_redirect      https://10.10.10.10:5707 https://something.de;
        chunked_transfer_encoding off;
        proxy_http_version 1.1;
    }

}
server {
listen 80;
root /usr/share/nginx/html;
index index.html index.htm;

location /grafana/ {
proxy_pass http://10.10.10.10:3000/;
}
}
########################################################################

Grafana Config

cp -p defaults.ini custom.ini
vi custom.ini
… see diff output

diff defaults.ini custom.ini
10c10
< instance_name = ${HOSTNAME}

instance_name = myhostname.domain
35c35
< http_addr =


http_addr = myhostname.domain
41c41
< domain = localhost


domain = myhostname.domain
48c48
< root_url = %(protocol)s://%(domain)s:%(http_port)s/


root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana/
51c51
< serve_from_sub_path = false


serve_from_sub_path = true
76c76
< host = 127.0.0.1:3306


host = myhostname.domain:3306

Grafana Log

INFO[06-23|11:23:47] Successful Login logger=http.server User=admin@localhost
INFO[06-23|11:24:00] Request Completed logger=context userId=0 orgId=0 uname= method=PUT path=/api/user/password status=401 remote_addr=10.10.10.10 time_ms=0 size=26 referer=http://NAT-IP-grafana-server/grafana/login
[/spoiler]This text will be blurred

How can I prevent auto-formatting? :wink:

You really have this in your Grafana config? As I stated in my first answer you must configre Grafana to your official external URL, otherwise it won’t work. You cannot in parallel access Grafana with proxy for some and without proxy for other clients.
Unless you can play split-DNS tricks and have one and the same hostname point to different IP addresses for external and internal users.
To repeat: internal users must go through the proxy, too. Your firewall needs to permit “hairpin” connections for that to work.

Also your proxied URL is really “something.de”? When I asked for the config I meant the literal verbatim complete configuration, otherwise nobody will be able to help.

Hello Patrick,
may be my poor English, the URL something.de and myhostname.domain were a little bit confusing, but it s nothing else like example.com, etc.
Yes, I forgot to change the domain to a “real URL”, sorry for that.
So, this time I just changed the domain in the grafana default config to well known,official, real URL (let’s take again something.de) according to https://grafana.com/tutorials/run-grafana-behind-a-proxy/#1 . I removed the hostname, just took ‘localhost’. My nginx.conf is very similar to https://grafana.com/tutorials/run-grafana-behind-a-proxy/#2 . This time without a sub-path. Please see below.
Additionally it is probably very important to mention, that I have to access the grafana server via a NAT IP.
The grafana server is working fine locally. Port forwarding from 80 to 3000 is ok. Using the grafana server’s NAT-IP, I get status 401.

Regards,

Roland

##################### nginx.conf
server {
listen 80;

root /usr/share/nginx/html;
index index.html index.htm;

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

##################### complete custom.ini, but just the domain is changed.to 7.0.3 default.ini
Why is it not possible to attach a text file??
I would like to stop the formatting, but I can’t. :-/ So replaced leading ‘#’ through ‘;’

;#################### Grafana Configuration Defaults #####################
;
; Do not modify this file in grafana installs
;

; 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 = data

; Temporary files in data directory older than given duration will be removed
temp_data_lifetime = 24h

; Directory where grafana can store logs
logs = data/log

; Directory where grafana will automatically scan and look for plugins
plugins = data/plugins

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

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

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

; The http port to use
http_port = 3000

; The public facing domain name used to access grafana from a browser
domain = something.de

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

; The full public facing url
root_url = %(protocol)s://%(domain)s:%(http_port)s/

; Serve Grafana from subpath specified in root_url setting. By default it is set to false for compatibility reasons.
serve_from_sub_path = false

; 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 = /tmp/grafana.sock

;################################### 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 property.

; 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 =

; 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 =

; For “postgres”, use either “disable”, “require” or “verify-full”
; For “mysql”, use either “true”, “false”, or “skip-verify”.
ssl_mode = disable

ca_cert_path =
client_key_path =
client_cert_path =
server_cert_name =

; For “sqlite3” only, path relative to data_path setting
path = grafana.db

; For “sqlite3” only. cache mode setting used for connecting to the database
cache_mode = private

;################################### Cache server #############################
[remote_cache]
; Either “redis”, “memcached” or “database” default is “database”
type = database

; cache connectionstring options
; database: will use Grafana primary database.
; redis: config like redis server e.g. addr=127.0.0.1:6379,pool_size=100,db=0,ssl=false. Only addr is required. ssl may be ‘true’, ‘false’, or ‘insecure’.
; memcache: 127.0.0.1:11211
connstr =

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

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

; How long the data proxy should wait before timing out default is 30 (seconds)
timeout = 30

; If enabled and user is not anonymous, data proxy will add X-Grafana-User header with username into the request, default is false.
send_user_header = 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.com
; for new versions (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 https://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 =

; Google Tag Manager ID, only enabled if you specify an id here
google_tag_manager_id =

;################################### Security ############################
[security]
; disable creation of admin user on first start of grafana
disable_initial_admin_creation = false

; 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

; 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

; set to true if you host Grafana behind HTTPS. default is false.
cookie_secure = false

; set cookie SameSite attribute. defaults to lax. can be set to “lax”, “strict”, “none” and “disabled”
cookie_samesite = lax

; set to true if you want to allow browsers to render Grafana in a ,

; Set to true if you want to enable http strict transport security (HSTS) response header.
; This is only sent when HTTPS is enabled in this configuration.
; HSTS tells browsers that the site should only be accessed using HTTPS.
; The default will change to true in the next minor release, 6.3.
strict_transport_security = false

; Sets how long a browser should cache HSTS. Only applied if strict_transport_security is enabled.
strict_transport_security_max_age_seconds = 86400

; Set to true if to enable HSTS preloading option. Only applied if strict_transport_security is enabled.
strict_transport_security_preload = false

; Set to true if to enable the HSTS includeSubDomains option. Only applied if strict_transport_security is enabled.
strict_transport_security_subdomains = false

; Set to true to enable the X-Content-Type-Options response header.
; The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised
; in the Content-Type headers should not be changed and be followed. The default will change to true in the next minor release, 6.3.
x_content_type_options = false

; Set to true to enable the X-XSS-Protection header, which tells browsers to stop pages from loading
; when they detect reflected cross-site scripting (XSS) attacks. The default will change to true in the next minor release, 6.3.
x_xss_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

; Set to true to enable this Grafana instance act as an external snapshot server and allow unauthenticated requests for
; creating and deleting snapshots.
public_mode = false

; remove expired snapshot
snapshot_remove_expired = true

;################################### Dashboards ##################

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

; Minimum dashboard refresh interval. When set, this will restrict users to set the refresh interval of a dashboard lower than given interval. Per default this is 5 seconds.
; The interval string is a possibly signed sequence of decimal numbers, followed by a unit suffix (ms, s, m, h, d), e.g. 30s or 1m.
min_refresh_interval = 5s

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

; Allow non admin users to create organizations
allow_org_create = false

; Set to true to automatically assign new users to the default organization (id 1)
auto_assign_org = true

; Set this value to automatically add new users to the provided organization (if auto_assign_org above is set to true)
auto_assign_org_id = 1

; Default role new users will be automatically assigned (if auto_assign_org above is set to true)
auto_assign_org_role = Viewer

; Require email validation before sign up completes
verify_email_enabled = false

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

; Default UI theme (“dark” or “light”)
default_theme = dark

; External user management
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

; Editors can administrate dashboard, folders and teams they create
editors_can_admin = false

[auth]
; Login cookie name
login_cookie_name = grafana_session

; The lifetime (days) an authenticated user can be inactive before being required to login at next visit. Default is 7 days.
login_maximum_inactive_lifetime_days = 7

; The maximum lifetime (days) an authenticated user can be logged in since login time before being required to login. Default is 30 days.
login_maximum_lifetime_days = 30

; How often should auth tokens be rotated for authenticated users when being active. The default is each 10 minutes.
token_rotation_interval_minutes = 10

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

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

; URL to redirect the user to after sign out
signout_redirect_url =

; Set to true to attempt login with OAuth automatically, skipping the login screen.
; This setting is ignored if multiple OAuth providers are configured.
oauth_auto_login = false

; OAuth state max age cookie duration. Defaults to 60 seconds.
oauth_state_cookie_max_age = 60

; limit of api_key seconds to live before expiration
api_key_max_seconds_to_live = -1

;################################### 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
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
allowed_domains =
team_ids =
allowed_organizations =

;################################### GitLab Auth #########################
[auth.gitlab]
enabled = false
allow_sign_up = true
client_id = some_id
client_secret = some_secret
scopes = api
auth_url = https://gitlab.com/oauth/authorize
token_url = https://gitlab.com/oauth/token
api_url = https://gitlab.com/api/v4
allowed_domains =
allowed_groups =

;################################### 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 =
hosted_domain =

;################################### Grafana.com Auth ####################
; legacy key names (so they work in env variables)
[auth.grafananet]
enabled = false
allow_sign_up = true
client_id = some_id
client_secret = some_secret
scopes = user:email
allowed_organizations =

[auth.grafana_com]
enabled = false
allow_sign_up = true
client_id = some_id
client_secret = some_secret
scopes = user:email
allowed_organizations =

;################################### Azure AD OAuth #######################
[auth.azuread]
name = Azure AD
enabled = false
allow_sign_up = true
client_id = some_client_id
client_secret = some_client_secret
scopes = openid email profile
auth_url = https://login.microsoftonline.com//oauth2/v2.0/authorize
token_url = https://login.microsoftonline.com//oauth2/v2.0/token
allowed_domains =
allowed_groups =

;################################### Okta OAuth #######################
[auth.okta]
name = Okta
enabled = false
allow_sign_up = true
client_id = some_id
client_secret = some_secret
scopes = openid profile email groups
auth_url = https://.okta.com/oauth2/v1/authorize
token_url = https://.okta.com/oauth2/v1/token
api_url = https://.okta.com/oauth2/v1/userinfo
allowed_domains =
allowed_groups =
role_attribute_path =

;################################### Generic OAuth #######################
[auth.generic_oauth]
name = OAuth
enabled = false
allow_sign_up = true
client_id = some_id
client_secret = some_secret
scopes = user:email
email_attribute_name = email:primary
email_attribute_path =
role_attribute_path =
auth_url =
token_url =
api_url =
allowed_domains =
team_ids =
allowed_organizations =
tls_skip_verify_insecure = false
tls_client_cert =
tls_client_key =
tls_client_ca =

;################################### Basic Auth ##########################
[auth.basic]
enabled = true

;################################### Auth Proxy ##########################
[auth.proxy]
enabled = false
header_name = X-WEBAUTH-USER
header_property = username
auto_sign_up = true
; Deprecated, use sync_ttl instead
ldap_sync_ttl = 60
sync_ttl = 60
whitelist =
headers =
enable_login_token = false

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

; LDAP backround sync (Enterprise only)
; At 1 am every day
sync_cron = “0 0 1 * * *”
active_sync_enabled = true

;################################### SMTP / Emailing #####################
[smtp]
enabled = false
host = localhost:25
user =
; If the password contains # or ; you have to wrap it with triple quotes. Ex “”"#password;"""
password =
cert_file =
key_file =
skip_verify = false
from_address = admin@grafana.localhost
from_name = Grafana
ehlo_identity =

[emails]
welcome_email_on_sign_up = false
templates_pattern = emails/*.html

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

;################################### Usage Quotas ########################
[quota]
enabled = false

;### set quotas to -1 to make unlimited. ####
; limit number of users per Org.
org_user = 10

; limit number of dashboards per Org.
org_dashboard = 100

; limit number of data_sources per Org.
org_data_source = 10

; limit number of api_keys per Org.
org_api_key = 10

; limit number of orgs a user can create.
user_org = 10

; Global limit of users.
global_user = -1

; global limit of orgs.
global_org = -1

; global limit of dashboards
global_dashboard = -1

; global limit of api_keys
global_api_key = -1

; global limit on number of logged in users.
global_session = -1

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

; Default setting for new alert rules. Defaults to categorize error and timeouts as alerting. (alerting, keep_state)
error_or_timeout = alerting

; Default setting for how Grafana handles nodata or null values in alerting. (alerting, no_data, keep_state, ok)
nodata_or_nullvalues = no_data

; Alert notifications can include images, but rendering many images at the same time can overload the server
; This limit will protect the server from render overloading and make sure notifications are sent out quickly
concurrent_render_limit = 5

; Default setting for alert calculation timeout. Default value is 30
evaluation_timeout_seconds = 30

; Default setting for alert notification timeout. Default value is 30
notification_timeout_seconds = 30

; Default setting for max attempts to sending alert notifications. Default value is 3
max_attempts = 3

; Makes it possible to enforce a minimal interval between evaluations, to reduce load on the backend
min_interval_seconds = 1

;################################### Explore #############################
[explore]
; Enable the Explore section
enabled = true

;################################### Internal Grafana Metrics ############
; Metrics available at HTTP API Url /metrics
[metrics]
enabled = true
interval_seconds = 10
; Disable total stats (stat_totals_*) metrics to be generated
disable_total_stats = false

;If both are set, basic auth will be required for the metrics endpoint.
basic_auth_username =
basic_auth_password =

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

;################################### Grafana.com integration ##########################
[grafana_net]
url = https://grafana.com

[grafana_com]
url = https://grafana.com

;################################### Distributed tracing ############
[tracing.jaeger]
; jaeger destination (ex localhost:6831)
address =
; tag that will always be included in when creating new spans. ex (tag1:value1,tag2:value2)
always_included_tag =
; 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
; Whether or not to use Zipkin span propagation (x-b3- HTTP headers).
zipkin_propagation = false
; Setting this to true disables shared RPC spans.
; Not disabling is the most common setting when using Zipkin elsewhere in your infrastructure.
disable_shared_zipkin_spans = false

;################################### 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]
endpoint =
path_style_access =
bucket_url =
bucket =
region =
path =
access_key =
secret_key =

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

[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

[rendering]
; Options to configure a remote HTTP image rendering service, e.g. using https://github.com/grafana/grafana-image-renderer.
; URL to a remote HTTP image renderer service, e.g. http://localhost:8081/render, will enable Grafana to render panels and dashboards to PNG-images using HTTP requests to an external service.
server_url =
; If the remote HTTP image renderer service runs on a different server than the Grafana server you may have to configure this to a URL where Grafana is reachable, e.g. http://grafana.domain/.
callback_url =
; Concurrent render request limit affects when the /render HTTP endpoint is used. Rendering many images at the same time can overload the server,
; which this setting can help protect against by only allowing a certain amount of concurrent requests.
concurrent_render_request_limit = 30

[panels]
; here for to support old env variables, can remove after a few months
enable_alpha = false
disable_sanitize_html = false

[plugins]
enable_alpha = false
app_tls_skip_verify_insecure = false
; Enter a comma-separated list of plugin identifiers to identify plugins that are allowed to be loaded even if they lack a valid signature.
allow_loading_unsigned_plugins =

;################################### Grafana Image Renderer Plugin ##########################
[plugin.grafana-image-renderer]
; Instruct headless browser instance to use a default timezone when not provided by Grafana, e.g. when rendering panel image of alert.
; See ICU’s metaZones.txt (https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt) for a list of supported
; timezone IDs. Fallbacks to TZ environment variable if not set.
rendering_timezone =

; Instruct headless browser instance to use a default language when not provided by Grafana, e.g. when rendering panel image of alert.
; Please refer to the HTTP header Accept-Language to understand how to format this value, e.g. ‘fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5’.
rendering_language =

; Instruct headless browser instance to use a default device scale factor when not provided by Grafana, e.g. when rendering panel image of alert.
; Default is 1. Using a higher value will produce more detailed images (higher DPI), but will require more disk space to store an image.
rendering_viewport_device_scale_factor =

; Instruct headless browser instance whether to ignore HTTPS errors during navigation. Per default HTTPS errors are not ignored. Due to
; the security risk it’s not recommended to ignore HTTPS errors.
rendering_ignore_https_errors =

; Instruct headless browser instance whether to capture and log verbose information when rendering an image. Default is false and will
; only capture and log error messages. When enabled, debug messages are captured and logged as well.
; For the verbose information to be included in the Grafana server log you have to adjust the rendering log level to debug, configure
; [log].filter = rendering:debug.
rendering_verbose_logging =

; Instruct headless browser instance whether to output its debug and error messages into running process of remote rendering service.
; Default is false. This can be useful to enable (true) when troubleshooting.
rendering_dumpio =

; Additional arguments to pass to the headless browser instance. Default is --no-sandbox. The list of Chromium flags can be found
; here (https://peter.sh/experiments/chromium-command-line-switches/). Multiple arguments is separated with comma-character.
rendering_args =

; You can configure the plugin to use a different browser binary instead of the pre-packaged version of Chromium.
; Please note that this is not recommended, since you may encounter problems if the installed version of Chrome/Chromium is not
; compatible with the plugin.
rendering_chrome_bin =

; Instruct how headless browser instances are created. Default is ‘default’ and will create a new browser instance on each request.
; Mode ‘clustered’ will make sure that only a maximum of browsers/incognito pages can execute concurrently.
; Mode ‘reusable’ will have one browser instance and will create a new incognito page on each request.
rendering_mode =

; When rendering_mode = clustered you can instruct how many browsers or incognito pages can execute concurrently. Default is ‘browser’
; and will cluster using browser instances.
; Mode ‘context’ will cluster using incognito pages.
rendering_clustering_mode =
; When rendering_mode = clustered you can define maximum number of browser instances/incognito pages that can execute concurrently…
rendering_clustering_max_concurrency =

; Limit the maxiumum viewport width, height and device scale factor that can be requested.
rendering_viewport_max_width =
rendering_viewport_max_height =
rendering_viewport_max_device_scale_factor =

; Change the listening host and port of the gRPC server. Default host is 127.0.0.1 and default port is 0 and will automatically assign
; a port not in use.
grpc_host =
grpc_port =

[enterprise]
license_path =

[feature_toggles]
; enable features, separated by spaces
enable =

So to summarize:

  1. You are forwarding external port 80 to port 80 on the machine with the Nginx?
  2. I can see from the Nginx config snippet that Nginx is forwarding to Grafana on port 3000.
  3. The DNS name for your external address is something.de?
  4. You are trying to access Grafana as http://something.de/ which leads to your Nginx (check the logs!) and your Grafana is configured with the identical domain name?

In that case it should work.

Yes, it should work, but it does not. :wink:
Summarization:

  • grafana server is working fine, using the same LAN with local IPs. Nginx forwarding with port 80 is also ok here. Grafana logs and nginx logs show no errors.
  • Using the NAT-IP and Port 80 for access: Login page appears. First login is ok. Site for entering a new password also appears. Afterwards you get the message “Unauthorized” and Grafana returns to the login page.

Ideas:
An “official DNS URL” for the NAT-IP might be necessary. The official URL (something.de) for the local host’s IP might not be sufficient.

Several server names in nginx.conf are possible.
Are several domain names in grafana.ini possible?

That’s what I was talking about all the time.
You absolutely must have a DNS entry for your external NAT IP. And you must configure Grafana for that URL. Grafana can only have one official URL and all access must go through that.

I wrote that multiple times.

ok, I understood. May be, I did not understand it yet, because I could not believe it. :wink:
That’s the first time in my long experience, that a server is only accessible via one official URL and not via IP or a NAT IP. Grafana experts may think about it :wink:
My alternative Visualization GUI “kibana” can handle everything. So I have to take Kibana at the moment, even if Grafana seems to have much better possibilities and layouts.
Try to access 35.241.23.245 in your browser. Event that is working. :wink:

Thanks for your patience with me. Let’s close this thread.

Regards,
Roland

You could as a last test try to use the official IP as the domain name in the Grafana config. I don’t know if that is supposed to work.

How are you ever going to enable SSL on that connection without a DNS entry?

Kind regards,
Patrick

Sorry, for not answering a long time.
I was busy elsewhere. I will have to order the DNS entry for the next try with http or https. But the entry will take “some time”. :-/
I will keep you up-to-date …

1 Like

You are aware that a static hosts entry on your desktop machine will do the trick for setup and testing?

Yes, of course.
But I have no client administrator rights. So I have to open a service desk ticket with “some” processing time. :-/