Table of Contents
Here I will show how I setup Grafana for visualization, with Promtail for log shipping, Loki for log aggregation, and InfluxDB for metrics. I use this to monitor my Proxmox cluster, pfSense router, and even my desktop pc. This blog will go over how I set it up to monitor my Proxmox cluster.
Screenshots
-
Grafana LXC Configuration
Installing Ubuntu Container
01. This container will be used to host Grafana, Promtail, and Loki.
02. I used the Ubuntu 22.04 template.
03. I increased the size to 40GB just because I have enough storage.
04. I left it at 1 core, which is more than enough. It currently idles at .27% CPU usage.
05. I increased the RAM to 1GB, which has been enough since it idles around 55% usage.
06. I gave it IP's within my subnet.
07. Left DNS settings at default.
08. Clicked 'Finish'.
Server Configurations
14. After going to the console and logging in as root, I ran the following command to update packages.
sudo apt-get update && sudo apt upgrade -y
 apt-get update
 – updates the package lists for upgrades and new package installations. apt upgrade
 – will upgrade all currently installed packages. -y
 – will automatically answer ‘yes’ to any prompts. 15. Rebooted the server to finish the updates.
shutdown -r now
16. Next I added a user, because it's good practice to not use 'root'.
sudo adduser nesto
17. Then I added the user to the sudo group, that way they have sudo permissions to run commands.
sudo usermod -aG sudo nesto
18. Then I installed OpenSSH so I can remote in using MobaXterm (you can use Putty if you'd like)/
sudo apt install openssh-server
19. The SSH service will usually start after installing it, but I like to make sure by running the following command.
sudo systemctl start ssh
20. I won't go over how to do this, but I used MobaXterm to SSH into this Ubuntu server. Mainly because it's easier to copy and paste commands into the CLI.
Installing Docker
21. Running the following command will download the official GPG key for the Docker repository.
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
-fsSL
 – Is a combination of flags: -f
 – tell ‘curl’ to not output anything if the HTTP status code indicates an error.. -s
 – tells ‘curl’ to hide the progress meter and error messages. -S
 – tells ‘curl’ to show error messages if it fails. -L
 – tells ‘curl’ to handle redirects.
22. Then I added the Docker repository with this command.
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
 deb
 – indicates that the repository is for binary packages. [arch=amd64]
 – means the repository is for 64-bit software. $(lsb_release -cs)
 – returns the codename for the Ubuntu server we installed and currently running commands on
stable tells the repository to use the latest stable version for Docker.
23. Updated packages again.
sudo apt-get update
24. Now I can install Docker Community Edition with the following command.
sudo apt-get install docker-ce -y
25. To test if Docker is installed correctly, I ran the following which will pull an image from the internet and output data to tell you if Docker is working.
sudo docker run hello-world
26. (Optional) Docker should start on it's own after installing, but you can double check by running the following command to start the service.
sudo systemctl start docker
27. Important: I wanted Docker to run upon startup, that way if there is a power outage, I won't have to manually start it.
sudo systemctl enable docker
28. I then added the user I created to the 'Docker' group, so that I have permission to run docker commands.
sudo usermod -aG docker ${USER}
Installing Docker-Compose
29. Now I downloaded Docker-Compose, and placed it in the '/usr/local/bin' directory.
sudo curl -L "https://github.com/docker/compose/releases/download/v2.7.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
-L
 – Tells ‘curl’ to follow any redirects. $(uname -s) and $(uname -m)
 – are used to automatically fill in the system’s kernel name and machine hardware name (e.g. ‘Linux’ and ‘x86_64).
30. Then I made the Docker-Compose binary executable.
sudo chmod +x /usr/local/bin/docker-compose
31. You can check if the installation was successful by running the following command.
docker-compose --version
-
Grafana, Loki, Promtail Installation
Configuring YAML Files
32. I then created a directory for Grafana.
mkdir grafana
33. I then created a directory for Loki.
mkdir loki
34. Then a directory for Promtail
mkdir promtail
35. Then I created the yaml file.
nano docker-compose.yml
36. This will run all 3 docker containers.
version: "3"
services:
loki:
image: grafana/loki:2.9.4
volumes:
- /home/nesto/loki:/etc/loki
ports:
- "3100:3100"
restart: unless-stopped
command: -config.file=/etc/loki/loki-config.yml
promtail:
image: grafana/promtail:2.9.4
volumes:
- /var/log:/var/log
- /home/nesto/promtail:/etc/promtail
restart: unless-stopped
command: -config.file=/etc/promtail/promtail-config.yml
grafana:
image: grafana/grafana:latest
user: "1000"
volumes:
- /home/nesto/grafana:/var/lib/grafana
ports:
- "3000:3000"
restart: unless-stopped
 ports: 3100:3100
 – Maps port 3100 on the host to port 3100 on the container, you can change this if you’re already using port 3100 elsewhere.
I also changed the image from loki:latest, and promtail:latest because the containers kept getting stuck in a restart loop. After quite of bit of troubleshooting I found specifying the 2.9.4 version fixed it.
37. Then I created another yaml file within the Loki directory I created earlier.
nano loki/loki-config.yml
38. I left everything at default.
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
common:
path_prefix: /tmp/loki
storage:
filesystem:
chunks_directory: /tmp/loki/chunks
rules_directory: /tmp/loki/rules
replication_factor: 1
ring:
instance_addr: 127.0.0.1
kvstore:
store: inmemory
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h
ruler:
alertmanager_url: http://localhost:9093
39. Next I created the Promtail yaml file.
nano promtail/promtail-config.yml
40. I kept all the default settings as well.
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
# local machine logs
- job_name: local
static_configs:
- targets:
- localhost
labels:
job: varlogs
__path__: /var/log/*log
41. Then I started all of them up with the following command. You want to make sure nothing is stuck in a restart loop.
docker-compose up -d
42. It'll take some time to install. You can always check if everything is running correctly by running the following command.
sudo docker ps
Accessing Grafana
43. First I waited for Promtail to be ready. To check if Promtail is ready, you'll access your server's IP with the port 3100/ready (example: 10.33.99.71:3100/ready). If it doesn't return with the word 'ready' then keep refreshing every few seconds until it does.
44. Then I access Grafana by adding port 3000/login (example: 10.33.99.71:3000/login). The default login is admin:admin.
45. You can change the password on the following screen. Afterwards, I started on setting up Prometheus.
-
InfluxDB LXC Configuration
Server Configuration
46. I setup another container for InfluxDB. I followed the same steps as I showed earlier, with minor changes (IP address).
Also, install Docker and Docker-Compose.
Configuring YAML File
47. Just like before, I created a directory for InfluxDB.
mkdir influxdb
48. Then created the yaml file.
nano /influxdb/docker-compose.yml
49. I left all the default settings.
version: "3"
services:
influxdb:
image: influxdb:latest
container_name: influxdb
networks:
- default
security_opt:
- no-new-privileges:true
restart: unless-stopped
ports:
- "8086:8086"
volumes:
- $DOCKERDIR/appdata/influxdb2/config:/etc/influxdb2
- $DOCKERDIR/appdata/influxdb2/db:/var/lib/influxdb2
50. Then started it up.
sudo docker-compose up -d
Initial Setup
51. To setup InfluxDB, you go to the server's IP plus the port you set (example: 10.33.99.73:8086).
52. I filled out the boxes, which can be changed or new ones added later.
53. I saved this API key in my VaultWarden, just incase I need it for something later.
54. I clicked on 'Configure Later'.
55. I then went to the side menu and clicked on Load Data > Buckets.
56. I then created a bucket named 'Proxmox' for easy identification, and changed the data retention to only 30 days.
57. Next, I had to create an API token.
58. I then created a custom API token, named it 'Proxmox API' for identification, and only gave it Write permissions to the Proxmox bucket.
59. I saved the API key in Vaultwarden.
-
Connecting InfluxDB
Grafana
60. I went back to Grafana, on the left-side menu I went to Connections > Data Sources.
61. Then selected InfluxDB.
62. I changed the Query language to Flux, then added the IP address and port for my InfluxDB server.
63. You have to enter the API Key from the initial setup.
64. Then click on 'Save & Test', and if everything is correct it'll return a green banner.
Proxmox
65. I then logged back into my Proxmox, clicked on Datacenter > Metric Server.
66. Clicked 'Add > InfluxDB'.
67. Server: IP address of the InfluxDB Server.
Port: I left my port at the default 8086.
Protocol: Change to HTTP.
Organization: from InfluxDB
Bucket: Proxmox bucket I setup
Token: Here is where I put the API token I created for Proxmox.
-
Grafana Dashboard
Finish Setup
68. Finally, I went back to Grafana, and clicked 'Dashboards'.
69. I could create my own, but it was quicker importing a template from the Grafana template library (https://grafana.com/grafana/dashboards).
70. The one I chose can be found here (Link). Copy the ID to clipboard.
71. Then paste it and click on 'Load'.
72. You can change the name, I left it at default. Then click Import.
73. It will then load the dashboard and you'll have to select the correct Bucket so the data can populate.