Grafana 12
Overview
Grafana is the de facto open source observability dashboard. It has built-in support for over 100 data sources, including Prometheus, Loki, Azure Monitor, CloudWatch, PostgreSQL, MySQL, MariaDB, ClickHouse, Elasticsearch, OpenSearch, InfluxDB and Tempo.
This guide covers deploying and configuring Grafana 12 OSS on Ubuntu 24.04 on Azure, using the SecureAnyCloud image from the Azure Marketplace.
The image ships Grafana 12.4 from the official packages.grafana.com APT repository (stable channel). The package is pinned with apt-mark hold, so future apt-get upgrade runs do not pull Grafana 13.
On every fresh virtual machine, grafana-firstboot.service replaces the build-time temporary admin password with a strong per-VM password, using grafana-cli admin reset-admin-password. The credentials are written to /stage/scripts/grafana-credentials.log (mode 0600). No two virtual machines share an admin password, and no password is baked into the image.
What you get:
- Grafana 12 OSS server from the official packages.grafana.com APT stable channel (pinned to 12.x and held against upgrade)
grafana-server.servicesystemd unit that starts automatically on bootgrafana-firstboot.servicesystemd oneshot that rotates the admin password- Listener on TCP 3000 (HTTP), bound to 0.0.0.0
- Bundled SQLite backend at
/var/lib/grafana/grafana.db(suitable for single-instance deployments) grafana-cliat/usr/sbin/grafana-clifor plugin management and admin password reset- Ubuntu 24.04 LTS base with the latest security patches applied at build time
- Azure Linux Agent for cloud integration and SSH key injection
- 24/7 SecureAnyCloud support with a guaranteed 24 hour response SLA
Prerequisites
You need:
- An active Azure subscription
- A subscription to the Grafana 12 OSS on Ubuntu 24.04 listing on the Azure Marketplace
- An SSH public key for VM authentication
- A virtual network and subnet in the target region
Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) for small deployments. Scale up to Standard_D2s_v3 if you serve more than 50 dashboards or run heavy ad-hoc queries.
Deploy from the Azure Portal
Open the Azure Portal and go to Marketplace. Search for Grafana 12, select the SecureAnyCloud publisher entry and click Create.
On the Networking tab, attach a network security group that allows inbound TCP 22 from your management IP range and TCP 3000 from your trusted client networks.
Do not expose port 3000 to the public internet without TLS. Grafana listens on plain HTTP by design, so terminate TLS at a reverse proxy. The SecureAnyCloud nginx-ssl-certbot-ubuntu-24-04 image makes a good companion reverse proxy.
Click Review + create, wait for validation, then click Create. Deployment takes around two minutes.
Deploy from the Azure CLI
RG="grafana-prod" LOCATION="eastus" VM_NAME="grafana-01" ADMIN_USER="azureuser" GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-sac/providers/Microsoft.Compute/galleries/sacGallery/images/grafana-12-ubuntu-24-04/versions/<version>" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create \
--resource-group "$RG" \
--name grafana-vnet --address-prefix 10.93.0.0/16 \
--subnet-name grafana-subnet --subnet-prefix 10.93.1.0/24 az network nsg create --resource-group "$RG" --name grafana-nsg az network nsg rule create \
--resource-group "$RG" --nsg-name grafana-nsg \
--name allow-ssh --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" \
--destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create \
--resource-group "$RG" --nsg-name grafana-nsg \
--name allow-grafana --priority 110 \
--source-address-prefixes "<your-mgmt-cidr>" \
--destination-port-ranges 3000 --access Allow --protocol Tcp az vm create \
--resource-group "$RG" --name "$VM_NAME" \
--image "$GALLERY_IMAGE_ID" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username "$ADMIN_USER" --ssh-key-values "$SSH_KEY" \
--vnet-name grafana-vnet --subnet grafana-subnet --nsg grafana-nsg \
--public-ip-sku StandardConnect over SSH
SSH to the VM as azureuser:
ssh azureuser@<vm-ip>grafana-server.service is already running, and grafana-firstboot.service has already rotated the admin password to a per-VM value.
Verify the Grafana service
Check the service status:
sudo systemctl status grafana-server.service --no-pagerThe expected state is active (running). Next, confirm the first-boot sentinel exists:
sudo test -f /var/lib/sac/data/grafana-firstboot.done && echo FIRSTBOOT_DONEConfirm that the listener is up on port 3000:
sudo ss -tln | grep 3000Confirm that the API reports healthy:
curl -s http://localhost:3000/api/healthYou should see {"database": "ok", "version": "12.4.x", "commit": "..."}.
Retrieve the admin password
Read the credentials file:
sudo cat /stage/scripts/grafana-credentials.logThe output looks like this:
ADMIN_USER=admin ADMIN_PASSWORD=<ADMIN_PASSWORD> PORT=3000 URL=http://<vm-ip>:3000Store the password in your secret store. The file is mode 0600 and readable by root only.
Sign in for the first time
Open http://<vm-ip>:3000 in your browser. The Grafana 12 sign-in page appears.
Sign in with admin and the password from Step 5. Grafana opens on the welcome dashboard, with quick links to add a data source and create your first dashboard.
Recommended: change the admin password again from the UI (Profile > Change Password). Create per-user accounts under Administration > Users, so production workflows do not run as the shared admin.
Add a data source
Open Connections > Data sources in the left navigation. On a fresh VM the list is empty. Click Add data source to open the catalog, then pick from the built-in options.
Common Azure pairings:
- Azure Monitor: a built-in plugin. Configure it with an Azure AD service principal (Tenant ID, Client ID, Client Secret) scoped to the subscription you want to query.
- Prometheus: point it at your Prometheus URL.
- PostgreSQL, MySQL and MariaDB: pair with the SecureAnyCloud postgresql-18-pgadmin-ubuntu-24-04, mysql-9-7-lts-ubuntu-24-04 or mariadb-11-ubuntu-24-04 images.
- Loki: point it at your Loki URL for log aggregation.
- OpenSearch and Elasticsearch: pair with the SecureAnyCloud images.
After adding a data source, click Save & Test to confirm the connection.
Install plugins
The image ships with no plugins, to keep it lean. Browse the in-app plugin catalog under Administration > Plugins and data > Plugins.
For scripted deployments, install plugins with grafana-cli from the command line:
sudo grafana-cli plugins install grafana-piechart-panel
sudo systemctl restart grafana-server.serviceRepeat for each plugin you need. Browse the full catalog at https://grafana.com/grafana/plugins/.
Put TLS in front for production
Grafana 12 listens on plain HTTP by design. For production, terminate TLS at a reverse proxy. There are two common paths.
Path A: Caddy or nginx on the same VM
sudo apt-get install -y nginxConfigure /etc/nginx/sites-available/grafana.conf with proxy_pass http://localhost:3000;, and bind apache or nginx on :443 to a real certificate.
Path B: Azure Application Gateway in front
Create an Application Gateway with TLS termination and route the backend pool to the VM private IP on port 3000. Restrict the NSG to allow inbound 3000 from the Application Gateway subnet only.
The SecureAnyCloud nginx-ssl-certbot-ubuntu-24-04 image is purpose-built for Path A. Deploy it on a separate small VM and point it at the private IP of this Grafana VM.
Server components
Key components and paths on the VM:
- Grafana server binary: /usr/sbin/grafana-server
- Grafana CLI: /usr/sbin/grafana-cli
- Config file: /etc/grafana/grafana.ini
- Data directory: /var/lib/grafana/
- Bundled SQLite database: /var/lib/grafana/grafana.db
- Plugin directory: /var/lib/grafana/plugins/
- Log directory: /var/log/grafana/
- Systemd unit: /usr/lib/systemd/system/grafana-server.service
- First-boot script: /usr/local/sbin/grafana-firstboot.sh
- First-boot service: /etc/systemd/system/grafana-firstboot.service
- Credentials file: /stage/scripts/grafana-credentials.log
- First-boot sentinel: /var/lib/sac/data/grafana-firstboot.done
Inspect the installed package version:
dpkg-query -W -f='${Package} ${Version}\n' grafanaConfirm that the package is held against major-version upgrades, so apt-get upgrade does not pull Grafana 13:
apt-mark showhold | grep grafanaManage the Grafana service
Check the status:
sudo systemctl status grafana-server.service --no-pagerStop, start or restart the service:
sudo systemctl stop grafana-server.service
sudo systemctl start grafana-server.service
sudo systemctl restart grafana-server.serviceView the logs:
sudo tail -n 50 /var/log/grafana/grafana.logReset the admin password if you lose it:
sudo grafana-cli admin reset-admin-password '<new-password>'Switch to a PostgreSQL backend (optional, for HA)
For multi-instance deployments behind a load balancer, switch from the bundled SQLite database to PostgreSQL or MySQL. Edit /etc/grafana/grafana.ini:
[database] type = postgres host = <postgres-host>:5432 name = grafana user = grafana password = <password>Create the database and user on your PostgreSQL server first, then restart Grafana.
Do not mix database backends. Pick one and stay with it, because switching later requires a full export and import of the dashboards directory.
Troubleshooting
Cannot reach Grafana on port 3000
- Confirm the service is running:
sudo systemctl status grafana-server.service - Confirm the listener is bound:
sudo ss -tln | grep 3000 - Check the log:
sudo tail -n 50 /var/log/grafana/grafana.log - Confirm the NSG allows TCP 3000 from your client source IP
Lost admin password
- Reset it with
sudo grafana-cli admin reset-admin-password '<new-password>' - The credentials file at
/stage/scripts/grafana-credentials.logcontains the password generated at first boot. Read it withsudo cat
Plugin install failed
- Check internet connectivity from the VM. Grafana CLI fetches plugins from grafana.com
- Check available disk space:
df -h /var/lib/grafana - Try again with verbose logging:
sudo grafana-cli --verbose plugins install <plugin-id>
Service fails to start
- Check the journal:
sudo journalctl -u grafana-server.service --no-pager -n 100 - Check the config syntax:
sudo grafana-server --config /etc/grafana/grafana.ini --check-config - Check filesystem space:
df -h /var/lib/grafana - Verify data directory ownership with
sudo ls -la /var/lib/grafana | head. It should begrafana:grafana
Security recommendations
- Change the admin password again from the UI after your first sign-in.
- Create per-user accounts under Administration > Users, and never share the admin login.
- Restrict port 22 to your management IP ranges only.
- Restrict port 3000 to trusted client networks only. Pair it with TLS from Step 9 for any non-trivial deployment.
- Enable Grafana built-in alerting in production environments, and route alerts to PagerDuty, Opsgenie, Slack or email.
- Switch to a PostgreSQL backend (Step 12) if you need HA across multiple Grafana instances.
- Keep Grafana updated within the 12.x line by running
sudo apt-mark unhold grafana && sudo apt-get install grafana=12.x.y && sudo apt-mark hold grafanaperiodically. Replace 12.x.y with the latest 12 release. - Shred the credentials file once the password is stored in your secret store:
sudo shred -u /stage/scripts/grafana-credentials.log
Support and licensing
Grafana OSS is licensed under the GNU Affero General Public License version 3 (AGPLv3). There is no per-user, per-dashboard or per-server fee. Grafana is a registered trademark of Grafana Labs.
SecureAnyCloud provides commercial support for this image, separately from the upstream project.
- Email: sales@secureanycloud.com
- Website: secureanycloud.com
- Support hours: 24/7, with a guaranteed 24 hour response SLA
Deploy on Azure
Launch Grafana 12 OSS on Ubuntu 24.04 with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Deploy on Azure
Launch Grafana 12 OSS on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com