Skip to content

How to Deploy SigNoz on a VPS

Updated Sep 2026

verified on Ubuntu 26.04 · Sep 2026
We earn commissions when you shop through the links below. Full disclosure →

Self-host SigNoz on a VPS with Foundry, the supported installer since the old compose files were retired, then keep the UI on loopback behind Caddy and send a test trace.

Before you start
  • A VPS with at least 4 GB RAM (8 GB for real retention)
  • A fresh Ubuntu 24.04 or 26.04 server with root/sudo SSH access
  • A domain you can point at the server
  • Docker Engine 20.10+ with the Compose v2 plugin (see the base guide below)
Need a box for this guide? Kamatera's free tier lets you spin one up now.Start free on Kamatera → (opens in new tab)

What SigNoz is

SigNoz is an OpenTelemetry-native observability platform. It stores metrics, logs and traces in one ClickHouse database and shows them in one UI, so a slow request can take you from its trace to the logs it wrote and the host metrics around it. Applications send data over OTLP, the OpenTelemetry protocol, on ports 4317 (gRPC) and 4318 (HTTP). An OpenTelemetry collector bundled with SigNoz (the "ingester") receives it.

It targets the same work as Datadog's APM. The SigNoz vs Datadog comparison covers what you gain and what you take on. If you only need metrics and dashboards, Prometheus plus Grafana is lighter; see SigNoz vs Grafana. For a single-binary alternative that also handles logs, metrics and traces, see SigNoz vs OpenObserve.

One install change to know first: as of SigNoz v0.130.0, the old install.sh script and the Docker Compose files under deploy/ in the SigNoz repository are deprecated and no longer distributed. The supported installer is Foundry, a CLI (foundryctl) that reads a declarative casting.yaml and generates and starts the Compose stack for you. Guides written before that change will point you at files that no longer exist.

Server sizing

SigNoz is the heaviest app on this page's shelf, because ClickHouse is doing the storage and querying underneath.

  • RAM: SigNoz's install docs require at least 4 GB of memory allocated to Docker. Their troubleshooting section names too little memory as the cause of containers that keep restarting. Budget 8 GB if you intend to keep real trace and log volumes rather than a demo.
  • What we measured: in our install check (GCP e2-standard-2, Ubuntu 26.04, August 2026), the freshly started stack idled at about 501 MB of RAM and took about 3.4 GB of Docker disk before any telemetry arrived. That is the empty baseline. ClickHouse's memory grows with ingest and queries.
  • Disk: telemetry is the growth driver, logs most of all. Start with 40 GB or more of SSD and watch it. Retention (below) controls the ceiling.

Run it on its own box, away from the services it watches. An observability stack that shares a VPS with production competes with production for memory exactly when things go wrong. The Best VPS for Monitoring page ranks hosts for this.

Prepare the server

This guide assumes Docker Engine and the Compose plugin are installed. If not, work through Docker & Compose on Ubuntu first. Allow SSH and the reverse-proxy ports:

sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw --force enable
sudo ufw status verbose

ufw does not protect Docker-published ports. Docker writes its own iptables rules ahead of ufw's, so a container port published as 8080:8080 is reachable from the internet whatever ufw says. That is why the install below rebinds the UI to 127.0.0.1. Your provider's cloud firewall does apply to published ports, so use it for the OTLP ports if your applications run elsewhere.

Where to host itaffiliate disclosure
Hetzner Cloudrun it on
2 vCPU · 4 GB RAM · 80 GB SSD · $23.59/mo
Get Hetzner Cloud (opens in new tab)
Kamaterafree trial
1 vCPU · 1 GB RAM · 20 GB SSD · $4.00/mo
Start free on Kamatera → (opens in new tab)
DigitalOceanalso works on
1 vCPU · 1 GB RAM · 25 GB SSD · $6.00/mo
Deploy on DigitalOcean → (opens in new tab)

Paid link — we earn a commission if you shop through it.

Install foundryctl

The installer script puts foundryctl in ~/.local/bin:

curl -fsSL https://signoz.io/foundry.sh | bash
export PATH="$HOME/.local/bin:$PATH"
grep -q '.local/bin' ~/.bashrc || echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
foundryctl --help | head -5

Write casting.yaml

The casting file describes the installation. The minimal version from SigNoz's docs targets Docker Compose. The patches block uses Foundry's JSON Patch support to change the UI's port mapping from 8080:8080 to 127.0.0.1:8080:8080, so only the reverse proxy can reach it:

mkdir -p ~/signoz && cd ~/signoz
cat > casting.yaml <<'YAML'
apiVersion: v1alpha1
kind: Installation
metadata:
  name: signoz
spec:
  deployment:
    flavor: compose
    mode: docker
  patches:
    - target: "deployment/compose.yaml"
      operations:
        - op: replace
          path: /services/signoz-signoz-0/ports/0
          value: "127.0.0.1:8080:8080"
YAML

Don't edit the generated files under pours/ by hand. Foundry's docs are explicit that forge overwrites them on the next run. Every change goes into casting.yaml: component settings under spec.<component>, anything else under spec.patches.

Deploy

cast checks your environment, renders the Compose files into pours/deployment/, and starts the containers:

cd ~/signoz
export PATH="$HOME/.local/bin:$PATH"
foundryctl cast -f casting.yaml

Pulling ClickHouse and the other images takes a few minutes on the first run. Wait for the SigNoz server to report healthy, then check that the port mapping took effect:

cd ~/signoz
for i in $(seq 1 60); do
  curl -fs http://127.0.0.1:8080/api/v1/health && break
  sleep 5
done
echo
docker ps --format '{{.Names}}\t{{.Status}}\t{{.Ports}}'

You should see ClickHouse, ClickHouse Keeper, Postgres (the metadata store), the ingester and the SigNoz server. The server's port should show 127.0.0.1:8080->8080/tcp. The ingester publishes 4317 and 4318 on all interfaces, because that is where your applications send data.

Create the admin account first

Until the first account exists, SigNoz is not fully set up. Two things follow from that. The signup page is open to whoever reaches the UI first, and that person becomes the root admin. And the ingester does not accept telemetry yet: in our run, OTLP requests to 4318 were refused until an account and organisation existed. They were accepted within a minute of signup. So create the account before you put a domain in front of it and before you debug "missing data".

The UI is bound to loopback, so reach it over an SSH tunnel from your own machine and open http://localhost:8080:

ssh -L 8080:127.0.0.1:8080 deploy@SERVER_IP

If you'd rather do it from the server's shell, the signup form posts to /api/v1/register. This creates the admin with a generated password saved to ~/signoz/admin-password:

cd ~/signoz
[ -f admin-password ] || openssl rand -base64 24 > admin-password
chmod 600 admin-password
curl -s -X POST http://127.0.0.1:8080/api/v1/register \
  -H 'Content-Type: application/json' \
  -d '{"name":"Admin","orgName":"example","email":"admin@example.com","password":"'"$(cat admin-password)"'"}' \
  | grep -o '"isRoot":[a-z]*'

"isRoot":true confirms the account is the root admin. Change the email to yours. It is your login.

Send a test trace

Before wiring up a real application, prove the pipeline works end to end. This posts one span to the OTLP/HTTP endpoint in the standard OpenTelemetry JSON encoding, retrying while the ingester finishes starting:

for i in $(seq 1 30); do
  NOW=$(date +%s%N)
  code=$(curl -s -o /tmp/otlp.out -w '%{http_code}' -X POST http://127.0.0.1:4318/v1/traces \
    -H 'Content-Type: application/json' \
    -d '{"resourceSpans":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"vps-smoke-test"}}]},"scopeSpans":[{"spans":[{"traceId":"5b8efff798038103d269b633813fc60c","spanId":"eee19b7ec3c1b174","name":"smoke-test","kind":1,"startTimeUnixNano":"'"$NOW"'","endTimeUnixNano":"'"$((NOW+50000000))"'"}]}]}]}')
  [ "$code" = 200 ] && break
  sleep 10
done
echo "HTTP $code"; cat /tmp/otlp.out; echo
[ "$code" = 200 ]

HTTP 200 with an empty {"partialSuccess":{}} body means the collector accepted the span. A service called vps-smoke-test should then appear on the Services page.

HTTPS + domain

Point an A record for signoz.example.com at the server and put Caddy in front of the loopback port:

signoz.example.com {
    reverse_proxy 127.0.0.1:8080
}

Then open https://signoz.example.com and log in with the admin account.

Securing the OTLP ports

The UI now requires a login. The OTLP receivers on 4317 and 4318 do not: they accept telemetry from anyone who can reach them. Pick one of these:

  • Applications on the same box: patch the ingester's ports to 127.0.0.1 the same way as the UI, with two more replace operations on /services/ingester/ports/0 and /services/ingester/ports/1.
  • Applications on other servers: restrict 4317/4318 in your provider's cloud firewall to those servers' IPs, or send over a private network or WireGuard.
  • Anything over the public internet: put a local OpenTelemetry Collector next to each application and forward over an authenticated, TLS-terminated path. Don't leave an open ingest port for strangers to fill your disk.

Retention

SigNoz keeps separate retention periods for logs, traces and metrics. Set them in the UI under Settings → Workspace → Retention Controls, with a Save button per signal. Two rules from the docs are worth knowing before you touch them: a change applies only to newly ingested data, and data past its retention is deleted permanently. Raising the number later does not bring it back. Logs usually decide your disk size, so set log retention first.

Backups

Everything lives in three Docker volumes whose names start with signoz-. List them:

docker volume ls --filter name=signoz

The Postgres metadata store holds users, dashboards, alerts and saved views. It is small and the most painful to lose. Dump it with the stack running:

cd ~/signoz
docker exec signoz-metastore-postgres-0 pg_dump -U signoz signoz \
  | gzip > signoz-meta-$(date +%F).sql.gz
ls -lh signoz-meta-*.sql.gz

The ClickHouse volume holds the telemetry itself. It is large, and it is often reasonable not to back it up at all: an observability store is usually worth more for its dashboards and alerts than for last month's spans. If you do want it, stop the stack with docker compose -f pours/deployment/compose.yaml stop, archive the signoz-telemetrystore-0-0-data volume with a throwaway alpine container, and start it again. Copy everything off the box.

Upgrades

The generated Compose file uses latest tags by default. To upgrade, update foundryctl itself, pull new images, and re-run cast:

cd ~/signoz
export PATH="$HOME/.local/bin:$PATH"
curl -fsSL https://signoz.io/foundry.sh | bash
docker compose -f pours/deployment/compose.yaml pull
foundryctl cast -f casting.yaml

To stay on a known version instead, pin the image in casting.yaml under spec.signoz.spec.image (for example signoz/signoz:<version>), as the SigNoz docs show. Take a metadata dump before any upgrade.

Troubleshooting

Containers keep restarting. Almost always memory. Check with free -m and docker stats --no-stream. SigNoz's docs put the floor at 4 GB for Docker.

foundryctl fails. Re-run the same command with --debug. foundryctl gauge -f casting.yaml runs only the prerequisite checks (Docker, Compose) without deploying.

The UI doesn't load through Caddy. Run curl -s 127.0.0.1:8080/api/v1/health on the box. If that works, the problem is DNS or the Caddyfile. If it doesn't, read docker compose -f pours/deployment/compose.yaml logs signoz-signoz-0.

No data from an application. Check that the app's OTLP exporter points at the server on 4317 (gRPC) or 4318 (HTTP), and that the provider firewall allows it. Then send the smoke-test span above from the application's host. If that arrives and the app's data doesn't, the problem is in the app's SDK settings.

Verification + next steps

You're done when https://signoz.example.com loads over a valid certificate, you're logged in as the admin, vps-smoke-test shows up under Services, docker ps shows the UI bound to 127.0.0.1, and a metadata dump sits somewhere off the box.

Next, instrument a real service with an OpenTelemetry SDK and point it at the ingester. Then set log retention to match your disk before the disk decides for you.

Next steps

How to self-host SigNoz →More self-hosted observability tools →Automatic HTTPS with Caddy →Run Claude Code with Ollama on Your Own VPS →Deploy Coolify on a VPS →How to Deploy Actual Budget on a VPS →How to Deploy AnythingLLM on a VPS →How to Deploy Appwrite on a VPS →How to Deploy Audiobookshelf on a VPS →How to Deploy Authelia on a VPS →How to Deploy authentik on a VPS →How to Deploy Baserow on a VPS →How to Deploy Beszel on a VPS →How to Deploy Bitwarden on a VPS →How to Deploy BookStack on a VPS →How to Deploy CapRover on a VPS →How to Deploy Checkmate on a VPS →How to Deploy Directus on a VPS →How to Deploy docker-mailserver on a VPS →How to Deploy Docmost on a VPS →How to Deploy Dokku on a VPS →How to Deploy Dokploy on a VPS →How to Deploy Firefly III on a VPS →How to Deploy Forgejo on a VPS →How to Deploy Gatus on a VPS →How to Deploy Ghostfolio on a VPS →How to Deploy Gitea on a VPS →How to Deploy GitLab on a VPS →How to Deploy GlitchTip on a VPS →How to Deploy Grafana on a VPS →How to Deploy Graylog on a VPS →How to Deploy Headscale on a VPS →How to Deploy Healthchecks on a VPS →How to Deploy Home Assistant on a VPS →How to Deploy Immich on a VPS →How to Deploy Jan on a VPS →How to Deploy Jellyfin on a VPS →How to Deploy Karakeep on a VPS →How to Deploy Keycloak on a VPS →How to Deploy Leantime on a VPS →How to Deploy LibreChat on a VPS →How to Deploy Linkwarden on a VPS →How to Deploy LocalAI on a VPS →How to Deploy Mailcow on a VPS →How to Deploy Mailu on a VPS →How to Deploy Matomo on a VPS →How to Deploy Mattermost on a VPS →How to Deploy Meilisearch on a VPS →How to Deploy Memos on a VPS →How to Deploy n8n on a VPS →How to Deploy Navidrome on a VPS →How to Deploy NetBird on a VPS →How to Deploy Netdata on a VPS →How to Deploy Nextcloud on a VPS →How to Deploy Next.js to a VPS →How to Deploy Nginx Proxy Manager on a VPS →How to Deploy NocoDB on a VPS →How to Deploy ntfy on a VPS →How to Deploy Ollama on a VPS →How to Deploy Open WebUI on a VPS →How to Deploy OpenHands on a VPS →How to Deploy OpenObserve on a VPS →How to Deploy OpenProject on a VPS →How to Deploy Outline on a VPS →How to Deploy Pangolin on a VPS →How to Deploy Paperless-ngx on a VPS →How to Deploy Passbolt on a VPS →How to Deploy Plane on a VPS →How to Deploy Plausible Analytics on a VPS →How to Deploy Pocket ID on a VPS →How to Deploy PocketBase on a VPS →How to Deploy Prometheus on a VPS →How to Deploy Psono on a VPS →How to Deploy Radarr on a VPS →How to Deploy Rocket.Chat on a VPS →How to Deploy Sonarr on a VPS →How to Deploy Stalwart on a VPS →How to Deploy Stirling-PDF on a VPS →How to Deploy Supabase on a VPS →How to Deploy Synapse on a VPS →How to Deploy Taiga on a VPS →How to Deploy TeamPass on a VPS →How to Deploy Tinyauth on a VPS →How to Deploy Traefik on a VPS →How to Deploy Trilium on a VPS →How to Deploy Twenty CRM on a VPS →How to Deploy Umami on a VPS →How to Deploy Uptime Kuma on a VPS →How to Deploy Vaultwarden on a VPS →How to Deploy Vikunja on a VPS →How to Deploy wg-easy on a VPS →How to Deploy Wiki.js on a VPS →How to Deploy Zabbix on a VPS →How to Deploy Zitadel on a VPS →How to Deploy Zulip on a VPS →Docker & Compose on Ubuntu 26.04 →Building AI Workflows with n8n →Install Open WebUI with Ollama →Adding AI-Powered Insights to Plausible Analytics →Building AI-Powered Apps with Supabase and pgvector →

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.