Deployment guide

Jellystat

Overview

Jellystat is a popular open source, self-hosted statistics and analytics dashboard for a Jellyfin media server. It records playback activity and presents your libraries, users, full and grouped watch history, most active content and live now-playing sessions in a clean, modern interface with charts and drill-downs.

This SecureAnyCloud image builds Jellystat 1.1.11 from source under /opt/jellystat and fronts it with nginx on port 80. It is secure by default: the image ships uninitialised, with no administrator and no shared secret. Your first visit opens a setup wizard where you create your own administrator and add your Jellyfin server.

Two per-VM secrets, a JWT signing secret and the PostgreSQL role password, are generated on first boot and never shared between instances. The jellystat-firstboot.service oneshot rotates those secrets, ensures the empty database exists, resolves the instance URL and starts the stack, then disables itself.

What you get:

  • Jellystat 1.1.11 (MIT) under /opt/jellystat
  • Local PostgreSQL 16 database jfstat, bound to loopback (127.0.0.1:5432)
  • jellystat.service running as the dedicated jellystat system user, bound to loopback at 127.0.0.1:3000
  • nginx reverse proxy on port 80, configured for the Socket.io WebSocket traffic that the live now-playing view relies on, and ready for your TLS certificate
  • jellystat-firstboot.service for per-VM secret rotation and stack start
  • Node.js 22 LTS runtime
  • Ubuntu 24.04 LTS base, patched at build time
  • 24/7 SecureAnyCloud support, 24h response SLA

Prerequisites

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

The recommended VM size is Standard_B2s. Jellystat is lightweight, and 4 GB of RAM is comfortable.

You also need a reachable Jellyfin server and a Jellyfin API key, so that Jellystat can read playback data during setup.

1

Deploy from the Azure Portal

Search the Azure Marketplace for Jellystat on Ubuntu 24.04 and choose your VM size.

Attach a network security group (NSG) that allows TCP 22 (SSH) from your management network and TCP 80 / 443 (the web app) from the networks that need it. In production, put TLS in front of port 80 (see Step 10).

2

Deploy from the Azure CLI

RG="jellystat-prod"; LOCATION="eastus"; VM_NAME="jellystat-01" IMAGE_URN="sac1647283583153:jellystat-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 js-vnet --address-prefix 10.90.0.0/16 --subnet-name js-subnet --subnet-prefix 10.90.1.0/24 az network nsg create -g "$RG" --name js-nsg az network nsg rule create -g "$RG" --nsg-name js-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 js-nsg --name allow-web --priority 110 \
  --source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 80 443 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:jellystat-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 js-vnet --subnet js-subnet --nsg js-nsg --public-ip-sku Standard
3

Connect over SSH

ssh azureuser@<vm-ip>
4

Verify the services are running

Run the commands below to check the stack. PostgreSQL and Jellystat listen on loopback only. nginx serves the web app on port 80 and proxies its Socket.io WebSocket traffic.

sudo systemctl is-active postgresql jellystat nginx ss -tln | grep -E ':80 |127.0.0.1:3000|127.0.0.1:5432' curl -s -o /dev/null -w 'GET /auth/isconfigured -> HTTP %{http_code}\n' http://127.0.0.1/auth/isconfigured

All three services report active. PostgreSQL is bound to 127.0.0.1:5432, the Node server to 127.0.0.1:3000 and nginx to :80. The configuration API returns HTTP 200 through nginx.

5

Confirm the secure defaults

Nothing sensitive ships in the image. The application reports state:0, so every instance starts at the create-admin wizard. The per-VM credentials note in /root is root-only.

The JWT signing secret and the PostgreSQL password are generated on first boot. The command below masks them.

curl -s http://127.0.0.1/auth/isconfigured
sudo stat -c '%n perms=%a owner=%U:%G' /root/jellystat-credentials.txt
sudo sed -E 's/^(JWT_SECRET|POSTGRES_PASSWORD)=.*/\1=**** (per-VM, first boot)/' /root/jellystat-credentials.txt | grep -E '^JELLYSTAT_URL|^POSTGRES_USER|^POSTGRES_DB|^NOTE'
curl -s -o /dev/null -w 'GET /api/getLibraries (no token) -> HTTP %{http_code}\n' http://127.0.0.1/api/getLibraries

The app reports state:0 (create-admin wizard) and the credentials note is 600 root:root. The two secrets are unique to this VM. A protected API endpoint returns HTTP 401 without an auth token.

6

Complete the first-run setup wizard

Open http://<vm-ip>/ in your browser. Because no administrator ships with the image, Jellystat shows First Time Setup Step 1 of 2. Choose your own admin username and password, then click Create User.

Step 2 of 2 asks for your Jellyfin server URL and an API key, so that Jellystat can read playback data. Create the key in Jellyfin under Dashboard, API Keys. Enter the URL and the key, then click Save Jellyfin Details.

7

Sign in and explore the dashboard

After setup, Jellystat requires authentication. Sign in with the admin username and password you just created.

The dashboard shows live now-playing sessions, recently added media, watch statistics over a configurable window, and a library overview. The left navigation gives you Libraries, Users, Activity, Statistics and Settings.

8

The runtime stack

node -v nginx -v sudo runuser -u postgres -- psql -tAc 'show server_version' jq -r .version /opt/jellystat/package.json

Node.js 22 LTS runs the server, nginx 1.24 fronts it and PostgreSQL 16 stores the data. The pinned Jellystat release is 1.1.11.

9

Data and persistence

All statistics live in the local PostgreSQL database jfstat, which is captured into the image and carried onto every instance. The application creates its own schema on first connect.

sudo runuser -u postgres -- psql -tAc "SELECT datname FROM pg_database WHERE datname='jfstat'" systemctl is-enabled jellystat-firstboot.service apt-mark showhold

The jfstat database is present. The first-boot service has run and disabled itself for this instance. No packages are held, so the OS security baseline is intact.

10

Enable HTTPS

nginx already fronts Jellystat on port 80 and is ready for TLS. Point a DNS record at your VM, then obtain a certificate with certbot.

sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain> --agree-tos -m <your-email> --redirect

certbot installs the certificate, rewrites the nginx server block for TLS and sets up automatic renewal. Your analytics portal is then served over HTTPS.

Managing the service

sudo systemctl status jellystat --no-pager sudo systemctl restart jellystat
sudo journalctl -u jellystat -n 20 --no-pager

The Node server logs to the journal. nginx logs are under /var/log/nginx/, and the PostgreSQL data lives under /var/lib/postgresql.

To back up the instance, snapshot the OS disk or use Jellystat's own scheduled backup feature under Settings.

Support

SecureAnyCloud provides 24/7 support for this image by email and live chat. Support covers deployment, nginx TLS termination, upgrades, Jellyfin integration and API keys, and PostgreSQL tuning and backups. Email sales@secureanycloud.com.

This is a repackaged open source software product, with additional charges for SecureAnyCloud support services. Jellystat and Jellyfin are trademarks of their respective owners. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.

Deploy on Azure

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