Merge pull request 'docs: public readiness — env reference, clustering guide, README improvements' (#50) from chore/public-readiness into main
Reviewed-on: #50
This commit was merged in pull request #50.
This commit is contained in:
@@ -8,3 +8,5 @@ vendor/
|
|||||||
*.local.json
|
*.local.json
|
||||||
*.local.md
|
*.local.md
|
||||||
*.local
|
*.local
|
||||||
|
.env
|
||||||
|
.github/
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# ─── uptop configuration ───────────────────────────────────
|
||||||
|
# Copy to .env and edit. Only uncomment what you need.
|
||||||
|
|
||||||
|
# ─── Core ──────────────────────────────────────────────────
|
||||||
|
UPTOP_PORT=23234 # SSH server port
|
||||||
|
UPTOP_HTTP_PORT=8080 # HTTP port (status page, push endpoints, metrics)
|
||||||
|
UPTOP_DB_TYPE=sqlite # sqlite or postgres
|
||||||
|
UPTOP_DB_DSN=/data/uptop.db # File path (SQLite) or connection string (Postgres)
|
||||||
|
|
||||||
|
# ─── Security ─────────────────────────────────────────────
|
||||||
|
# UPTOP_ADMIN_KEY=ssh-ed25519 AAAA... you@host # Seed first admin user on startup
|
||||||
|
# UPTOP_KEYS=/data/authorized_keys # Path to authorized_keys file (one key per line)
|
||||||
|
# UPTOP_SSH_HOST_KEY=/data/.ssh/id_ed25519 # SSH host key path (auto-generated if missing)
|
||||||
|
# UPTOP_ENCRYPTION_KEY= # AES-256-GCM key for alert credentials (64 hex chars)
|
||||||
|
# # Generate: openssl rand -hex 32
|
||||||
|
# # Without this, alert passwords/tokens stored in plaintext
|
||||||
|
# UPTOP_CLUSTER_SECRET= # Shared key for cluster API + import/export auth
|
||||||
|
|
||||||
|
# ─── Status Page ──────────────────────────────────────────
|
||||||
|
# UPTOP_STATUS_ENABLED=false # Enable public status page at /status
|
||||||
|
# UPTOP_STATUS_TITLE=System Status # Status page heading
|
||||||
|
|
||||||
|
# ─── TLS ──────────────────────────────────────────────────
|
||||||
|
# UPTOP_TLS_CERT= # Path to TLS certificate (enables HTTPS)
|
||||||
|
# UPTOP_TLS_KEY= # Path to TLS private key
|
||||||
|
|
||||||
|
# ─── Clustering (leader/follower) ────────────────────────
|
||||||
|
# See docs/clustering.md for setup guides.
|
||||||
|
# UPTOP_CLUSTER_MODE=leader # leader, follower, or probe
|
||||||
|
# UPTOP_PEER_URL= # Leader HTTP URL (required for follower and probe)
|
||||||
|
|
||||||
|
# ─── Distributed Probing ─────────────────────────────────
|
||||||
|
# UPTOP_NODE_ID= # Unique node identifier (required for probe mode)
|
||||||
|
# UPTOP_NODE_NAME= # Human-readable node name
|
||||||
|
# UPTOP_NODE_REGION= # Region tag (e.g. us-east, eu-west) for monitor routing
|
||||||
|
# UPTOP_AGG_STRATEGY=any-down # How multi-probe results combine: any-down, majority-down, all-down
|
||||||
|
|
||||||
|
# ─── Advanced ─────────────────────────────────────────────
|
||||||
|
# UPTOP_INSECURE_SKIP_VERIFY=false # Skip TLS cert verification on monitored targets
|
||||||
|
# UPTOP_ALLOW_PRIVATE_TARGETS=false # Allow monitoring RFC1918/loopback addresses
|
||||||
|
# UPTOP_METRICS_PUBLIC=false # Expose /metrics without auth
|
||||||
|
# UPTOP_CORS_ORIGIN= # Access-Control-Allow-Origin for /status/json
|
||||||
@@ -25,3 +25,4 @@ authorized_keys
|
|||||||
tmp
|
tmp
|
||||||
*.local.json
|
*.local.json
|
||||||
*.local.md
|
*.local.md
|
||||||
|
.env
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [2026.06.2] — 2026-06-02 (infrastructure)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Split release pipeline into separate binary and Docker workflows (#45)
|
||||||
|
- Pin Docker base images by digest (#45)
|
||||||
|
- Add GitHub release relay — mirrors Gitea releases to GitHub (#49)
|
||||||
|
- Add Grype CVE scanning to Docker pipeline (#45)
|
||||||
|
- Make CVE scan non-blocking for non-exploitable wish SCP vulnerability (#48)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- git-cliff install in CI — resolve download URL dynamically, extract to /tmp (#46, #47)
|
||||||
|
|
||||||
## [2026.06.1] — 2026-06-01
|
## [2026.06.1] — 2026-06-01
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
@@ -15,6 +27,14 @@
|
|||||||
- Existing Docker volumes with root-owned files require migration before upgrading:
|
- Existing Docker volumes with root-owned files require migration before upgrading:
|
||||||
`docker run --rm -v <volume>:/data alpine chown -R 1000:1000 /data`
|
`docker run --rm -v <volume>:/data alpine chown -R 1000:1000 /data`
|
||||||
|
|
||||||
|
## [2026.05.6] — 2026-05-30 (infrastructure)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Sync README to Docker Hub on release (#43)
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Patch Docker Scout CVEs, remove unused openssh-client (#41)
|
||||||
|
|
||||||
## [2026.05.5] — 2026-05-29
|
## [2026.05.5] — 2026-05-29
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -86,9 +86,9 @@ First run: set `UPTOP_ADMIN_KEY` to your SSH public key, or attach to the contai
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><strong>Binary</strong></summary>
|
<summary><strong>Binary (Linux amd64)</strong></summary>
|
||||||
|
|
||||||
Download from [Releases](https://gitea.lerkolabs.com/lerkolabs/uptop/releases).
|
Download from [Releases](https://github.com/lerkolabs/uptop/releases).
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -101,6 +101,8 @@ go install gitea.lerkolabs.com/lerkolabs/uptop/cmd/uptop@latest
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
**Upgrading:** Pull the new image (or binary) and restart. Database migrations run automatically on startup.
|
||||||
|
|
||||||
## Config as code
|
## Config as code
|
||||||
|
|
||||||
Export your current monitors:
|
Export your current monitors:
|
||||||
@@ -129,12 +131,30 @@ Full reference in [docs/config-as-code.md](docs/config-as-code.md).
|
|||||||
| `UPTOP_DB_DSN` | `uptop.db` | Database path or connection string |
|
| `UPTOP_DB_DSN` | `uptop.db` | Database path or connection string |
|
||||||
| `UPTOP_STATUS_ENABLED` | `false` | Enable public status page |
|
| `UPTOP_STATUS_ENABLED` | `false` | Enable public status page |
|
||||||
| `UPTOP_STATUS_TITLE` | `System Status` | Status page title |
|
| `UPTOP_STATUS_TITLE` | `System Status` | Status page title |
|
||||||
| `UPTOP_CLUSTER_MODE` | `leader` | `leader` or `follower` |
|
| `UPTOP_ENCRYPTION_KEY` | | AES-256-GCM key for alert credentials ([details](#encryption)) |
|
||||||
| `UPTOP_PEER_URL` | | Leader URL for follower nodes |
|
| `UPTOP_CLUSTER_MODE` | `leader` | `leader`, `follower`, or `probe` |
|
||||||
|
| `UPTOP_PEER_URL` | | Leader URL for follower and probe nodes |
|
||||||
| `UPTOP_CLUSTER_SECRET` | | Shared key for cluster + API auth |
|
| `UPTOP_CLUSTER_SECRET` | | Shared key for cluster + API auth |
|
||||||
| `UPTOP_INSECURE_SKIP_VERIFY` | `false` | Skip TLS verification for checks |
|
| `UPTOP_INSECURE_SKIP_VERIFY` | `false` | Skip TLS verification for checks |
|
||||||
|
| `UPTOP_ALLOW_PRIVATE_TARGETS` | `false` | Allow monitoring RFC1918/loopback addresses |
|
||||||
| `UPTOP_ADMIN_KEY` | | SSH public key seeded as first admin on startup |
|
| `UPTOP_ADMIN_KEY` | | SSH public key seeded as first admin on startup |
|
||||||
|
|
||||||
|
See [`.env.example`](.env.example) for all options including TLS, probes, and advanced settings.
|
||||||
|
|
||||||
|
### Encryption
|
||||||
|
|
||||||
|
Set `UPTOP_ENCRYPTION_KEY` to encrypt alert credentials (SMTP passwords, webhook URLs, API tokens) at rest with AES-256-GCM. Generate a key:
|
||||||
|
|
||||||
|
openssl rand -hex 32
|
||||||
|
|
||||||
|
Without this, credentials are stored as plaintext in the database. uptop warns on startup if unset. To encrypt credentials on an existing install, run `uptop migrate-secrets` with the key set.
|
||||||
|
|
||||||
|
## Clustering
|
||||||
|
|
||||||
|
uptop supports three modes: **leader** (default single node), **follower** (HA failover — takes over if the leader goes down), and **probe** (stateless distributed checks from multiple regions).
|
||||||
|
|
||||||
|
See [docs/clustering.md](docs/clustering.md) for setup guides, or the working examples in [`deploy/`](deploy/).
|
||||||
|
|
||||||
## Migrating from Uptime Kuma
|
## Migrating from Uptime Kuma
|
||||||
|
|
||||||
Export your Kuma backup JSON, then:
|
Export your Kuma backup JSON, then:
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# Clustering
|
||||||
|
|
||||||
|
uptop supports three deployment modes for different reliability and coverage needs.
|
||||||
|
|
||||||
|
## Single node (default)
|
||||||
|
|
||||||
|
Out of the box, uptop runs as a standalone leader. One process, one database, runs all checks. No clustering config needed.
|
||||||
|
|
||||||
|
## Leader + follower (HA failover)
|
||||||
|
|
||||||
|
A follower is a standby replica that takes over if the leader goes down.
|
||||||
|
|
||||||
|
**How it works:**
|
||||||
|
- The follower polls the leader's `/api/health` endpoint every 5 seconds
|
||||||
|
- After 3 consecutive failures (15 seconds), the follower promotes itself and starts running checks
|
||||||
|
- When the leader recovers, the follower detects it and goes back to standby
|
||||||
|
- Both nodes have their own database — they do not share state
|
||||||
|
|
||||||
|
**Required env vars:**
|
||||||
|
|
||||||
|
| Node | Variable | Value |
|
||||||
|
|------|----------|-------|
|
||||||
|
| Both | `UPTOP_CLUSTER_SECRET` | Same shared secret |
|
||||||
|
| Follower | `UPTOP_CLUSTER_MODE` | `follower` |
|
||||||
|
| Follower | `UPTOP_PEER_URL` | Leader's HTTP URL (e.g. `http://leader:8080`) |
|
||||||
|
|
||||||
|
See [`deploy/docker-compose.cluster.yml`](../deploy/docker-compose.cluster.yml) for a working example.
|
||||||
|
|
||||||
|
## Leader + probes (distributed monitoring)
|
||||||
|
|
||||||
|
Probes are lightweight, stateless nodes that run checks from different locations and report results back to the leader.
|
||||||
|
|
||||||
|
**How it works:**
|
||||||
|
- A probe registers with the leader on startup
|
||||||
|
- Every 30 seconds, it fetches check assignments filtered by its region
|
||||||
|
- It runs the assigned checks (up to 10 concurrent) and posts results back
|
||||||
|
- The leader aggregates results from all probes and triggers alerts based on the aggregation strategy
|
||||||
|
- Probes have no database, no UI, and no configuration of their own
|
||||||
|
|
||||||
|
**Required env vars:**
|
||||||
|
|
||||||
|
| Node | Variable | Value |
|
||||||
|
|------|----------|-------|
|
||||||
|
| Both | `UPTOP_CLUSTER_SECRET` | Same shared secret |
|
||||||
|
| Leader | `UPTOP_AGG_STRATEGY` | `any-down`, `majority-down`, or `all-down` |
|
||||||
|
| Probe | `UPTOP_CLUSTER_MODE` | `probe` |
|
||||||
|
| Probe | `UPTOP_PEER_URL` | Leader's HTTP URL |
|
||||||
|
| Probe | `UPTOP_NODE_ID` | Unique identifier (e.g. `probe-us-east`) |
|
||||||
|
| Probe | `UPTOP_NODE_REGION` | Region tag matching monitor assignments |
|
||||||
|
|
||||||
|
Optional: `UPTOP_NODE_NAME` for a human-readable label in the TUI.
|
||||||
|
|
||||||
|
See [`deploy/docker-compose.probe.yml`](../deploy/docker-compose.probe.yml) for a multi-region example.
|
||||||
|
|
||||||
|
## Aggregation strategies
|
||||||
|
|
||||||
|
When multiple probes check the same monitor, the leader combines their results:
|
||||||
|
|
||||||
|
| Strategy | Behavior |
|
||||||
|
|----------|----------|
|
||||||
|
| `any-down` (default) | DOWN if **any** probe reports down |
|
||||||
|
| `majority-down` | DOWN if **most** probes report down |
|
||||||
|
| `all-down` | DOWN only if **all** probes report down |
|
||||||
|
|
||||||
|
Set via `UPTOP_AGG_STRATEGY` on the leader.
|
||||||
|
|
||||||
|
## Follower vs probe
|
||||||
|
|
||||||
|
| | Follower | Probe |
|
||||||
|
|---|---|---|
|
||||||
|
| **Purpose** | Failover / redundancy | Distributed checks from multiple regions |
|
||||||
|
| **Database** | Own database (independent) | None (stateless) |
|
||||||
|
| **Runs checks** | Only when leader is down | Always, on assigned monitors |
|
||||||
|
| **Scales to** | 1 follower per leader | Many probes per leader |
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- Set `UPTOP_CLUSTER_SECRET` on all nodes. Without it, cluster API endpoints are unauthenticated.
|
||||||
|
- Secrets are sent in HTTP headers (`X-Upkeep-Secret`). Use TLS or a reverse proxy for production.
|
||||||
|
- uptop warns on startup if the cluster secret is missing or if cluster mode is active without TLS.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
module gitea.lerkolabs.com/lerkolabs/uptop
|
module gitea.lerkolabs.com/lerkolabs/uptop
|
||||||
|
|
||||||
go 1.26.3
|
go 1.26.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7
|
github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7
|
||||||
|
|||||||
Reference in New Issue
Block a user