try.directtry.direct

Deploy Self-Hosted Analytics in 5 Minutes - Umami + Stacker

What You'll Build

A self-hosted Umami analytics dashboard with PostgreSQL - running on your machine in under 5 minutes. No Google Analytics, no data leaves your server.

  • Umami dashboard (Node.js)
  • PostgreSQL database with healthchecks
  • Persistent volumes for data
  • .env template with auto-generated secrets

Quick Answer

mkdir ~/umami && cd ~/umami
stacker init --from-github umami-software/umami --with-ai --force
cp .env.example .env && ./scripts/generate-secrets.sh
stacker deploy --target local
Dashboard at http://localhost:3000. Default login: admin / umami.

Prerequisites

  • Docker (docker --version)
  • Git (git --version)
  • Stacker (stacker --version)

Step 1: Install Stacker

curl -fsSL https://raw.githubusercontent.com/trydirect/stacker/main/install.sh | bash
stacker --version
# stacker 0.3.0

Step 2: Generate Configuration

mkdir ~/umami && cd ~/umami
stacker init --from-github umami-software/umami --with-ai --force

Stacker clones Umami, reads the docker-compose.yml, and generates:

stacker.yml                 # Deployment config
.stacker/Dockerfile         # Optimized Node.js build
.stacker/docker-compose.yml # Production compose file
.env.example                # All env vars with placeholders
scripts/generate-secrets.sh # Fills in passwords

Step 3: Configure Secrets

cp .env.example .env
./scripts/generate-secrets.sh
# Generates: DB_PASSWORD, DATABASE_URL, HASH_SALT

Optional - edit .env to set your timezone or tracking domain:

TZ=UTC
TRACKER_SCRIPT_NAME=tracker.js

Step 4: Deploy

stacker config validate
# ✓ Configuration is valid

stacker deploy --target local
# Building app...
# Creating postgres...
# ✓ Stack deployed successfully

Step 5: Verify and Use

stacker status
# umami     running
# postgres  running

open http://localhost:3000

Login with admin / umami. Change the password immediately.

Understanding the Generated Config

The stacker.yml that Stacker generated:

name: umami
app:
  type: node
  ports:
    - "3000:3000"
  environment:
    DATABASE_URL: "postgresql://umami:${DB_PASSWORD}@postgres:5432/umami"
    NEXT_AUTH_URL: "http://localhost:3000"
    NEXT_AUTH_SECRET: "${HASH_SALT}"
services:
  - name: postgres
    image: postgres:16-alpine
    ports:
      - "127.0.0.1:5432:5432"
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: "${DB_PASSWORD}"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: "CMD pg_isready -U umami"
      interval: 5s
      timeout: 2s
      retries: 10
volumes:
  postgres_data: {}

What Stacker got right automatically:

  • Node.js detected from package.json
  • PostgreSQL service extracted from compose file
  • Healthcheck - pg_isready added for database
  • Port isolation - PostgreSQL on 127.0.0.1 only
  • Named volume - data persists across restarts
  • Secrets - no hardcoded passwords

Customizing

Add a reverse proxy with SSL

# Add to stacker.yml:
proxy:
  type: nginx
  auto_detect: true
  domains:
    - domain: analytics.yourdomain.com
      ssl: auto
      upstream: app:3000

stacker deploy --target local

Deploy to a remote server

stacker config setup server
# Enter: host, user, SSH key

stacker deploy --target server

Deploy to cloud

stacker config setup cloud
# Choose: hetzner, digitalocean, aws, linode, vultr

stacker deploy --target cloud

Adding Your Website to Umami

Once Umami is running:

  1. Open http://localhost:3000
  2. Login → Settings → Websites → Add Website
  3. Enter your domain and name
  4. Copy the tracking script into your HTML:
<script defer src="http://localhost:3000/tracker.js"
        data-website-id="your-website-id"></script>

Troubleshooting

Port 3000 already in use

# Edit stacker.yml:
app:
  ports:
    - "3001:3000"

stacker deploy --target local

Database connection refused

# Check PostgreSQL is healthy:
stacker status

# Check logs:
stacker logs postgres

Want to reset everything

stacker destroy --target local
rm -rf .stacker stacker.yml .env .env.example

Key Takeaways

  • Umami deploys in 5 minutes with 4 commands
  • Stacker handles the entire Docker stack automatically
  • Healthchecks, port isolation, and secret generation are built in
  • The same config works on local, server, or cloud
  • Source: github.com/trydirect/stacker

Try It Yourself

Deploy this stack or browse pre-built templates in the marketplace. Your first deployment is always free.