Skip to content
New storyWe built Skald to count visitors. It caught an AI-key thief.
SkaldEvery visit, truly told.

Self-host · Render

Self-hosted analytics on Render, from one Blueprint

Self-hosted analytics on Render is one web service from the Skald image and one persistent disk. The repository's Blueprint sets up both and asks only for your site's names.

Self-hosted analytics on Render means running Skald's Docker image as a Render web service with a persistent disk at /var/lib/skald. Render gives it HTTPS and keeps it up; Skald keeps the history on the disk and takes your sites' logs by HTTPS. One of the ways to self-host Skald free.

30-day free trial · no card · we set it up within one working day · free to self-host

render.yaml · what the Blueprint makes · sampleone instance
  1. web skaldservice
  2. image ghcr.io/spcaeo/skald:latestsource
  3. disk /var/lib/skald · 5 GBhistory
  4. health /traffic-auth/logincheck
  5. SKALD_SITE example.comyou fill in
  6. SKALD_BASE_URL https://stats.example.comHTTPS

Sample values. The Blueprint asks for your own when you deploy.

[01] deploy

Deploy Skald on Render in five steps

The repository's render.yaml is a Render Blueprint. It makes the service, the disk and the settings; you add a domain and two commands in the Shell tab.

  1. 1. Start the Blueprint

    Press Deploy to Render below, or New > Blueprint and pick your fork: Render reads render.yaml at its root. deploy/render.yaml is the same file.

  2. 2. Fill in four settings

    SKALD_SITE, SKALD_HOSTS, SKALD_BASE_URL and SKALD_LOG_DIR. Pick a paid instance type: a disk needs one.

  3. 3. Add your domain

    The service gets an onrender.com address. For your own, Settings > Custom Domains, then the CNAME record Render shows. Render issues the certificate.

  4. 4. Make the first owner

    The service's Shell tab, then skald accounts init. It prints a link to set the password.

  5. 5. Find the proxy

    Render does not publish its proxies' addresses. One command in the Shell tab prints them; set SKALD_TRUSTED_PROXIES to their range.

[02] the Blueprint

What the Render Blueprint sets up

One web service, one disk, the settings. Nothing else: no database service, no worker, no cron job. Skald runs its own schedule inside the one service.

Render's docs do not say who owns a new disk. Either way the container hands /var/lib/skald to its own user, 10001, at the first start, then drops to that user.

From render.yaml, sample values for example.com
PartWhat it is
Servicea web service named skald from ghcr.io/spcaeo/skald:latest
PortPORT=8080
Health check/traffic-auth/login
Diskskald-data, 5 GB at /var/lib/skald. It can grow later, never shrink
Set for youSKALD_INGEST=true, SKALD_TIMEZONE=UTC (change it to yours)
Asks youSKALD_SITE, SKALD_HOSTS, SKALD_BASE_URL, SKALD_LOG_DIR (/var/lib/skald/ingest/example.com)
LaterSKALD_TRUSTED_PROXIES, from step 5

[03] in the Shell tab

Two commands in Render's Shell tab

Open the service, then Shell. Change the name and the email in the first one to your own before you copy.

Render Shell · edit the name and email first
$ skald accounts init --org "Example Co" --owner-email owner@example.com

Prints a link that sets the owner's password.

Render Shell · while the dashboard loads
$ python3 /opt/skald/docker/entrypoint.py peers

Prints the addresses connected to port 8080: Render's proxy, not you.

Set the trusted proxy

Render's proxy opens every connection to Skald and appends the visitor's address to X-Forwarded-For. Until Skald knows which proxy to believe, every visitor has the proxy's address.

  1. Leave SKALD_TRUSTED_PROXIES empty. Open the dashboard, and while it loads, run peers.
  2. Set SKALD_TRUSTED_PROXIES to the smallest private range that holds what it printed, for example 10.0.0.0/8 for 10.x.x.x. Keep SKALD_REAL_IP_HEADER at its default, X-Forwarded-For. Redeploy.
  3. Check: Internal addresses > Add my current address must show your own public address. Remove the entry after.

If it shows another public address on every try, a CDN sits in front of Render's proxy. Empty the setting again and ask Render's support which header holds the visitor's address. Skald refuses 0.0.0.0/0.

[04] your site's log

Send your site's visits to Skald on Render

Render has no log of your website, so the site's requests arrive by HTTPS. SKALD_INGEST=true and SKALD_LOG_DIR turn the receiving end on. Then pick where your site runs.

In the dashboard, Settings > Connections > Send this site's visits to Skald fills in the send address and a sending token for you, and ends with Test connection.

tap one

One command on the web server

On the site's nginx or Apache server, with or without Docker, one command finds the access log and sends its new lines to this Skald. Skald makes the sending token for you.

curl -fsSL https://<your Skald>/traffic-kit/<code> | sudo bash

A template: your Skald shows the real line. Its link works once, for 24 hours.

[05] keeping it

The disk, deploys and upgrades on Render

The disk holds everything Skald keeps: the history, accounts, settings, its own backups and the shipped log lines of the last days.

  1. Grow the disk

    Start at 5 GB. skald doctor in the Shell tab shows how full it is. A Render disk grows, never shrinks, so grow it in small steps.

  2. A short stop per deploy

    With a disk, Render stops the old instance before it starts the new one: a few seconds of downtime. Fine for Skald, which runs as one copy.

  3. Upgrades

    Run skald backup in the Shell tab, then deploy the new image. The databases are brought up to date at start. Pin :2 in the image address to get every 2.x release and never a breaking one.

What it does not do on Render

  • It does not run on a free instance type: there is no disk, so every restart loses the history.
  • It does not scale past one instance. The history is SQLite on one disk.
  • It has no log of your website on Render, so the site's log is sent to it. A site with no server or CDN log (the script tag alone) shows no AI crawlers and no bots.
  • Render does not publish its proxies' addresses, so the trusted range is yours to find and to check again after Render changes its network.

questions

Self-hosted analytics on Render FAQ

Straight answers, including what Skald does not do.

Can Skald run on Render's free instance type?

Not well. A Render disk needs a paid instance type. A free instance has no disk, so Skald would lose its history at every restart. Check Render's pricing page before you choose.

What does the Skald Blueprint make on Render?

A web service from the image ghcr.io/spcaeo/skald:latest on port 8080 with the health check /traffic-auth/login, a 5 GB disk at /var/lib/skald, and the settings. It asks you for SKALD_SITE, SKALD_HOSTS, SKALD_BASE_URL and SKALD_LOG_DIR.

Can I make the Render disk bigger later?

Yes. A Render disk can grow later, but it cannot shrink. Start at 5 GB and grow it when Skald's doctor shows the disk filling.

Is there downtime when Render deploys Skald?

A few seconds. With a disk, Render stops the old instance before it starts the new one, and the service cannot scale past one instance. Both are fine for Skald, which is built to run as exactly one copy.

Why does every visitor show the same address on Render?

Render puts a proxy in front of the service and does not publish its addresses. Run the peers command in the Shell tab while the dashboard loads, then set SKALD_TRUSTED_PROXIES to the smallest private range that holds the addresses it prints, and redeploy.

$ tail -f access.log | skald

See what AI does with your site. Free for 30 days.

No card. We set up hosted Skald for you within one working day, or you self-host it free. Every line of your log, sorted and added up.

Start free trial Live demo