It seems extremely easy to do if you know all required Docker containers, but it's not so obvious if you are not a fluent Docker user.
Here is what it takes to create SSL secured Grafana + InfluxDB Docker setup:
- Grafana (https://hub.docker.com/r/grafana/grafana/)
- InfluxDB (https://hub.docker.com/_/influxdb/)
- Nginx-proxy (https://hub.docker.com/r/jwilder/nginx-proxy/)
- Let's Encrypt Nginx-proxy companion (https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion/)
The additional benefit of this setup is certificate autogeneration and auto-renewal (no more worries/downtime related to expired Let's Encrypt certificate.
- docker (https://www.docker.com/)
- docker-compose (https://docs.docker.com/compose/install/ eases multi-container setup and removal operations)
Create docker-compose.yml file with the content similar to the example below and execute docker-compose up -d command in the directory where your yml file is saved.
Here is the example content of docker-compose.yml with some comments related to the required modifications/adjustments (don't worry about the file length, feel free to skip this section and continue reading starting from Architecture description):
version: '2' services: grafana: image: grafana/grafana:5.0.0 # or probably any other version container_name: grafana restart: always environment: - VIRTUAL_HOST=YOUR.DOMAIN.TEST # adjust to match your domain name - VIRTUAL_PROTO=https - VIRTUAL_PORT=3000 - LETSENCRYPT_HOST=YOUR.DOMAIN.TEST # adjust to match your domain name - LETSENCRYPT_EMAIL=YOUR.EMAIL@ADDRESS.TEST # adjust to match your email - GF_SERVER_CERT_FILE=/etc/letsencrypt/certs/YOUR.DOMAIN.TEST.crt # adjust to match your domain name - GF_SERVER_CERT_KEY=/etc/letsencrypt/certs/YOUR.DOMAIN.TEST.key # adjust to match your domain name - GF_SERVER_PROTOCOL=https - GF_SERVER_DOMAIN=YOUR.DOMAIN.TEST # adjust to match your domain name - GF_SECURITY_ADMIN_USER=SECURE_USERNAME # adjust to create Grafana admin account - GF_SECURITY_ADMIN_PASSWORD=SECURE_PASS # adjust to set Grafana admin password volumes: - ./letsencrypt/certs:/etc/letsencrypt/certs:ro - grafana-data:/var/lib/grafana influx: image: influxdb:1.4.2 # or any other recent version container_name: influx restart: always volumes: - influx-data:/var/lib/influxdb - ./letsencrypt/certs:/etc/letsencrypt/certs:ro ports: - "8086:8086" environment: # might be used someday when issue #59 will be resolved/merged #- VIRTUAL_HOST=YOUR.DOMAIN.TEST:8086 #- VIRTUAL_PROTO=https #- VIRTUAL_PORT=8086 - INFLUXDB_HTTP_HTTPS_ENABLED=true - INFLUXDB_HTTP_HTTPS_CERTIFICATE=/etc/letsencrypt/certs/YOUR.DOMAIN.TEST.crt # adjust to match your domain name - INFLUXDB_HTTP_HTTPS_PRIVATE_KEY=/etc/letsencrypt/certs/YOUR.DOMAIN.TEST.key # adjust to match your domain name - INFLUXDB_DB=SOME_DB_NAME # set any other to create database on initialization - INFLUXDB_HTTP_ENABLED=true - INFLUXDB_HTTP_AUTH_ENABLED=true - INFLUXDB_ADMIN_USER=SECURE_USERNAME # adjust to create InfluxDB admin account - INFLUXDB_ADMIN_PASSWORD=SECURE_PASS # adjust to create InfluxDB admin password # Containers below ensures automatic cert creation and renewal nginx: image: jwilder/nginx-proxy:0.6.0 container_name: nginx restart: always labels: - com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./nginx/html:/usr/share/nginx/html - ./nginx/vhost.d:/etc/nginx/vhost.d - ./letsencrypt/certs:/etc/nginx/certs:ro letsencrypt: image: jrcs/letsencrypt-nginx-proxy-companion:v1.7 container_name: letsencrypt restart: always volumes_from: - nginx volumes: - ./letsencrypt/certs:/etc/nginx/certs:rw - /var/run/docker.sock:/var/run/docker.sock:ro volumes: influx-data: driver: local grafana-data: driver: local
That's all. Just replace:
- YOUR.DOMAIN.TEST - appropriate domain name
- YOUR.EMAIL@ADDRESS.TEST - your email address
- SECURE_USERNAME - some username
- SECURE_PASS - secure password for the user
After executing docker-compose up -d you SSLed Grafana + Influx stack should be available over https://YOUR.DOMAIN.TEST and https://YOUR.DOMAIN.TEST:8086. It may take a couple of minutes on the first run because of Let's Encrypt certificate generation.
As an "extra" benefit the Nginx ensures HSTS headers for SSLed service, which basically means that all requests have to be done using an encrypted connection (the browser will force
https:// at the beginning of the address).
As we know by default Docker creates it's own subnetwork for running containers and communication between them. Here is how it looks in the above example.
NOTE 1: Influx URL. Inside Grafana data sources panel you will have to define your Influx URL using a fully qualified domain name (FQDN e.g. https://YOUR.DOMAIN.TEST:8086) and not internal Docker subnetwork alias e.g. influx. This is due to the fact that SSL certificate will work with Influx only if it is accessed through the URL for which certificate was requested.
NOTE 2: Grafana port. In this setup Grafana still uses its default 3000 port, the redirection from 80 and 443 ports is handled by the Nginx proxy server.
NOTE 3: Influx without proxy. As you may notice InfluxDB connections doesn't go through Nginx. That fact is caused by the Nginx env variables configuration limitation. It doesn't allow to specify port-based routing (only subdomain routing is available). For more details please refer to the Github issue #59
Here is some more information about setup presented above. Some of them may be evident especially for (more or less) experienced Docker users. I think that they are worth at least skimming through.
The container name option, once specified, let's you refer to the deployed container using a custom name instead of SHA code. It is useful especially for checking container status with
docker logs [container_name] or executing custom commands with
docker exec -it [container_name].
Just to ensure continuous work even after Docker/host restart. Be careful with restart: unless-stopped as this option lacks the container autostart feature.
They are used (in this setup) just to mark which container is the Nginx proxy in order to trigger its reloading on certificate update. It's a handy feature implemented by letsencrypt-nginx-proxy-companion.
That's a tricky one. The docker.sock allows the container to work with Docker Engine API. It is used by the jwilder/nginx-proxy to do its VIRTUAL_... env variables magic. The docker API works similar to any JSON based HTTP API, but it is exposed on docker.sock socket.
:ro and :rw suffixes
I think it's an obvious one but to cover "everything" I can say that those are folder/file permissions: "Read Only" and "Read and Write".
There are 3 kinds of "paths" used in this setup:
- absolute paths like /var/run/docker.sock:... which points to the host system internal files
- relative paths e.g. *./letsencrypt/certs:... which are a handy way of storing/sharing container files with the host system
- volumes dirs influx-data:... these are used for ensuring data persistence ensured by the Docker
Don't worry that the cert file paths are invalid on the first run when there are no certificate files. As soon as Let's Encrypt certificate request will be fulfilled you will find appropriate certificates in the specified localizations.
That's all for now. I'd be happy to answer some questions. I hope to be able to explain everything about this or similar setup.