Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
3769302
feat(frontend): add ApexCharts foundations for Chart.js migration
Aug 11, 2026
41c539a
feat(disk): migrate DiskHistoryChart.vue to ApexCharts
Aug 11, 2026
2ca9c6b
feat(host): migrate HostMetricsPanel.vue to ApexCharts
Aug 11, 2026
5d543d2
feat(proxmox): migrate RRDChartCard/ProxmoxNodeChartsPanel to ApexCharts
Aug 11, 2026
ff96ddd
feat(proxmox): migrate ProxmoxGuestView.vue CPU/RAM chart to ApexCharts
Aug 11, 2026
c5f64c6
feat(network-flows): migrate NetworkFlowsHistoryChart.vue to ApexCharts
Aug 11, 2026
6392076
feat(monitoring): migrate UptimeDetailSection.vue latency chart to Ap…
Aug 11, 2026
21dbd97
feat(dashboard): migrate DashboardView.vue summary chart to ApexCharts
Aug 11, 2026
f21732d
feat(security): rewrite TrafficRequestsChart/TrafficStatusChart to de…
Aug 11, 2026
b99a0cd
chore(frontend): remove chart.js/vue-chartjs, finish ApexCharts migra…
Aug 11, 2026
a497f2e
Merge pull request #257 from Rem7474/claude/apexcharts-migration
Rem7474 Aug 16, 2026
ab876d6
refactor(frontend): migrate NotificationBell dropdown to native Table…
Aug 16, 2026
c3d5971
refactor(frontend): migrate ToastContainer to native Tabler .toast
Aug 16, 2026
8e5066f
Merge pull request #262 from Rem7474/claude/tabler-notification-dropdown
Rem7474 Aug 16, 2026
2629b80
Merge pull request #263 from Rem7474/claude/tabler-toast-container
Rem7474 Aug 16, 2026
4bf7237
refactor(frontend): adopt Tabler .datagrid for SSL certificate details
Aug 16, 2026
8d997b7
Merge pull request #264 from Rem7474/claude/tabler-datagrid
Rem7474 Aug 16, 2026
ba77e61
refactor(frontend): use Tabler .tracking layout for uptime availabili…
Aug 16, 2026
0dd9e50
Merge pull request #265 from Rem7474/claude/tabler-tracking
Rem7474 Aug 16, 2026
292ead2
refactor(server): align alert email template with Tabler's own email …
Aug 16, 2026
cf668f4
Merge pull request #266 from Rem7474/claude/tabler-email-templates
Rem7474 Aug 16, 2026
077cd8e
refactor(frontend): split navbar into two rows (Tabler dashboard patt…
Aug 16, 2026
8625b2b
fix(frontend): keep row 1 on a single line on mobile
Aug 16, 2026
1da3ce2
Merge pull request #267 from Rem7474/claude/tabler-two-tier-navbar
Rem7474 Aug 16, 2026
d5244fe
docs: update screenshots for v10.5.0-dev
github-actions[bot] Aug 16, 2026
c290e4a
fix(go): bump toolchain to 1.25.13 and klauspost/compress to close CVEs
Aug 16, 2026
a0bdb88
fix(frontend): bump nanoid to close high-severity npm audit finding
Aug 16, 2026
ac4d7a5
ci(security): stop pinning govulncheck to a stale v1.1.4
Aug 16, 2026
8cac0ea
ci(security): also run on pull_request, not just push to main
Aug 16, 2026
280b738
ci(security): split CodeQL into its own workflow, scoped to source paths
Aug 16, 2026
ef73765
merge: main into dev, keeping main's screenshots on conflict
Aug 16, 2026
d424ec9
fix(go): bump moby/go-archive, moby/sys/user, x/net to close nancy CVEs
Aug 16, 2026
046a793
ci(codeql): switch Go from build-mode none to manual, build both modules
Aug 16, 2026
1f8eb44
ci(nancy): ignore CVE-2026-56860 for x/net — already fixed upstream
Aug 16, 2026
46ffbd3
fix(server,frontend): allow inline styles for ApexCharts, fix donut l…
Aug 16, 2026
548ce98
Merge pull request #269 from Rem7474/claude/fix-apexcharts-csp-legend…
Rem7474 Aug 16, 2026
abe114f
perf(docker): cross-compile server image instead of emulating arm64
Aug 16, 2026
9184825
fix(frontend): stop losing ApexCharts formatter/tooltip functions on …
Aug 17, 2026
e084af9
Merge pull request #272 from Rem7474/claude/fix-apexcharts-formatter-…
Rem7474 Aug 17, 2026
c66960c
fix(frontend): theme ApexCharts tooltip chrome to match dark-only app…
Rem7474 Aug 17, 2026
88703c5
refactor(frontend): replace custom ApexCharts tooltip HTML with nativ…
Rem7474 Aug 17, 2026
077b6be
fix(frontend): keep ApexCharts plot background transparent (#275)
Rem7474 Aug 17, 2026
46b6065
fix(frontend): remove dead light-theme CSS in AlertRuleModal's step c…
Rem7474 Aug 17, 2026
dde1c21
fix(frontend): remove navbar/dropdown CSS overrides already covered b…
Rem7474 Aug 19, 2026
8d89ccd
fix(tasks): ad-hoc custom task run, optional action, live status refr…
Rem7474 Aug 23, 2026
4a14ea4
feat(proxmox): interactive LXC console (xterm.js over PVE termproxy) …
Rem7474 Aug 23, 2026
7bdebdb
docs: passe d'exactitude sur la doc avant la remontée dev → main (#287)
Rem7474 Aug 25, 2026
1c8e3ac
ci: add SonarCloud static analysis across all 3 modules (#295)
Rem7474 Aug 28, 2026
ca6f284
fix(proxmox): guest chart, mobile console/nav, and missing backup tas…
Rem7474 Aug 28, 2026
d006c11
docs(claude): document the dev→main release-PR branching flow (#296)
Rem7474 Aug 28, 2026
5ec7e93
ci(dependabot): target dev instead of main (#297)
Rem7474 Aug 28, 2026
01bbb49
ci: add secret scanning (TruffleHog) and make Trivy blocking (#293)
Rem7474 Aug 28, 2026
a0ddbf9
ci: also skip the SonarQube scan on Dependabot PRs (#306)
Rem7474 Aug 28, 2026
3558712
ci(dependabot): drop label references that don't exist in the repo (#…
Rem7474 Aug 28, 2026
dc0713c
ci(security): skip nancy on Dependabot PRs (#310)
Rem7474 Aug 28, 2026
4b7f0bb
ci(codeql): pick the Go version from whichever of server/agent needs …
Rem7474 Aug 28, 2026
2942ec2
ci: bump SonarSource/sonarqube-scan-action (#304)
dependabot[bot] Aug 28, 2026
f44b53c
chore(docker): bump golang from 1.26-alpine to 1.27-alpine in /server…
dependabot[bot] Aug 28, 2026
2e60b77
chore(frontend): bump axios from 1.18.1 to 1.19.0 in /frontend (#254)
dependabot[bot] Aug 28, 2026
3898144
chore(frontend): bump pinia from 3.0.4 to 4.0.3 in /frontend (#279)
dependabot[bot] Aug 28, 2026
8bd7ed7
chore(agent): bump the agent-minor-patch group across 1 directory wit…
dependabot[bot] Aug 28, 2026
10c8e11
chore(server): bump the server-minor-patch group across 1 directory w…
dependabot[bot] Aug 28, 2026
3bea495
fix(audit): SonarCloud findings — real fixes, false-positive triage, …
Rem7474 Aug 28, 2026
09780fc
chore(frontend): bump the frontend-prod-patch group across 1 director…
dependabot[bot] Aug 28, 2026
fdf236e
chore(frontend): bump the frontend-dev group across 1 directory with …
dependabot[bot] Aug 28, 2026
00e73a5
chore: add LICENSE (AGPLv3), SECURITY.md, and pull published image in…
Rem7474 Aug 28, 2026
b284526
docs: migrate docs/ to wiki/, auto-deployed to GitHub wiki (#294)
Rem7474 Aug 28, 2026
fbedd14
docs: add docker-compose.dev.yml to restore local-build for the root …
Rem7474 Aug 28, 2026
b05c8ac
docs(claude): remove PR-number citations from the branching bullet (#…
Rem7474 Aug 28, 2026
4939f63
docs: add a documentation-style rule to CLAUDE.md, sweep for narrativ…
Rem7474 Aug 28, 2026
09979af
ci(security): fix reproducible Trivy failures on the server image (#314)
Rem7474 Aug 28, 2026
9006dc8
fix(frontend): stop mutating form props in place across alert/setting…
Rem7474 Aug 29, 2026
7cda971
test(frontend): raise new-code Vitest coverage for the v11 release PR…
Rem7474 Aug 29, 2026
77d94e7
ci(frontend): re-enable real-browser tests in CI and wire their cover…
Rem7474 Aug 29, 2026
8c381ce
test(server): close v11 new-code coverage gaps in proxmox console + s…
Rem7474 Aug 29, 2026
6c08549
ci(security): suppress a false-positive nancy CVE on an unreachable m…
Rem7474 Aug 29, 2026
2818a19
test(frontend): cover HostCustomTasksTab for the v11 coverage gate (#…
Rem7474 Aug 29, 2026
fe1c0f6
docs: document test-quality-over-coverage-percentage as a standing ru…
Rem7474 Aug 29, 2026
4c2eb8b
feat(server): production readiness bootstrap, persistent jwt secret, …
Rem7474 Aug 29, 2026
a2a7505
fix(server): address findings from the dev→main release audit (#323)
Rem7474 Aug 30, 2026
0bd2a3f
test(frontend): close the remaining v11 coverage gaps (form setters, …
Rem7474 Aug 30, 2026
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
91 changes: 78 additions & 13 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@

SERVER_PORT=8080

# Docker image published by the release workflow (ghcr.io, multi-arch, cosign-signed).
# Pin SERVERSUPERVISOR_VERSION to a specific tag (e.g. v9.2.0) for a reproducible
# deployment instead of tracking "latest"; leave commented to use the default in
# docker-compose.yml.
# SERVERSUPERVISOR_IMAGE=ghcr.io/rem7474/serversupervisor
# SERVERSUPERVISOR_VERSION=latest

# Deployment environment. Set to "dev" or "development" for local work — the
# server will then auto-generate a JWT_SECRET when none is provided and skip
# the strict secret validation. Any other value (or unset) is treated as
Expand Down Expand Up @@ -75,10 +82,11 @@ DB_PASSWORD=your-secure-password-here
# Authentication
# ----------------------------------------

# REQUIRED in production. Generate with: openssl rand -hex 32
# Must be at least 32 characters. In APP_ENV=dev mode an ephemeral random
# secret is generated automatically when this var is unset.
JWT_SECRET=generate-a-random-long-secret-here
# Secret used to sign JWT tokens.
# Optional: if left empty, a secure random 64-character hex secret will be
# generated on first boot and persisted in the database settings table.
# To generate manually: openssl rand -hex 32
JWT_SECRET=

# JWT access token lifetime (default: 24h)
# Supported units: h (hours), m (minutes), s (seconds)
Expand All @@ -87,9 +95,13 @@ JWT_EXPIRATION=24h
# Refresh token lifetime (default: 168h = 7 days)
REFRESH_TOKEN_EXPIRATION=168h

# Default admin credentials (created on first startup)
# Default admin credentials (created on first startup if no user exists).
# - ADMIN_USER: username for initial account (default: admin).
# - ADMIN_PASSWORD: if left empty, a secure random 16-character password is
# generated at first boot and printed in `docker compose logs server`. You will
# be prompted to change it upon first login.
ADMIN_USER=admin
ADMIN_PASSWORD=your-admin-password
ADMIN_PASSWORD=

# ----------------------------------------
# Rate Limiting
Expand All @@ -101,6 +113,11 @@ RATE_LIMIT_RPS=100
# Maximum burst size per IP (default: 200)
RATE_LIMIT_BURST=200

# Same, for the /api/agent/* routes. Agents report on a fixed interval and
# must not be throttled like a browser.
AGENT_RATE_LIMIT_RPS=20
AGENT_RATE_LIMIT_BURST=40

# ----------------------------------------
# GitHub Release Tracking (optional)
# ----------------------------------------
Expand All @@ -123,10 +140,14 @@ DOCKER_IMAGE_POLL_INTERVAL=6h
# Alerts & Notifications (optional)
# ----------------------------------------

# Generic webhook URL for alert notifications (Discord, Slack, ntfy, custom...)
# Leave empty to disable webhook alerts.
# ntfy example: https://ntfy.sh/your-topic
# Discord example: https://discord.com/api/webhooks/...
# ntfy server base URL. Alert rules using the "ntfy" channel take the scheme
# and host from here; each rule can override the topic.
# Example: https://ntfy.sh/your-topic
#
# This URL is ALSO the target of the deprecated "notify" channel, which POSTs
# raw JSON to it. That payload matches no third-party schema in particular —
# it will not render correctly as a Discord or Slack webhook. A real
# Slack/Teams/Discord channel is ROADMAP.md item #6, not yet implemented.
NOTIFY_URL=

# SMTP configuration for email alerts
Expand All @@ -139,13 +160,26 @@ SMTP_FROM=serversupervisor@yourdomain.com
SMTP_TO=admin@yourdomain.com
SMTP_TLS=true

# ntfy auth token, for a protected topic. Leave empty for a public topic.
NTFY_AUTH_TOKEN=

# ----------------------------------------
# Metrics
# ----------------------------------------

# How many days to keep raw metrics (default: 30)
METRICS_RETENTION_DAYS=30

# How many days to keep audit log rows (default: 90). Can be refined per
# category from Settings only (audit_retention_days_by_category) — a
# per-category map doesn't fit a flat KEY=value env var.
AUDIT_RETENTION_DAYS=90

# How many days to keep web-log requests (default: 30) and network flows
# (default: 14). Both tables grow fast on a busy reverse proxy.
WEB_LOGS_RETENTION_DAYS=30
NETWORK_FLOWS_RETENTION_DAYS=14

# ----------------------------------------
# Backups (docker-compose "postgres-backup" service)
# ----------------------------------------
Expand All @@ -167,10 +201,12 @@ BACKUP_KEEP_MONTHS=6
# TLS/Security
# ----------------------------------------

# Enable TLS for the server (false if behind reverse proxy with TLS termination)
# NOTE: this does NOT make the server serve HTTPS — it only listens over
# plain HTTP and is meant to sit behind a TLS-terminating reverse proxy.
# TLS_ENABLED only forces the `Secure` flag on session cookies, so set it to
# true whenever the app is reached over https://, even (especially) when the
# proxy is the one terminating TLS.
TLS_ENABLED=false
# TLS_CERT_FILE=/etc/ssl/certs/server.pem
# TLS_KEY_FILE=/etc/ssl/private/server.key

# Extra allowed WebSocket origins (comma-separated)
# Use when the app is behind a reverse proxy with a different domain
Expand All @@ -179,6 +215,35 @@ TLS_ENABLED=false
# ALLOWED_ORIGINS=https://supervisor.yourdomain.com,https://backup.yourdomain.com
ALLOWED_ORIGINS=

# WebAuthn (passkeys / security keys). Both are derived from BASE_URL and
# ALLOWED_ORIGINS when left empty — only set them if the frontend genuinely
# isn't served from the API's own origin.
# WEBAUTHN_RP_ID=supervisor.yourdomain.com
# WEBAUTHN_RP_ORIGINS=https://supervisor.yourdomain.com

# ----------------------------------------
# Web-log threat scoring (optional)
# ----------------------------------------

# The threat score of an IP in the Traffic/Threats views is a weighted sum of
# signals. Defaults are calibrated for ordinary traffic — only touch these if
# the scoring is too noisy or too lax on yours. Full table in the README.
# THREAT_THRESHOLD_MEDIUM=15
# THREAT_THRESHOLD_HIGH=50
# THREAT_THRESHOLD_CRITICAL=150
# THREAT_WEIGHT_HITS=2
# THREAT_WEIGHT_BREADTH=3
# THREAT_WEIGHT_STATUS_404=2
# THREAT_WEIGHT_STATUS_4XX=1.5
# THREAT_WEIGHT_STATUS_5XX=3
# THREAT_WEIGHT_STATUS_3XX=1
# THREAT_WEIGHT_STATUS_2XX=0.1
# THREAT_WEIGHT_ADMIN_PANEL=3
# THREAT_WEIGHT_WORDPRESS=2
# THREAT_WEIGHT_PATH_TRAVERSAL=5
# THREAT_WEIGHT_SUSPICIOUS_METHOD=2
# THREAT_WEIGHT_KNOWN_SCANNER=4

# WebAuthn (passkeys / security keys, an additional MFA factor alongside TOTP).
# By default the Relying Party ID/origins are derived from BASE_URL/ALLOWED_ORIGINS
# above, which is correct for the vast majority of deployments (frontend served
Expand Down
10 changes: 6 additions & 4 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ updates:
# ── Actions GitHub ────────────────────────────────────────
- package-ecosystem: github-actions
directory: /
target-branch: dev
schedule:
interval: weekly
day: monday
Expand All @@ -13,7 +14,7 @@ updates:
prefix: "ci"
labels:
- dependencies
- github-actions
- ci
groups:
github-actions:
patterns:
Expand All @@ -22,6 +23,7 @@ updates:
# ── Go - Serveur ──────────────────────────────────────────
- package-ecosystem: gomod
directory: /server
target-branch: dev
schedule:
interval: weekly
day: monday
Expand All @@ -31,7 +33,6 @@ updates:
prefix: "chore(server)"
labels:
- dependencies
- go
- server
# Grouper les mises à jour mineures/patch ensemble
groups:
Expand All @@ -49,6 +50,7 @@ updates:
# ── Go - Agent ────────────────────────────────────────────
- package-ecosystem: gomod
directory: /agent
target-branch: dev
schedule:
interval: weekly
day: monday
Expand All @@ -58,7 +60,6 @@ updates:
prefix: "chore(agent)"
labels:
- dependencies
- go
- agent
groups:
agent-minor-patch:
Expand All @@ -73,6 +74,7 @@ updates:
# ── npm - Frontend ────────────────────────────────────────
- package-ecosystem: npm
directory: /frontend
target-branch: dev
schedule:
interval: weekly
day: tuesday # décalé pour éviter trop de PRs le même jour
Expand All @@ -82,7 +84,6 @@ updates:
prefix: "chore(frontend)"
labels:
- dependencies
- javascript
- frontend
# Grouper toutes les devDependencies ensemble
groups:
Expand Down Expand Up @@ -111,6 +112,7 @@ updates:
# ── Docker - images de base ───────────────────────────────────
- package-ecosystem: docker
directory: /server
target-branch: dev
schedule:
interval: weekly
day: wednesday
Expand Down
2 changes: 1 addition & 1 deletion .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ documentation:
- changed-files:
- any-glob-to-any-file:
- '*.md'
- 'docs/**'
- 'wiki/**'

database:
- changed-files:
Expand Down
28 changes: 20 additions & 8 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,32 @@ lint bloquant (`agent/.golangci.yml`).
### CI Frontend (`ci-frontend.yml`) — push/PR sur `frontend/**`

- Job `quality` : `npm ci` → lint → typecheck → **tests unitaires/composants
(`npm run test`, Vitest)** → build de production
- Les tests navigateur (`npm run test:browser`, Playwright/Chromium, rendu
Chart.js / D3) **ne sont pas exécutés en CI** pour l'instant : bug amont de
l'optimiseur de deps Vite 8 (rolldown) en mode browser Vitest 4 (voir
`vitest.browser.config.ts`). À lancer en local ; rajouter un job
`browser-tests` une fois le correctif amont disponible.
(`npm run test`, Vitest, happy-dom)** → build de production
- Job `browser-tests` : `npm ci` → installation de Playwright/Chromium →
**tests navigateur réels (`npm run test:browser`)**, pour tout ce qui
dépend d'un rendu effectif (ApexCharts SVG, carte du monde D3) que
happy-dom ne peut pas exécuter.

### Security (`security.yml`) — lundi 6h UTC + push sur les manifests + manuel
### Security (`security.yml`) — lundi 6h UTC + push/PR sur les manifests + manuel

Scanners de dépendances/image — ne se déclenchent que quand un manifest
(`go.mod`/`go.sum`/`package.json`/`package-lock.json`/`Dockerfile`) change,
en push sur `main` **et** sur PR (pour bloquer une dépendance vulnérable
avant le merge, pas après).

- `govulncheck` (server + agent), version épinglée — **bloquant**
- `nancy` (CVE des deps Go, server + agent) — **bloquant**
- `npm audit --audit-level=moderate` (frontend) — **bloquant**
- Trivy sur l'image server (SARIF → onglet Security) — informatif
- CodeQL (`go`, `javascript`, `security-extended`)

### CodeQL (`codeql.yml`) — lundi 6h UTC + push/PR sur `server|agent|frontend/**` + manuel

Scan du code source lui-même (`go`, `javascript`, `security-extended`) —
volontairement dans son **propre** workflow, pas dans `security.yml` :
contrairement aux scanners de dépendances ci-dessus, CodeQL doit tourner sur
tout changement de code (injection SQL, XSS, etc.), pas seulement quand un
manifest bouge — sans pour autant faire tourner govulncheck/nancy/trivy sur
chaque commit de code.

### Release (`release.yml`) — tags `vX.Y.Z[-pre]`

Expand Down
33 changes: 26 additions & 7 deletions .github/workflows/ci-frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,29 @@ jobs:
env:
NODE_ENV: production

# NOTE: the real-browser tests (`npm run test:browser`, Playwright/Chromium) are
# intentionally NOT run in CI yet. An upstream Vite 8 (rolldown) + Vitest 4
# browser-mode dep-optimizer bug breaks them (`init_shared_esm_bundler is not
# defined` at import; or a double Vue instance when worked around). See
# vitest.browser.config.ts for the full diagnosis. Run them locally with:
# cd frontend && npx playwright install --with-deps chromium && npm run test:browser
# Re-add a `browser-tests` job here once the upstream optimizer bug is fixed.
browser-tests:
name: Real-browser tests
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./frontend

steps:
- name: Checkout code
uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: '22'
cache: npm
cache-dependency-path: frontend/package-lock.json

- name: Install dependencies
run: npm ci --no-audit

- name: Install Playwright Chromium
run: npx playwright install --with-deps chromium

- name: Real-browser tests
run: npm run test:browser
Loading
Loading