Home Assistant: Installing Grafana (LXC) with Let’s Encrypt SSL

If you want visually appealing dashboards for your long term Home Assistant data stored in InfluxDB, look no further than Grafana. Grafana allows you to query, visualize, alert on and understand metrics captured by Home Assistant (and MANY other platforms). You can create some really stunning dashboards.

Sample Grafana Dashboard (Courtesy Grafana)

As covered in previous posts, I’m running Home Assistant OS (HAOS) on Proxmox (see Home Assistant: Proxmox Quick Start Guide). I’m also running InfluxDB in a LXC container (see Home Assistant: Installing InfluxDB (LXC)). This post will cover installing Grafana in a LXC container on Proxmox and optionally using certbot and LetsEncrypt for a trusted SSL certificate. You can install Grafana in Home Assistant directly via an add-on. However, I prefer a standalone Grafana LXC for a couple of reasons:

  • The HA Grafana add-on has hard coded default username and password. You can’t change the password on the default account, but you could delete the account and create a new one with a custom password. Not too user friendly and not a great security practice. 
  • The Grafana HA add-on is primarily designed for viewing within HA via direct access, but does support ingress access. However, there are sporadic forum posts that ingress has been spotty/buggy. I don’t want to deal with that.

What's in this Tutorial

In this tutorial I cover the following procedures:
 
  • Installing Grafana in a LXC container on Proxmox via the tteck script
  • Adding InfluxDB as a data source in Grafana
  • (Optional) Configure Grafana with a Letsencrypt SSL certificate
  • (Optional) Adding Grafana as an iFrame to Home Assistant with custom icons

Grafana LXC Installation

  1. Login to Proxmox and select your Proxmox server in the left pane.
  2. Click on Shell in the middle pane.
  3. Enter the following command to start the InfluxDB LXC install. Press Enter on Yes.
				
					bash -c "$(wget -qLO - https://github.com/tteck/Proxmox/raw/main/ct/grafana.sh)"


				
			

4. Select Advanced.

5. Leave Container Type Unprivileged.
6. Enter a complex password.
7. Accept the container ID.
8. Set the Hostname.
9. Leave the Disk Size.
10. Leave the Core Count.
11. Reduce RAM to 256MB.
12. Leave the Bridge.
13. Optionally set a static IP (e.g. 192.168.10.45/24).
14. Set a Gateway IP.
15. Don’t disable IPv6 (unless you need to).
16. Leave MTU Size.
17. Set DNS Search Domain (if needed).
18. Set a DNS server IP.
19. Leave the MAC address blank.
20. Leave the VLAN.
21. Enable Root SSH access.

 

22. Don’t enable verbose mode.
23. Press enter on Yes, Create Grafana LXC.
24. Select your storage by using the arrow keys, then press space to select, and tab to OK.
25. Again, select the storage you want to use.
26. Wait a minute or two for the install to complete. Take note of the IP and port (3000).
27. Open a web browser and go to http://IP:3000. You should get the Grafana welcome screen.

Grafana InfluxDB Configuration

  1. Login using admin / admin.
  2. Enter a new password when prompted.
  3. Click on the cog in the lower left pane and click Data Sources.

4. Click on Add data source.
5. Search for InfluxDB and click on it.
6. Fill out the following information:

  • Name (e.g. InfluxDB or HomeAssistant)
  • Leave InfluxQL
  • Enter the URL of your InfluxDB (e.g. http://IP:8086)
  • Enter your InfluxDB Home Assistant database name
  • Enter your InfluxDB username
  • Click Reset on password and enter your InfluxDB password
  • Click on Save & test. Verify data is found.

Adding Grafana iFrame to HA (Optional)

If you want to directly access the Grafana web UI from within Home Assistant (like you can with the HA Grafana add-on) it can be pretty easy…Just add the lines below in your configuration.yaml file. I’ve included using a custom icon (details below).

Note: If you are accessing Home Assistant UI over HTTPS then your Grafana URL must be HTTPS as well due to browser iFrame security requirements. The Grafana certificate will need to be fully trusted (e.g. use certbot with Letsencrypt) and can NOT be self-signed (again, browser security). This means you need to use a publicly registered domain name and FQDN to access Home Assistant and Grafana. 

				
					
panel_iframe:
  grafana:
    title: Grafana
    url: "https://grafana.mydomain.com:3000/"
    icon: "phu:grafana"
    require_admin: true

				
			

If you want the Grafana icon in the frontend sidebar you can install the custom brand icons via HACS and add the following line to your configuration.yaml file. Make sure you restart Home Assistant after you load the icon pack and change the configuration.yaml file.

				
					
# Load frontend themes from the themes folder
frontend: 
  extra_module_url:
    - /local/community/custom-brand-icons/custom-brand-icons.js

				
			

DNS Redirect for SSL

If you are configuring the Grafana server for a trusted SSL certificate you will want to access your Grafana server via FQDN from inside your home network. This will prevent any browser warnings. It also keeps all traffic (including DNS queries) within your home network. To do this you need to configure a DNS redirect rule on your router, firewall, Pi-hole, AdGuard server or with NextDNS. 

What is a DNS redirect rule? Basically when your home computer does a DNS query for grafana.mydomain.com we want the private internal IP address of your Grafana server returned, not a public IP address of your ISP’s modem. This means your router/firewall will intercept that request to the public DNS server and respond with the private (internal) IP of your Grafana server. See the diagram below for the traffic flow.

Before proceeding create a DNS direct rule that points the FQDN of your Grafana server to the private (internal) IP address of your Grafana server. You should not create a record in your public DNS Cloudflare zone that has the private IP of your Grafana server. Do the redirect on an internal device.

Grafana SSL Certificate (Optional)

This procedure is written using the python certbot with cloudflare DNS package. I was unable to use procedures based on snap certbot inside the LXC container. I managed to get the base snapd installed, however the last step of pulling down the certbot package failed. LXC containers have unique security restrictions that cause snapd issues. 

If you aren’t using Cloudflare DNS, then you will need to use a different certbot package and use the appropriate parameters for your DNS provider. Certbot automatically installs a cron job that will handle automatic renewal of your certificate. So you don’t need to do anything for renewals, as they are automatic.

  1. Open a SSH session to your Grafana LXC.
  2. Type the following commands: 
				
					apt-get install python3-certbot-dns-cloudflare
mkdir /root/.secrets/
nano /root/.secrets/cloudflare.ini
				
			

3. Add the following line and use your Cloudflare DNS ZONE API key (NOT global API key), then save and exit nano. See my post Getting your Cloudflare Zone API Key and Account ID for more details.

				
					dns_cloudflare_api_token = yourapikey
				
			

4. Run the following commands to set restrictive permissions on the directory and file.

				
					chmod 0700 /root/.secrets/
chmod 0400 /root/.secrets/cloudflare.ini
				
			

5. Run the following command but change the domain (use both the ‘flat’ domain mydomain.com and the wildcard *.mydomain.com). Change the email address to a real address that Letsencrypt can send notifications to. If you get a txt record mismatch error it might be due to slow DNS propagation. You can increase the wait from 30 seconds to whatever value you want.

Warning: If you get a failure, be careful how many times you re-attempt. Letsencrypt has a threshold of attempts for production that you can’t exceed or it will deny issuing a certificate. If you get a failure, try the –staging option (which isn’t rate limited) until you get a success. Then remove the –staging option to obtain a real certificate.

				
					
certbot certonly -d mydomain.com,*.mydomain.com \
    --dns-cloudflare --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
    --dns-cloudflare-propagation-seconds 30 \
    --post-hook "systemctl restart grafana-server" \
    --preferred-challenges dns-01 \
    --non-interactive --agree-tos \
    --email <span 
                data-original-string="M771w76qPDJf44JBhoUuOGUj/jRNihfzSxD5m5MAvjo="
                class="apbct-email-encoder"
                title="This contact has been encoded by Anti-Spam by CleanTalk. Click to decode. To finish the decoding make sure that JavaScript is enabled in your browser.">le*********@my******.com</span>
				
			

6. Now we need to set symlinks to where Grafana expects the certificates.

				
					ln -s /etc/letsencrypt/live/mydomain.com/privkey.pem /etc/grafana/grafana.key
ln -s /etc/letsencrypt/live/mydomain.com/fullchain.pem /etc/grafana/grafana.crt
				
			

7. Now let’s set the permissions.

Note: You may run into a situation were the mydomain.com letsencrypt directory has numbers after it (e.g. /etc/letsencrypt/live/mydomain.com-0001), due to failed attempts or dry runs. This will cause the permissions commands, below, to fail due to dangling symlinks. If that happens, the best solution is to delete the Grafana LXC container and rebuild it. Certbot is pretty complicated under the hood and it’s quicker to start over than fix certbot.

				
					
chgrp -R grafana /etc/letsencrypt/*
chmod -R g+rx /etc/letsencrypt/*
chgrp -R grafana /etc/grafana/grafana.crt /etc/grafana/grafana.key
chmod 440 /etc/grafana/grafana.crt /etc/grafana/grafana.key
				
			

8. Open the grafana.ini file with nano so we can modify a few parameters.

				
					nano /etc/grafana.ini
				
			

9. Modify the grafana.ini file by locating the ## Server## section and make the following changes to existing lines. Remember to remove the semi-colon at the start of each line.

				
					protocol = https
http_port = 3000
enforce_domain = false
domain = grafana.mydomain.com
root_url (Only uncomment this line; leave as-is)
cert_file = /etc/grafana/grafana.crt
cert_key = /etc/grafana/grafana.key



				
			

10. While still in the grafana.ini file search (^W) for embedding and uncomment the line then change the flag to true.

10. Save and exit Nano. Verify Grafana can see the certificates:

				
					ls -l /etc/grafana/grafana.*
				
			

11. Restart the grafana service. Then browse to https://fqdn.com:3000 and verify you see the Grafana login screen and that you have no SSL errors. Now you can restart Home Assistant and verify that the iFrame works.

				
					systemctl restart grafana-server
				
			
Grafana iFrame in Home Assistant (HTTPS)

Summary

Installing Grafana in a LXC container on Proxmox is super easy. If you want to configure Grafana to use HTTPS with a Letsencrypt certificate, then yes, it’s a bit more complicated. But, if you go the distance with the SSL certificate you can then add Grafana as an iFrame inside Home Assistant for seamless access. Otherwise you will just need to access Grafana in a regular browser window, in which case HTTPS is not required.

Print Friendly, PDF & Email

Related Posts

Subscribe
Notify of
3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Alex
August 7, 2023 10:58 am

Hi,

I’m having some difficulties adding an Grafana iframe to HA. Does this config work with Cloudflare tunnels? I have a tunnel configured to https://grafana.mydomain.com that is working but if I use that URL on panel_iframe I get an error “grafana.mydomain.com refused to connect”.

What am I missing?

Been following some of your guides and they are amazing, thanks for your work!

— edit
It’s working now, didn’t noticed the semi-colons on the grafana.ini file 🙂

Last edited 8 months ago by Alex
Azeem
December 17, 2023 3:42 pm

I have been following your guide/instruction and they have been great. I installed it and it was working, Now I tried created SSL, all steps were successful, however I am unable to access grafana via new grafana.mydomainxy.com:3000 or even via direct IP address.

Amy thought, I have double checked all stuff, though I reach out before I reinstall it.

Jostein Hove-Henriksen
February 20, 2024 8:05 am

Had problems with iframe.
Solution:

cookie_samesite = disabled

in grafana.ini