diff --git a/CHANGELOG.md b/CHANGELOG.md
index 83a41406..af7a20ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- feat: CI job to auto-refresh doc screenshots on every develop push
- docs: bootstrap user-facing documentation from codebase audit — added configuration, stack management, editor, multi-node, and alerts & notifications pages; updated introduction, quickstart, and features overview; restructured mint.json navigation with Getting Started / Features / Reference / Operations groups
- docs: add Tier 2 feature pages — dashboard, resources hub, app store, global observability, and host console
+- docs: add Tier 3 reference and operations pages — settings reference, troubleshooting, and backup & restore
### Fixed
- fix(ci): YAML syntax error in update-screenshots `if:` condition (`!` tag and `: ` in plain scalar); wrapped in `${{ }}`
diff --git a/docs/mint.json b/docs/mint.json
index e986e350..ba9fa041 100644
--- a/docs/mint.json
+++ b/docs/mint.json
@@ -37,11 +37,16 @@
},
{
"group": "Reference",
- "pages": []
+ "pages": [
+ "reference/settings"
+ ]
},
{
"group": "Operations",
- "pages": []
+ "pages": [
+ "operations/troubleshooting",
+ "operations/backup"
+ ]
}
]
}
diff --git a/docs/operations/backup.mdx b/docs/operations/backup.mdx
new file mode 100644
index 00000000..a42041cf
--- /dev/null
+++ b/docs/operations/backup.mdx
@@ -0,0 +1,139 @@
+---
+title: Backup & Restore
+description: What to back up, how to restore it, and how to migrate Sencho to a new host.
+---
+
+Sencho stores all its state in two places: the **data directory** (SQLite database) and your **compose directory** (your actual stack files). Both need to be backed up for a complete recovery.
+
+---
+
+## What to back up
+
+### 1. Data directory (`DATA_DIR`)
+
+Default path: `/app/data` inside the container, mapped to wherever you mounted it on the host (e.g. `./sencho-data`).
+
+Contains:
+- `sencho.db` — SQLite database with all settings, nodes, alerts, metrics history, and notification history
+
+This single file is everything Sencho knows about itself. Back it up and you can fully restore any Sencho installation.
+
+### 2. Compose directory (`COMPOSE_DIR`)
+
+The directory containing your stack subdirectories — your `compose.yaml` files, `.env` files, and any bind-mounted config files stored there.
+
+This is your actual application data. It lives entirely outside Sencho and you almost certainly already have it on a schedule, but include it in any Sencho backup plan.
+
+---
+
+## Backing up
+
+### Simple file copy
+
+```bash
+# Stop Sencho to ensure the SQLite WAL is flushed (recommended but not strictly required)
+docker stop sencho
+
+# Copy the data directory
+cp -r /path/to/sencho-data /path/to/backup/sencho-data-$(date +%Y%m%d)
+
+# Copy compose stacks
+cp -r /opt/compose /path/to/backup/compose-$(date +%Y%m%d)
+
+# Restart
+docker start sencho
+```
+
+### SQLite online backup (without stopping)
+
+SQLite supports hot backups via its `.backup` command. This is safe to run while Sencho is running:
+
+```bash
+sqlite3 /path/to/sencho-data/sencho.db ".backup '/path/to/backup/sencho.db'"
+```
+
+### Automated daily backup (cron example)
+
+```cron
+0 3 * * * sqlite3 /path/to/sencho-data/sencho.db ".backup '/backups/sencho-$(date +\%Y\%m\%d).db'" && find /backups -name "sencho-*.db" -mtime +30 -delete
+```
+
+This backs up the database at 3 AM daily and deletes backups older than 30 days.
+
+---
+
+## Restoring
+
+### Restore from backup
+
+1. Stop Sencho:
+ ```bash
+ docker stop sencho
+ ```
+
+2. Replace the data directory with your backup:
+ ```bash
+ rm -rf /path/to/sencho-data/*
+ cp /path/to/backup/sencho.db /path/to/sencho-data/sencho.db
+ ```
+
+3. Restore your compose directory if needed:
+ ```bash
+ cp -r /path/to/backup/compose /opt/compose
+ ```
+
+4. Start Sencho:
+ ```bash
+ docker start sencho
+ ```
+
+Sencho will read the restored database and resume with all your previous settings, nodes, and alert rules intact.
+
+---
+
+## Migrating to a new host
+
+### Step 1: Prepare the new host
+
+Install Docker and Docker Compose on the new machine. Create the same directory structure you use for your compose files, following the [1:1 path rule](/getting-started/configuration#compose-directory-the-11-path-rule).
+
+### Step 2: Copy data
+
+Transfer your backup files to the new host:
+
+```bash
+scp -r /path/to/sencho-data newhost:/path/to/sencho-data
+scp -r /opt/compose newhost:/opt/compose
+```
+
+### Step 3: Deploy Sencho on the new host
+
+Use the same `docker-compose.yml` you used on the old host (with the same `COMPOSE_DIR` and `DATA_DIR` paths):
+
+```bash
+docker compose up -d
+```
+
+### Step 4: Update remote node references
+
+If other Sencho instances were pointing to your old host as a remote node, update their node config to use the new host's IP or hostname. Generate a new API token on the restored instance and distribute it.
+
+### Step 5: Verify
+
+- Log in and confirm your stacks, nodes, and alerts are all present
+- Check that at least one stack deploys correctly
+- Verify the node switcher shows the expected nodes with green status
+
+---
+
+## What is NOT backed up by this process
+
+| Item | Location | Notes |
+|------|----------|-------|
+| Container data volumes | Wherever each stack's volumes are mounted on the host | Back these up separately per-application |
+| Actual container images | Docker image cache | These are re-pulled on next deploy — no backup needed |
+| Sencho logs (docker logs) | Container stdout | Not persisted beyond container lifetime |
+
+
+ Sencho does not currently have a built-in backup scheduler or export function. The approaches above use standard OS tools and SQLite's own backup mechanism.
+
diff --git a/docs/operations/troubleshooting.mdx b/docs/operations/troubleshooting.mdx
new file mode 100644
index 00000000..8a1feb1d
--- /dev/null
+++ b/docs/operations/troubleshooting.mdx
@@ -0,0 +1,163 @@
+---
+title: Troubleshooting
+description: Solutions to the most common Sencho setup and runtime problems.
+---
+
+## Containers won't start after deploy
+
+**Symptom:** You click Deploy and containers immediately exit or never appear.
+
+**Check:** Open the [Host Console](/features/host-console) and run:
+
+```bash
+docker compose -f /path/to/your/stack/compose.yaml logs
+```
+
+The most common causes:
+
+- **Missing environment variable** — a required variable in your `.env` file is empty or has the wrong name.
+- **Port already in use** — another container or host process is bound to the same port. Change the host port in the compose file.
+- **Volume path does not exist** — a bind-mount path on the host doesn't exist yet. Create the directory manually.
+
+---
+
+## The 1:1 path rule — volumes resolve to wrong paths
+
+**Symptom:** Stacks deploy but relative volume paths (e.g. `./config:/config`) point to the wrong location inside the container, or `docker compose` exits with a path error.
+
+**Cause:** Your `COMPOSE_DIR` is mounted at a different path inside the Sencho container than it has on the host.
+
+**Fix:** Your compose volume mount and `COMPOSE_DIR` environment variable must use the **same absolute path** on both sides:
+
+```yaml
+# docker-compose.yml for Sencho itself
+volumes:
+ - /opt/docker:/opt/docker # same path inside and outside
+environment:
+ - COMPOSE_DIR=/opt/docker
+```
+
+See [Configuration — the 1:1 path rule](/getting-started/configuration#compose-directory-the-11-path-rule) for a full explanation.
+
+---
+
+## "Permission denied" on the Docker socket
+
+**Symptom:** Sencho starts but shows errors accessing Docker, or the stack list is empty even though containers exist.
+
+**Cause:** The Sencho container cannot read `/var/run/docker.sock`.
+
+**Fix:** Ensure the socket is mounted:
+
+```yaml
+volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+```
+
+On Linux, the Docker socket is owned by the `docker` group. The Sencho entrypoint detects the socket's GID automatically and adds the internal `sencho` user to the matching group. If you see permission errors despite a correct mount, check that the socket file is readable:
+
+```bash
+ls -la /var/run/docker.sock
+# Expected: srw-rw---- 1 root docker ...
+```
+
+If the group is not `docker`, the auto-detection still works — Sencho reads the GID from the socket file at startup.
+
+---
+
+## Login page shows "Something went wrong"
+
+**Symptom:** You enter credentials and get a generic error instead of being logged in.
+
+**Possible causes and fixes:**
+
+| Cause | Fix |
+|-------|-----|
+| `JWT_SECRET` is not set or is empty | Set a non-empty value for `JWT_SECRET` in your environment |
+| Container restarted and session cookie is stale | Clear browser cookies for the Sencho domain and try again |
+| Rate limit triggered (5 failed attempts in 15 min) | Wait 15 minutes, or restart the container to reset the limiter |
+
+---
+
+## WebSocket connections fail (logs/console not streaming)
+
+**Symptom:** The log viewer or host console shows a spinner that never resolves, or you see "Disconnected" immediately after connecting.
+
+**Cause:** A reverse proxy is not forwarding WebSocket upgrade headers.
+
+**Fix:** Add WebSocket support to your proxy config:
+
+```nginx
+# Nginx
+proxy_http_version 1.1;
+proxy_set_header Upgrade $http_upgrade;
+proxy_set_header Connection "upgrade";
+proxy_read_timeout 3600s;
+```
+
+Traefik handles WebSocket upgrades automatically for HTTP/1.1 backends — no extra config needed.
+
+---
+
+## Remote node shows "Offline" or "Unknown"
+
+**Symptom:** A node you added shows a red or gray status dot.
+
+**Checks in order:**
+
+1. **Is the remote Sencho instance running?** SSH to that machine and verify.
+2. **Is the API URL correct?** It must include the protocol and port (e.g. `http://192.168.1.20:3001`). Open it in a browser — you should see a JSON response from `/api/health`.
+3. **Is the token correct?** Tokens are long JWT strings. Even one missing character will cause auth to fail. Regenerate the token on the remote instance and update the node config.
+4. **Is there a firewall blocking the port?** The primary Sencho host must be able to reach the remote host's Sencho port.
+
+Click the **wifi icon** on the node row to re-test connectivity after making changes.
+
+---
+
+## Forgotten admin password
+
+Sencho has no password recovery flow. To reset the password:
+
+1. Stop the Sencho container
+2. Connect to the SQLite database directly:
+
+```bash
+sqlite3 /path/to/data/sencho.db
+```
+
+3. Delete the existing credentials so Sencho re-enters first-boot setup mode:
+
+```sql
+DELETE FROM global_settings WHERE key IN ('auth_username', 'auth_password_hash', 'auth_jwt_secret');
+```
+
+4. Restart the container — the setup screen will appear on next visit.
+
+
+ This resets authentication entirely. All active sessions become invalid. Your stacks, nodes, and alert rules are not affected.
+
+
+---
+
+## Checking the health endpoint
+
+Sencho exposes a health endpoint for monitoring and container health checks:
+
+```bash
+curl http://localhost:3000/api/health
+# {"status":"ok","uptime":12345.67}
+```
+
+A `200` response confirms the backend is running. Use this endpoint in your uptime monitor or load balancer health check.
+
+---
+
+## Getting logs from the Sencho container itself
+
+```bash
+docker logs sencho
+# or, to follow:
+docker logs -f sencho
+```
+
+The backend logs all route errors and service failures to stdout. This is the first place to look when the UI shows an error with no useful message.
diff --git a/docs/reference/settings.mdx b/docs/reference/settings.mdx
new file mode 100644
index 00000000..9ca2c9b7
--- /dev/null
+++ b/docs/reference/settings.mdx
@@ -0,0 +1,126 @@
+---
+title: Settings Reference
+description: Complete reference for every option in the Sencho Settings Hub.
+---
+
+Open the Settings Hub by clicking **Settings** in the top navigation bar. The left sidebar lists all available sections.
+
+
+
+
+
+---
+
+## Account
+
+**Scope:** Global (applies to this Sencho instance, not per-node)
+
+Change the admin account password. All three fields are required.
+
+| Field | Description |
+|-------|-------------|
+| **Current Password** | Your existing password for verification |
+| **New Password** | Must be at least 6 characters |
+| **Confirm New Password** | Must match New Password |
+
+Click **Update Password** to apply. The change takes effect immediately; existing sessions remain valid.
+
+---
+
+## System Limits
+
+**Scope:** Per-node (applies to the currently selected node)
+
+Configure resource thresholds that trigger visual warnings on the dashboard stat cards. These are display thresholds only — Sencho does not throttle or kill containers when limits are reached.
+
+| Setting | Range | Description |
+|---------|-------|-------------|
+| **Host CPU Limit** | 1–100% | CPU percentage above which the CPU card turns orange/red |
+| **Host RAM Limit** | 1–100% | RAM percentage above which the RAM card turns orange/red |
+| **Host Disk Limit** | 1–100% | Disk percentage above which the Disk card turns orange/red |
+| **Docker Janitor Threshold** | ≥ 0 GB | Minimum free disk space to maintain. When free space falls below this value, a warning is shown. Set to `0` to disable. |
+| **Global Crash Alerts** | On / Off | When enabled, Sencho sends a notification whenever any managed container exits unexpectedly |
+
+Click **Save** to apply. An unsaved-changes indicator appears when you have edits pending.
+
+---
+
+## Notifications
+
+**Scope:** Global
+
+Configure external destinations for alert notifications. Three agent types are supported, each on its own sub-tab: **Discord**, **Slack**, and **Webhook**.
+
+For each agent:
+
+| Field | Description |
+|-------|-------------|
+| **Enable toggle** | Activates or deactivates this agent. Disabled agents receive no messages even if a URL is saved. |
+| **Webhook URL** | The endpoint Sencho will POST to when an alert fires |
+
+Click **Save** to persist changes. Click **Test** to send a test payload immediately and verify delivery.
+
+At least one agent must be enabled for stack alerts to deliver notifications. See [Alerts & Notifications](/features/alerts-notifications) for how to create alert rules.
+
+---
+
+## Appearance
+
+**Scope:** Global (stored in the browser, not the server)
+
+| Setting | Options | Description |
+|---------|---------|-------------|
+| **Theme** | Light / Dark / Auto | `Auto` follows the OS system preference. Changes apply immediately without a page reload. |
+
+---
+
+## Developer
+
+**Scope:** Per-node (applies to the currently selected node)
+
+Advanced settings for log streaming behaviour and data retention. Most users can leave these at their defaults.
+
+| Setting | Default | Description |
+|---------|---------|-------------|
+| **Developer Mode** | Off | When on, the [Global Observability](/features/global-observability) view switches from polling to real-time Server-Sent Events streaming |
+| **Global Logs Refresh Rate** | 5s | Polling interval in standard mode. Options: `1s`, `3s`, `5s`, `10s` |
+| **Metrics Retention Hours** | 24 | How many hours of CPU/RAM history to keep for dashboard charts. Max: 8,760 (1 year) |
+| **Log Retention Days** | 30 | How many days of notification history to keep in the database. Max: 365 |
+
+Click **Save** to apply.
+
+
+ Lower refresh rates (1s) increase backend CPU usage as Sencho polls Docker more frequently. Use only when actively debugging.
+
+
+---
+
+## Nodes
+
+**Scope:** Global
+
+Manage connections to local and remote Sencho instances. This is the same interface as the [Multi-Node](/features/multi-node) feature — see that page for the full walkthrough.
+
+Quick reference:
+
+| Action | How |
+|--------|-----|
+| Add a remote node | Click **+ Add Node** |
+| Generate a token for this instance | Click **Generate Token** |
+| Test an existing node's connectivity | Click the wifi icon on any row |
+| Edit a node | Click the pencil icon |
+| Delete a node | Click the trash icon (remote nodes only) |
+
+---
+
+## App Store
+
+**Scope:** Global
+
+| Setting | Default | Description |
+|---------|---------|-------------|
+| **Template Registry URL** | LinuxServer.io registry | The URL Sencho fetches templates from. Must return a JSON array in Portainer v2 template format. Leave blank to restore the default. |
+
+Click **Save** to update the URL. Click **Refresh Cache** to clear the cached template list and fetch fresh data from the registry immediately.
+
+See [App Store](/features/app-store#custom-template-registry) for more on custom registries.