Deployment guide

Perses

Overview

Perses is an open-source dashboard and observability visualization platform and a Cloud Native Computing Foundation project. Like Grafana, it renders rich dashboards over your observability data, currently supporting Prometheus metrics, Tempo traces, Loki logs and Pyroscope profiles. Its distinguishing feature is dashboards as code: dashboards follow an open, standardized specification and can be authored, validated and version-controlled as code with its native CLI and SDKs, which makes it a natural fit for GitOps workflows.

Perses ships as a single, self-contained Go server with the React user interface embedded and a file backend for projects and dashboards, so it stays lightweight and starts instantly. The SecureAnyCloud image installs Perses 0.53.1 behind an nginx reverse proxy that binds the server to loopback.

The appliance is secure by default. Perses is reachable only through nginx on port 80, behind an HTTP Basic Auth gate. Its password is generated uniquely and at random on the first boot of every VM, so no shared or default credential ships in the image. A per-instance at-rest encryption key is generated the same way.

What you get:

  • Perses 0.53.1, a single Go server with the React UI embedded (/opt/perses/perses)
  • percli command-line client for dashboards as code (/opt/perses/percli)
  • File backend for projects and dashboards at /opt/perses/data, with no external database to maintain
  • perses.service running as perses, bound to loopback 127.0.0.1:8080
  • nginx.service reverse proxy on TCP 80 with a per-VM HTTP Basic Auth gate, TLS-ready
  • perses-firstboot.service generating the per-VM password and encryption key on first boot
  • A seeded demo project and a welcome dashboard, so the UI is populated on first boot and you can replace them with your own datasources and dashboards
  • An unauthenticated /healthz endpoint for load balancer probes
  • An Ubuntu 24.04 LTS base with the latest patches and unattended security upgrades enabled
  • 24/7 SecureAnyCloud support, 24h response SLA

Prerequisites

You need an active Azure subscription, an SSH key, and a VNet with a subnet.

The recommended VM size is Standard_B2s. Perses is light, and 4 GB RAM is plenty.

1

Deploy from the Azure Portal

Search the Azure Marketplace for Perses, choose the plan, and create the VM.

In the networking step, attach a network security group (NSG) that allows inbound TCP 22 (SSH) and TCP 80 (the UI, behind Basic Auth) from your client networks only. For production, put a TLS reverse proxy in front of port 80 (Step 16).

2

Deploy from the Azure CLI

Run the following commands, replacing the values in angle brackets:

RG="perses-prod"; LOCATION="eastus"; VM_NAME="perses-01" IMAGE_URN="sac1647283583153:perses-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create -g "$RG" --name ps-vnet --address-prefix 10.108.0.0/16 --subnet-name ps-subnet --subnet-prefix 10.108.1.0/24 az network nsg create -g "$RG" --name ps-nsg az network nsg rule create -g "$RG" --nsg-name ps-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 -g "$RG" --nsg-name ps-nsg --name allow-web --priority 110 \
  --source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 80 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:perses-ubuntu-24-04:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
  --size Standard_B2s --storage-sku StandardSSD_LRS \
  --admin-username azureuser --ssh-key-values "$SSH_KEY" \
  --vnet-name ps-vnet --subnet ps-subnet --nsg ps-nsg --public-ip-sku Standard
3

Connect via SSH

Connect to the VM as azureuser:

ssh azureuser@<vm-ip>

perses.service, nginx.service and perses-firstboot.service all start automatically on first boot.

4

Verify the Service

Check the services, the first-boot marker and the listening ports:

sudo systemctl is-active perses nginx perses-firstboot
sudo test -f /var/lib/sac/data/perses-firstboot.done && echo FIRSTBOOT_DONE
sudo ss -tlnp | grep -E ':80 |8080'

In the expected output, all three services are active. nginx is bound to the public port 80, and Perses is bound to loopback 127.0.0.1:8080 only:

active active active FIRSTBOOT_DONE LISTEN 0 4096 127.0.0.1:8080 0.0.0.0:* users:(("perses",...)) LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",...))
5

Retrieve Your Per-VM Password

The web UI is protected by an HTTP Basic Auth password that is generated uniquely on this VM's first boot. Read it, along with the URL and username, from the root-only credentials file:

sudo cat /root/perses-credentials.txt

The file holds the username (admin), this VM's URL and the per-VM password. No credential is baked into the image, and every VM gets its own. Perses itself is bound to loopback, so the only way in is through the nginx password gate:

PERSES_URL=http://<vm-ip>/ PERSES_USERNAME=admin PERSES_PASSWORD=<PERSES_PASSWORD>

An unauthenticated request is rejected, and Perses listens only on loopback.

6

Open the Perses UI

Open http://<vm-ip>/ in a browser and sign in as admin with the password from Step 5.

The home page lists your projects and recently viewed dashboards. The demo project seeded by the image is already there.

7

Explore the Demo Project

Click the demo project. A project groups dashboards, variables, datasources and secrets. The seeded Welcome dashboard is listed and ready to open.

8

Open the Welcome Dashboard

Open the Welcome dashboard. It renders the sample Markdown panels seeded by the image, so the interface is populated the moment the VM boots. This is the dashboard view you will use for your own metrics, traces, logs and profiles.

9

Edit Dashboards in the Browser

Click Edit to open the dashboard in edit mode. Add panels and panel groups, wire them to variables and datasources, and save. This is the same dashboard model you can also manage as code with percli (Step 12).

10

Use the REST API

Everything in the UI is also available through the JSON REST API, behind the same per-VM password. List your projects and a project's dashboards:

curl -s -u admin:<PERSES_PASSWORD> http://127.0.0.1/api/v1/projects | jq '[.[].metadata.name]'
curl -s -u admin:<PERSES_PASSWORD> http://127.0.0.1/api/v1/projects/demo/dashboards | jq '[.[].metadata.name]'

The calls return the seeded demo project and its welcome dashboard:

[ "demo" ] [ "welcome" ]
11

Create a Project and Dashboard via the API

You can create resources entirely through the API. This example creates a myteam project and a first dashboard with a Markdown panel, then reads the dashboard back:

PW='<PERSES_PASSWORD>' curl -s -u admin:$PW -H 'Content-Type: application/json' -X POST http://127.0.0.1/api/v1/projects \
  -d '{"kind":"Project","metadata":{"name":"myteam"}}' -o /dev/null -w 'create project: %{http_code}\n' curl -s -u admin:$PW -H 'Content-Type: application/json' -X POST http://127.0.0.1/api/v1/projects/myteam/dashboards \
  -d '{"kind":"Dashboard","metadata":{"name":"first","project":"myteam"},"spec":{"duration":"1h","panels":{"n":{"kind":"Panel","spec":{"display":{"name":"Notes"},"plugin":{"kind":"Markdown","spec":{"text":"# My first dashboard"}}}}},"layouts":[{"kind":"Grid","spec":{"items":[{"x":0,"y":0,"width":24,"height":6,"content":{"$ref":"#/spec/panels/n"}}]}}]}}' \
  -o /dev/null -w 'create dashboard: %{http_code}\n' curl -s -u admin:$PW http://127.0.0.1/api/v1/projects/myteam/dashboards/first | jq '.metadata.name'

Both create calls return 200, and the dashboard reads back as "first".

12

Dashboards as Code with percli

Perses ships percli, its command-line client, so you can manage dashboards as code and wire them into CI. Log in to your instance through the password gate, then apply resources from files:

/opt/perses/percli login http://admin:<PERSES_PASSWORD>@127.0.0.1 /opt/perses/percli apply -f my-dashboard.json /opt/perses/percli get dashboards --project demo

A Perses dashboard is a plain declarative document. Keep it in Git, validate it in CI and apply it on merge. This is the core of the dashboards-as-code workflow.

13

Add a Datasource

To visualize live data, add a datasource to a project, for example a Prometheus endpoint. Use the project's Datasources tab in the UI, or add it as a resource file. A project-scoped Prometheus datasource looks like this:

kind: Datasource metadata: name: prometheus project: demo spec: default: true plugin: kind: PrometheusDatasource spec: directUrl: http://your-prometheus:9090

Once a datasource exists, add a TimeSeriesChart, StatChart or GaugeChart panel to a dashboard and query it. The panel plugins for metrics, traces, logs and profiles all ship in the image.

14

Server Components

  • Perses server binary: /opt/perses/perses
  • percli client: /opt/perses/percli
  • Config file: /etc/perses/config.yaml
  • File database (projects and dashboards): /opt/perses/data
  • Bundled plugin archives: /opt/perses/plugins-archive
  • systemd unit: /etc/systemd/system/perses.service
  • First-boot script: /usr/local/sbin/perses-firstboot.sh
  • Per-VM credentials note: /root/perses-credentials.txt (mode 0600)
  • nginx Basic Auth file: /etc/nginx/.perses.htpasswd (per-VM bcrypt)

Confirm that the files exist and that the health endpoint responds:

ls -1 /opt/perses/perses /opt/perses/percli /etc/perses/config.yaml /opt/perses/data curl -sI http://127.0.0.1/healthz | head -1
15

Managing the Service

Restart the service and read its recent log lines with:

sudo systemctl restart perses.service
sudo journalctl -u perses.service --no-pager -n 15

Perses is a single binary with a local file database, so it restarts in a second or two. The service is hardened with NoNewPrivileges, ProtectSystem=full and ProtectHome, and it has write access to its own directory only.

16

Add TLS (Optional)

For production, terminate TLS at nginx. Point a DNS record at the VM, then use the packaged nginx with a certificate from Let's Encrypt:

sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain>

certbot installs the certificate, rewrites the nginx server block to listen on 443 and sets up automatic renewal. Keep the Basic Auth gate in place so the UI stays private over HTTPS.

17

Change or Rotate the Password

The password lives in the nginx Basic Auth file. To set a new one, regenerate the entry with htpasswd (bcrypt), then reload nginx:

sudo htpasswd -B /etc/nginx/.perses.htpasswd admin
sudo systemctl reload nginx

Update /root/perses-credentials.txt if you want the note to reflect the new value. The password is stored only on this VM.

18

Security Recommendations

  • Restrict the NSG so ports 80 and 22 reach only trusted networks.
  • Terminate TLS at nginx (Step 16) so the UI and API travel encrypted.
  • Keep Perses on loopback. It is served only through the nginx password gate, so do not bind it to a public interface.
  • Rotate the password (Step 17) and store it in your secrets manager.
  • Back up /opt/perses/data to Azure Blob so your projects and dashboards survive a rebuild.
  • Patch the OS monthly with sudo apt-get update && sudo apt-get upgrade. Unattended security upgrades are already enabled.
19

Support and Licensing

Perses is licensed under the Apache License 2.0, with no per-CPU or per-user fee. SecureAnyCloud provides commercial support separately.

  • Email: sales@secureanycloud.com
  • Website: secureanycloud.com
  • Support hours: 24/7, 24h response SLA

Deploy on Azure

Launch Perses 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 Perses 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

Deploy on Azure