Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Git
.git
.gitignore

# Build artifacts
build/
minim

# Documentation
*.md
docs/
LICENSE

# IDE and editor files
.idea/
.vscode/
*.swp
*.swo

# Claude Code
.claude/

# Local config
mise.toml

# Docker Compose files (not needed in app image)
compose.yml
.env
.env.example
proxy/
30 changes: 30 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Minimalytics Docker Compose Configuration
# Copy this file to .env and customize the values

# =============================================================================
# Port Configuration
# =============================================================================

# Internal port for minimalytics (not exposed to host by default)
MINIM_PORT=3333

# External port for the authenticated proxy (exposed to host)
PROXY_PORT=3334

# =============================================================================
# Authentication
# =============================================================================

# Username for dashboard access
AUTH_USER=admin

# Password for dashboard access (change this!)
AUTH_PASS=changeme

# =============================================================================
# Optional: Domain Configuration
# =============================================================================

# Your domain name (used for logging/identification, not for TLS)
# TLS termination is handled by your production reverse proxy
DOMAIN=localhost
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
templates/*
.DS_Store
build/*

# Environment file with credentials
.env
40 changes: 40 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Build stage
FROM golang:1.23-alpine AS builder

# Install build dependencies for CGO (required by SQLite)
RUN apk add --no-cache gcc musl-dev

WORKDIR /app

# Copy go mod files first for better layer caching
COPY go.mod go.sum ./
RUN go mod download

# Copy source code
COPY . .

# Build with CGO enabled for SQLite support
RUN CGO_ENABLED=1 go build -ldflags="-s -w" -o minim .

# Runtime stage
FROM alpine:3.20

# Install runtime dependencies for SQLite
RUN apk add --no-cache ca-certificates

WORKDIR /app

# Copy binary from builder
COPY --from=builder /app/minim .

# Copy static files for the web UI
COPY --from=builder /app/static ./static

# Create data directory
RUN mkdir -p /root/.minim

# Expose default port
EXPOSE 3333

# Run the server directly (execserver runs in foreground)
CMD ["./minim", "execserver"]
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,45 @@ Minimalytics is a **standalone minimalist analytics tool** built on SQLite. Desi
sudo mv build/minim /usr/local/bin/
```

### Docker

1. Build the image:
```bash
docker build -t minimalytics .
```

2. Run the container:
```bash
docker run -p 3333:3333 -v minim-data:/root/.minim minimalytics
```

The volume mount persists the SQLite database across container restarts.

### Docker Compose (with authentication)

Docker Compose runs minimalytics with an HAProxy reverse proxy that adds basic authentication to the dashboard while leaving the event API open.

1. Copy the example environment file and configure:
```bash
cp .env.example .env
```

2. Edit `.env` with your credentials:
```
AUTH_USER=admin
AUTH_PASS=your-secure-password
PROXY_PORT=3334
```

3. Start the services:
```bash
docker compose up -d
```

4. Access the services:
- **Dashboard** (requires auth): `http://localhost:3334`
- **Event API** (no auth): `http://localhost:3334/api/event/`

---

## Usage
Expand Down
23 changes: 23 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
services:
minimalytics:
build: .
environment:
- MINIM_PORT=${MINIM_PORT:-3333}
volumes:
- minim-data:/root/.minim
restart: unless-stopped

haproxy:
build: ./proxy
ports:
- "${PROXY_PORT:-3334}:80"
environment:
- AUTH_USER=${AUTH_USER:-admin}
- AUTH_PASS=${AUTH_PASS:-changeme}
- MINIM_PORT=${MINIM_PORT:-3333}
depends_on:
- minimalytics
restart: unless-stopped

volumes:
minim-data:
10 changes: 10 additions & 0 deletions proxy/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Use same Alpine version as minimalytics for layer sharing
FROM alpine:3.20

RUN apk add --no-cache haproxy

COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg

EXPOSE 80

CMD ["haproxy", "-f", "/usr/local/etc/haproxy/haproxy.cfg"]
32 changes: 32 additions & 0 deletions proxy/haproxy.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
global
log stdout format raw local0

defaults
log global
mode http
option httplog
timeout connect 5s
timeout client 30s
timeout server 30s

userlist auth_users
user "${AUTH_USER}" insecure-password "${AUTH_PASS}"

frontend http_front
bind *:80

# ACL for event API - no auth required
acl is_event_api path_beg /api/event/

# Route event API without auth
use_backend minimalytics_noauth if is_event_api

# Everything else requires auth
default_backend minimalytics_auth

backend minimalytics_noauth
server app minimalytics:"${MINIM_PORT}" check

backend minimalytics_auth
http-request auth unless { http_auth(auth_users) }
server app minimalytics:"${MINIM_PORT}" check